提交 82cbaa09 编写于 作者: T Terry

更改支付流程

上级 398f3294
......@@ -35,6 +35,7 @@ class Placeorder
public function getLastData()
{
$post = Yii::$app->request->post();
if (is_array($post) && !empty($post)) {
/**
* 对传递的数据,去除掉非法xss攻击部分内容(通过\Yii::$service->helper->htmlEncode()).
......@@ -42,6 +43,7 @@ class Placeorder
$post = \Yii::$service->helper->htmlEncode($post);
// 检查前台传递的数据的完整
if ($this->checkOrderInfoAndInit($post)) {
// 如果游客用户勾选了注册账号,则注册,登录,并把地址写入到用户的address中
$gus_status = $this->guestCreateAndLoginAccount($post);
$save_address_status = $this->updateAddress($post);
......@@ -53,17 +55,21 @@ class Placeorder
$checkout_type = $serviceOrder::CHECKOUT_TYPE_STANDARD;
$serviceOrder->setCheckoutType($checkout_type);
// 将购物车数据,生成订单。
$innerTransaction = Yii::$app->db->beginTransaction();
try {
$genarateStatus = Yii::$service->order->generateOrderByCart($this->_billing, $this->_shipping_method, $this->_payment_method);
# 生成订单,扣除库存,但是,不清空购物车。
$genarateStatus = Yii::$service->order->generateOrderByCart($this->_billing, $this->_shipping_method, $this->_payment_method,false);
if ($genarateStatus) {
// 得到当前的订单信息
//$orderInfo = Yii::$service->order->getCurrentOrderInfo();
// 发送新订单邮件
//Yii::$service->email->order->sendCreateEmail($orderInfo);
// 得到支付跳转前的准备页面。
$startUrl = Yii::$service->payment->getStandardStartUrl();
$innerTransaction->commit();
//echo $startUrl;exit;
Yii::$service->url->redirect($startUrl);
return true;
......@@ -73,6 +79,7 @@ class Placeorder
} catch (Exception $e) {
$innerTransaction->rollBack();
}
}
} else {
}
......
......@@ -35,6 +35,11 @@ class Placeorder
public function getLastData()
{
$post = Yii::$app->request->post();
$token = Yii::$app->request->get('token');
if(!$token){
Yii::$service->helper->errors->add('token can not empty');
return false;
}
if (is_array($post) && !empty($post)) {
$post = \Yii::$service->helper->htmlEncode($post);
// 设置paypal快捷支付
......@@ -54,7 +59,7 @@ class Placeorder
// 将购物车数据,生成订单,生成订单后,不清空购物车,不扣除库存,在支付成功后在清空购物车。
$innerTransaction = Yii::$app->db->beginTransaction();
try {
$genarateStatus = Yii::$service->order->generateOrderByCart($this->_billing, $this->_shipping_method, $this->_payment_method, false);
$genarateStatus = Yii::$service->order->generateOrderByCart($this->_billing, $this->_shipping_method, $this->_payment_method, false,$token);
if ($genarateStatus) {
$innerTransaction->commit();
} else {
......@@ -66,10 +71,10 @@ class Placeorder
//echo 22;
if ($genarateStatus) {
// 得到当前的订单信息
$doExpressCheckoutReturn = $this->doExpressCheckoutPayment();
$doExpressCheckoutReturn = $this->doExpressCheckoutPayment($token);
//echo 333;
if ($doExpressCheckoutReturn) {
$ExpressOrderPayment = Yii::$service->payment->paypal->updateExpressOrderPayment($doExpressCheckoutReturn);
$ExpressOrderPayment = Yii::$service->payment->paypal->updateExpressOrderPayment($doExpressCheckoutReturn,$token);
// 如果支付成功,并把信息更新到了订单数据中,则进行下面的操作。
//echo 444;
if ($ExpressOrderPayment) {
......@@ -107,10 +112,10 @@ class Placeorder
return false;
}
public function doExpressCheckoutPayment()
public function doExpressCheckoutPayment($token)
{
$methodName_ = 'DoExpressCheckoutPayment';
$nvpStr_ = Yii::$service->payment->paypal->getExpressCheckoutPaymentNvpStr();
$nvpStr_ = Yii::$service->payment->paypal->getExpressCheckoutPaymentNvpStr($token);
//echo $nvpStr_;exit;
$DoExpressCheckoutReturn = Yii::$service->payment->paypal->PPHttpPost5($methodName_, $nvpStr_);
//var_dump($DoExpressCheckoutReturn);
......
......@@ -424,14 +424,14 @@ class Review
public function expressReview()
{
$setTokenStatus = Yii::$service->payment->paypal->setExpressToken();
$setPayerIDStatus = Yii::$service->payment->paypal->setExpressPayerID();
if (!$setTokenStatus) {
$getToken = Yii::$service->payment->paypal->getExpressToken();
$getPayerID = Yii::$service->payment->paypal->getExpressPayerID();
if (!$getToken) {
Yii::$service->page->message->AddError('paypal express token is empty');
return [];
}
if (!$setPayerIDStatus) {
if (!$getPayerID) {
Yii::$service->page->message->AddError('paypal express PayerID is empty');
return [];
......
......@@ -17,8 +17,14 @@ use Yii;
*/
class Start
{
public function startExpress()
{
$checkStatus = $this->checkStockQty();
if(!$checkStatus){
return;
}
$methodName_ = 'SetExpressCheckout';
$nvpStr_ = Yii::$service->payment->paypal->getExpressTokenNvpStr();
//echo $nvpStr_;exit;
......@@ -26,18 +32,45 @@ class Start
//var_dump($SetExpressCheckoutReturn);
if (strtolower($SetExpressCheckoutReturn['ACK']) == 'success') {
$token = $SetExpressCheckoutReturn['TOKEN'];
$redirectUrl = Yii::$service->payment->paypal->getSetExpressCheckoutUrl($token);
Yii::$service->url->redirect($redirectUrl);
exit;
# 生成订单,订单中只有id,increment_id,token 三个字段有值。
if($token){
if(!Yii::$service->order->generatePPExpressOrder($token)){
return false;
}
$redirectUrl = Yii::$service->payment->paypal->getSetExpressCheckoutUrl($token);
return Yii::$service->url->redirect($redirectUrl);
}
} elseif (strtolower($SetExpressCheckoutReturn['ACK']) == 'failure') {
echo $SetExpressCheckoutReturn['L_LONGMESSAGE0'];
} else {
var_dump($SetExpressCheckoutReturn);
}
}
// 首先验证购物车中是否存在产品
//public function validateCart(){
//}
// 检查购物车中产品的库存。此步只是初步检查,在快捷支付完成返回网站的时候,生成订单的时候,还要进一步检查产品库存,
// 因为在支付的过程中,产品可能被买走。
public function checkStockQty(){
$stockCheck = Yii::$service->product->stock->checkItemsQty();
//var_dump($stockCheck);exit;
if(!$stockCheck){
Yii::$service->url->redirectByUrlKey('checkout/cart');
return false;
}else{
if(isset($stockCheck['stockStatus'])){
if($stockCheck['stockStatus'] == 2){
$outStockProducts = $stockCheck['outStockProducts'];
if(is_array($outStockProducts) && !empty($outStockProducts)){
foreach($outStockProducts as $outStockProduct){
$product_name = Yii::$service->store->getStoreAttrVal($outStockProduct['product_name'], 'name');
Yii::$service->helper->errors->add('product: ['.$product_name.'] is stock out.');
}
Yii::$service->page->message->addByHelperErrors();
Yii::$service->url->redirectByUrlKey('checkout/cart');
return false;
}
}
}
}
return true;
}
}
<?php
/**
* FecShop file.
*
* @link http://www.fecshop.com/
* @copyright Copyright (c) 2016 FecShop Software LLC
* @license http://www.fecshop.com/license/
*/
namespace fecshop\app\appfront\modules\Payment\block\paypal\standard;
use Yii;
/**
* @author Terry Zhao <2358269014@qq.com>
* @since 1.0
*/
class Placeorder
{
/**
* 用户的账单地址信息,通过用户传递的信息计算而来。
*/
public $_billing;
public $_address_id;
/**
* 用户的货运方式.
*/
public $_shipping_method;
/**
* 用户的支付方式.
*/
public $_payment_method;
public function getLastData()
{
$token = Yii::$app->request->get('token');
if(!$token){
Yii::$service->helper->errors->add('token can not empty');
return false;
}
//echo '33'.'<br>';
echo $token.'<br>';
// 得到当前的订单信息
$doExpressCheckoutReturn = $this->doExpressCheckoutPayment($token);
if ($doExpressCheckoutReturn) {
//var_dump($doExpressCheckoutReturn);
$ExpressOrderPayment = Yii::$service->payment->paypal->updateExpressOrderPayment($doExpressCheckoutReturn,$token);
// 如果支付成功,并把信息更新到了订单数据中,则进行下面的操作。
//echo 444;
//var_dump($ExpressOrderPayment);
if ($ExpressOrderPayment) {
//echo 55;
// 支付成功后,在清空购物车数据。而不是在生成订单的时候。
Yii::$service->cart->clearCartProductAndCoupon();
// (删除)支付成功后,扣除库存。
// (删除)Yii::$service->product->stock->deduct();
// echo 555;
// 发送新订单邮件
// 扣除库存和优惠券
// 在生成订单的时候已经扣除了。参看order service GenerateOrderByCart() function
// 得到支付跳转前的准备页面。
$paypal_standard = Yii::$service->payment->paypal->standard_payment_method;
//echo '<br>';
//echo $paypal_standard;
$successRedirectUrl = Yii::$service->payment->getStandardSuccessRedirectUrl($paypal_standard);
//echo '<br>';
//echo $successRedirectUrl;
Yii::$service->url->redirect($successRedirectUrl);
return true;
}
}else{
Yii::$service->url->redirectByUrlKey('checkout/onepage');
}
// 如果订单支付过程中失败,将订单取消掉
if (!$doExpressCheckoutReturn || !$ExpressOrderPayment) {
Yii::$service->order->cancel();
}
Yii::$service->page->message->addByHelperErrors();
return false;
}
public function doExpressCheckoutPayment($token)
{
$methodName_ = 'DoExpressCheckoutPayment';
$nvpStr_ = Yii::$service->payment->paypal->getExpressCheckoutPaymentNvpStr($token);
//echo '<br/>nvpStr_:<br/>"'.$nvpStr_.'<br/><br/>';
$DoExpressCheckoutReturn = Yii::$service->payment->paypal->PPHttpPost5($methodName_, $nvpStr_);
//echo '<br/>DoExpressCheckoutReturn <br/><br/>';
//var_dump($DoExpressCheckoutReturn);
//echo '<br/>DoExpressCheckoutReturn <br/><br/>';
//exit;
if (strstr(strtolower($DoExpressCheckoutReturn['ACK']), 'success')) {
return $DoExpressCheckoutReturn;
} else {
if ($DoExpressCheckoutReturn['ACK'] == 'Failure') {
$message = $DoExpressCheckoutReturn['L_LONGMESSAGE0'];
// 添加报错信息。
//Message::error($message);
Yii::$service->helper->errors->add($message);
} else {
Yii::$service->helper->errors->add('paypal express payment error.');
}
return false;
}
}
/**
* @property $post | Array
* 登录用户,保存货运地址到customer address ,然后把生成的
* address_id 写入到cart中。
* shipping method写入到cart中
* payment method 写入到cart中 updateCart
*/
public function updateAddress($post)
{
return Yii::$service->cart->updateGuestCart($this->_billing, $this->_shipping_method, $this->_payment_method);
}
/**
* 如果是游客,那么保存货运地址到购物车表。
*/
/*
public function updateCart(){
if(Yii::$app->user->isGuest){
return Yii::$service->cart->updateGuestCart($this->_billing,$this->_shipping_method,$this->_payment_method);
}else{
return Yii::$service->cart->updateLoginCart($this->_address_id,$this->_shipping_method,$this->_payment_method);
}
}
*/
/**
* @property $post | Array
* @return bool
* 检查前台传递的信息是否正确。同时初始化一部分类变量
*/
public function checkOrderInfoAndInit($post)
{
$address_one = '';
$billing = isset($post['billing']) ? $post['billing'] : '';
if (!Yii::$service->order->checkRequiredAddressAttr($billing)) {
return false;
}
$this->_billing = $billing;
$shipping_method = isset($post['shipping_method']) ? $post['shipping_method'] : '';
$payment_method = isset($post['payment_method']) ? $post['payment_method'] : '';
// 验证货运方式
if (!$shipping_method) {
Yii::$service->helper->errors->add('shipping method can not empty');
return false;
} else {
if (!Yii::$service->shipping->ifIsCorrect($shipping_method)) {
Yii::$service->helper->errors->add('shipping method is not correct');
return false;
}
}
$this->_shipping_method = $shipping_method;
$this->_payment_method = $payment_method;
Yii::$service->payment->setPaymentMethod($this->_payment_method);
return true;
}
}
......@@ -17,6 +17,31 @@ use Yii;
*/
class Start
{
public function startExpress()
{
$methodName_ = 'SetExpressCheckout';
$nvpStr_ = Yii::$service->payment->paypal->getStandardTokenNvpStr();
//echo $nvpStr_;exit;
// 通过接口,得到token信息
$SetExpressCheckoutReturn = Yii::$service->payment->paypal->PPHttpPost5($methodName_, $nvpStr_);
//var_dump($SetExpressCheckoutReturn);
if (strtolower($SetExpressCheckoutReturn['ACK']) == 'success') {
$token = $SetExpressCheckoutReturn['TOKEN'];
$increment_id = Yii::$service->order->getSessionIncrementId();
# 将token写入到订单中
Yii::$service->order->updateTokenByIncrementId($increment_id,$token);
$redirectUrl = Yii::$service->payment->paypal->getSetStandardCheckoutUrl($token);
Yii::$service->url->redirect($redirectUrl);
return;
} elseif (strtolower($SetExpressCheckoutReturn['ACK']) == 'failure') {
echo $SetExpressCheckoutReturn['L_LONGMESSAGE0'];
} else {
var_dump($SetExpressCheckoutReturn);
}
}
/*
public function getLastData()
{
$loaderImg = Yii::$service->image->getImgUrl('images/loader.gif', 'appfront');
......@@ -133,4 +158,5 @@ class Start
return $str;
}
*/
}
......@@ -42,4 +42,21 @@ class ExpressController extends AppfrontController
return $data;
}
}
public function actionIpn()
{
\Yii::info('paypal ipn begin', 'fecshop_debug');
$post = Yii::$app->request->post();
if (is_array($post) && !empty($post)) {
$post = \Yii::$service->helper->htmlEncode($post);
ob_start();
ob_implicit_flush(false);
var_dump($post);
$post_log = ob_get_clean();
\Yii::info($post_log, 'fecshop_debug');
//Yii::$service->payment->paypal->receiveIpn($post);
}
}
}
......@@ -18,6 +18,47 @@ use Yii;
*/
class StandardController extends AppfrontController
{
public $enableCsrfValidation = true;
public function actionStart()
{
return $this->getBlock()->startExpress();
}
// 2.Review 从paypal确认后返回
public function actionReview()
{
$this->getBlock('placeorder')->getLastData();
}
public function actionIpn()
{
\Yii::info('paypal ipn begin', 'fecshop_debug');
$post = Yii::$app->request->post();
if (is_array($post) && !empty($post)) {
$post = \Yii::$service->helper->htmlEncode($post);
ob_start();
ob_implicit_flush(false);
var_dump($post);
$post_log = ob_get_clean();
\Yii::info($post_log, 'fecshop_debug');
//Yii::$service->payment->paypal->receiveIpn($post);
}
}
/*
public $enableCsrfValidation = false;
private $use_local_certs = true;
......@@ -46,7 +87,7 @@ class StandardController extends AppfrontController
$post_log = ob_get_clean();
\Yii::info($post_log, 'fecshop_debug');
Yii::$service->payment->paypal->receiveIpn($post);
//Yii::$service->payment->paypal->receiveIpn($post);
}
}
......@@ -79,4 +120,5 @@ class StandardController extends AppfrontController
$res = curl_exec($ch);
echo $res;
}
*/
}
......@@ -3,6 +3,7 @@ use fecshop\app\appfront\helper\Format;
?>
<div class="main container one-column">
<div class="col-main">
<?= Yii::$service->page->widget->render('flashmessage'); ?>
<?php if(is_array($cart_info) && !empty($cart_info)){ ?>
<div class="product_page">
......
<?php
use yii\db\Migration;
class m170627_013243_fecshop_tables extends Migration
{
public function safeUp()
{
$arr = [
"
ALTER TABLE `sales_flat_order` ADD `payment_token` VARCHAR( 255 ) NULL COMMENT '支付过程中使用的token,譬如paypal express支付',
ADD INDEX ( `payment_token` )
"
,
];
foreach ($arr as $sql) {
$this->execute($sql);
}
}
public function safeDown()
{
echo "m170619_014655_fecshop_tables cannot be reverted.\n";
return false;
}
/*
// Use safeUp/safeDown to run migration code within a transaction
public function safeUp()
{
}
public function safeDown()
{
}
*/
}
......@@ -98,6 +98,22 @@ class Order extends Service
return new MyOrder();
}
}
/**
* @property $increment_id | String , 订单号
* @return object (MyOrder),返回 MyOrder model
* 通过订单号,得到订单信息。
*/
protected function actionGetByIncrementId($increment_id)
{
$one = MyOrder::findOne(['increment_id' => $increment_id]);
$primaryKey = $this->getPrimaryKey();
if ($one[$primaryKey]) {
return $one;
} else {
return false;
}
}
/**
* @property $reflush | boolean 是否从数据库中重新获取,如果是,则不会使用类变量中计算的值
......@@ -283,21 +299,7 @@ class Order extends Service
return true;
}
/**
* @property $increment_id | String , 订单号
* @return object (MyOrder),返回 MyOrder model
* 通过订单号,得到订单信息。
*/
protected function actionGetByIncrementId($increment_id)
{
$one = MyOrder::findOne(['increment_id' => $increment_id]);
$primaryKey = $this->getPrimaryKey();
if ($one[$primaryKey]) {
return $one;
} else {
return false;
}
}
/**
* @property $increment_id | String , 订单号
......@@ -323,16 +325,61 @@ class Order extends Service
return;
}
}
protected function actionGeneratePPExpressOrder($token){
$myOrder = new MyOrder();
$myOrder->payment_token = $token;
$myOrder->save();
$order_id = $myOrder['order_id'];
if($order_id){
$increment_id = $this->generateIncrementIdByOrderId($order_id);
$myOrder['increment_id'] = $increment_id;
$myOrder->save();
$this->setSessionIncrementId($increment_id);
return true;
}else{
Yii::$service->helper->errors->add('generate order fail');
return false;
}
}
protected function actionGetByPaymentToken($token){
$one = MyOrder::find()->where(['payment_token' => $token])
->one();
if(isset($one['order_id']) && $one['order_id']){
return $one;
}else{
return '';
}
}
/**
* @property $reflush | boolean 是否从数据库中重新获取,如果是,则不会使用类变量中计算的值
* 通过从session中取出来订单的increment_id
* 在通过increment_id(订单编号)取出来订单信息。
*/
protected function actionGetInfoByPaymentToken($token)
{
$orderModel = $this->getByPaymentToken($token);
$increment_id = isset($orderModel['increment_id']) ? $orderModel['increment_id'] : '';
return Yii::$service->order->getOrderInfoByIncrementId($increment_id);
}
/**
* @property $address | Array 货运地址
* @property $shipping_method | String 货运快递方式
* @property $payment_method | Array 支付方式、
* @property $clearCartAndDeductStock | boolean 是否清空购物车,并扣除库存,这种情况是先 生成订单,在支付的情况下失败的处理方式。
* @property $token | string 代表 通过payment_token得到order,然后更新order信息的方式生成order,这个是paypal购物车express支付对应的功能
* @return bool 通过购物车的数据生成订单是否成功
* 通过购物车中的产品信息,以及传递的货运地址,货运快递方式,支付方式生成订单。
*/
protected function actionGenerateOrderByCart($address, $shipping_method, $payment_method, $clearCart = true)
protected function actionGenerateOrderByCart($address, $shipping_method, $payment_method, $clearCart = true , $token = '')
{
$cart = Yii::$service->cart->quote->getCurrentCart();
if (!$cart) {
......@@ -368,7 +415,19 @@ class Order extends Service
$beforeEventName = 'event_generate_order_before';
$afterEventName = 'event_generate_order_after';
Yii::$service->event->trigger($beforeEventName, $cartInfo);
$myOrder = new MyOrder();
if($token){
// 有token 代表前面已经生成了order,直接通过token查询出来即可。
$myOrder = $this->getByPaymentToken($token);
if(!$myOrder){
Yii::$service->helper->errors->add('order increment id is not exist.');
return false;
}else{
$increment_id = $myOrder['increment_id'];
}
}else{
$myOrder = new MyOrder();
}
$myOrder['order_status'] = $this->payment_status_pending;
$myOrder['store'] = $cartInfo['store'];
$myOrder['created_at'] = time();
......@@ -415,16 +474,17 @@ class Order extends Service
$myOrder['payment_method'] = $payment_method;
$myOrder['shipping_method'] = $shipping_method;
$myOrder->save();
$order_id = Yii::$app->db->getLastInsertId();
$increment_id = $this->generateIncrementIdByOrderId($order_id);
$orderModel = $this->getByPrimaryKey($order_id);
Yii::$service->event->trigger($afterEventName, $orderModel);
if ($orderModel[$this->getPrimaryKey()]) {
$orderModel['increment_id'] = $increment_id;
$orderModel->save();
$order_id = $myOrder['order_id'];
if(!$increment_id){
$increment_id = $this->generateIncrementIdByOrderId($order_id);
$myOrder['increment_id'] = $increment_id;
$myOrder->save();
}
$this->setSessionIncrementId($increment_id);
Yii::$service->event->trigger($afterEventName, $myOrder);
if ($myOrder[$this->getPrimaryKey()]) {
Yii::$service->order->item->saveOrderItems($cartInfo['products'], $order_id, $cartInfo['store']);
$this->setSessionIncrementId($increment_id);
// 优惠券
// 优惠券是在购物车页面添加的,添加后,优惠券的使用次数会被+1,
// 因此在生成订单部分,是没有优惠券使用次数操作的(在购物车添加优惠券已经被执行该操作)
......@@ -459,6 +519,18 @@ class Order extends Service
{
return Yii::$app->session->get(self::CURRENT_ORDER_CREAMENT_ID);
}
/**
* @property $increment_id | String 订单号
* @property $token | String ,通过api支付的token
* 通过订单号,更新订单的支付token
*/
protected function actionUpdateTokenByIncrementId($increment_id,$token){
$myOrder = Yii::$service->order->getByIncrementId($increment_id);
if($myOrder){
$myOrder->payment_token = $token;
$myOrder->save();
}
}
/**
* 从session中销毁订单号.
......
......@@ -203,7 +203,26 @@ class Payment extends Service
}
}
}
/**
* @property $payment_method | String 支付方式。
* @return 返回进行数据交互的express的api地址。
*/
public function getStandardApiUrl($payment_method = '')
{
if (!$payment_method) {
$payment_method = $this->getPaymentMethod();
}
if ($payment_method) {
$paymentConfig = $this->paymentConfig;
if (isset($paymentConfig['standard'][$payment_method]['api_url'])) {
if (!empty($paymentConfig['standard'][$payment_method]['api_url'])) {
return $paymentConfig['standard'][$payment_method]['api_url'];
}
}
}
}
/**
* @property $url | String url的字符串
* @return string 根据传递的字符串格式,得到相应的url
......@@ -284,6 +303,10 @@ class Payment extends Service
}
}
}
/**
* @property $payment_method | String 支付方式。
......@@ -398,6 +421,26 @@ class Payment extends Service
}
}
}
/**
* @property $payment_method | String 支付方式。
* @return 返回进行数据交互的express的signature。
*/
public function getStandardReturnUrl($payment_method = '')
{
if (!$payment_method) {
$payment_method = $this->getPaymentMethod();
}
if ($payment_method) {
$paymentConfig = $this->paymentConfig;
if (isset($paymentConfig['standard'][$payment_method]['return_url'])) {
if (!empty($paymentConfig['standard'][$payment_method]['return_url'])) {
return $this->getUrl($paymentConfig['standard'][$payment_method]['return_url']);
}
}
}
}
/**
* @property $payment_method | String 支付方式。
......@@ -437,4 +480,26 @@ class Payment extends Service
}
}
}
/**
* @property $payment_method | String 支付方式。
* @return 返回进行数据交互的express的signature。
*/
public function getExpressIpnUrl($payment_method = '')
{
if (!$payment_method) {
$payment_method = $this->getPaymentMethod();
}
if ($payment_method) {
$paymentConfig = $this->paymentConfig;
if (isset($paymentConfig['express'][$payment_method]['ipn_url'])) {
if (!empty($paymentConfig['express'][$payment_method]['ipn_url'])) {
return $this->getUrl($paymentConfig['express'][$payment_method]['ipn_url']);
}
}
}
}
}
......@@ -39,6 +39,7 @@ class Paypal extends Service
public $use_local_certs = false;
// 在payment中 express paypal 的配置值
public $express_payment_method;
public $standard_payment_method;
public $version = '109.0';
public $crt_file;
......@@ -47,7 +48,9 @@ class Paypal extends Service
const EXPRESS_TOKEN = 'paypal_express_token';
const EXPRESS_PAYER_ID = 'paypal_express_payer_id';
protected $expressPayerID;
protected $expressToken;
/**
* @property $domain | string
* @return 得到证书crt文件的绝对路径
......@@ -286,12 +289,15 @@ class Paypal extends Service
// 发送新订单邮件
Yii::$service->email->order->sendCreateEmail($orderInfo);
} elseif ($payment_status == $this->payment_status_failed) {
$this->_order->order_status = Yii::$service->order->payment_status_canceled;
$this->_order->save();
# 因为涉及到扣库存,因此,先不更改订单状态。
//$this->_order->order_status = Yii::$service->order->payment_status_canceled;
//$this->_order->save();
} elseif ($payment_status == $this->payment_status_refunded) {
$this->_order->order_status = Yii::$service->order->payment_status_canceled;
$this->_order->save();
# 因为涉及到扣库存,因此,先不更改订单状态。
//$this->_order->order_status = Yii::$service->order->payment_status_canceled;
//$this->_order->save();
} else {
}
}
//$innerTransaction->commit();
......@@ -318,6 +324,23 @@ class Paypal extends Service
return $ApiUrl.'?cmd=_express-checkout&token='.urlencode($token);
}
}
/**
* @property $token | String , 通过 下面的 PPHttpPost5 方法返回的paypal express的token
* @return String,通过token得到跳转的 paypal url,
* 得到上面的url后,进行跳转到paypal,然后确认,然后返回到fecshop,paypal会传递货运地址等信息
* 到fecshop,这样用户不需要手动填写货运地址等信息。因此,这种方式为快捷支付。
*/
public function getSetStandardCheckoutUrl($token)
{
if ($token) {
$ApiUrl = Yii::$service->payment->getStandardApiUrl($this->standard_payment_method);
return $ApiUrl.'?useraction=commit&cmd=_express-checkout&token='.urlencode($token);
}
}
/**
* @property $methodName_ | String,请求的方法,譬如: $methodName_ = "SetExpressCheckout";
......@@ -329,12 +352,18 @@ class Paypal extends Service
public function PPHttpPost5($methodName_, $nvpStr_, $i = 1)
{
$API_NvpUrl = Yii::$service->payment->getExpressNvpUrl($this->express_payment_method);
$API_Signature = Yii::$service->payment->getExpressSignature($this->express_payment_method);
$API_UserName = Yii::$service->payment->getExpressAccount($this->express_payment_method);
$API_Password = Yii::$service->payment->getExpressPassword($this->express_payment_method);
$API_Signature = Yii::$service->payment->getExpressSignature($this->express_payment_method);
$API_UserName = Yii::$service->payment->getExpressAccount($this->express_payment_method);
$API_Password = Yii::$service->payment->getExpressPassword($this->express_payment_method);
$ipn_url = Yii::$service->payment->getExpressIpnUrl($this->express_payment_method);
// Set the API operation, version, and API signature in the request.
$nvpreq = "METHOD=$methodName_&PWD=$API_Password&USER=$API_UserName&SIGNATURE=$API_Signature$nvpStr_";
$nvpreq = "METHOD=$methodName_&PWD=$API_Password&USER=$API_UserName&SIGNATURE=$API_Signature$nvpStr_";
$nvpreq .= "&PAYMENTREQUEST_0_NOTIFYURL=".urlencode($ipn_url);
//echo $nvpreq;
//\Yii::info($nvpreq, 'fecshop_debug');
//exit;
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_URL, $API_NvpUrl);
......@@ -359,6 +388,7 @@ class Paypal extends Service
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Connection: Close']);
// Get response from the server.
$httpResponse = curl_exec($ch);
//echo "<br><br>%%%%%".$httpResponse."%%%%%<br><br>";
if (!$httpResponse) {
$i++;
if ($i > 5) {
......@@ -414,12 +444,12 @@ class Paypal extends Service
* 【paypal快捷支付部分】api发送付款
* 通过该函数,将参数组合成字符串,通过api发送给paypal进行付款。
*/
public function getExpressCheckoutPaymentNvpStr()
public function getExpressCheckoutPaymentNvpStr($token)
{
$nvp_array = [];
$nvp_array['PAYERID'] = $this->getExpressPayerID();
$nvp_array['TOKEN'] = $this->getExpressToken();
$nvp_array['TOKEN'] = $this->getExpressToken();
$nvp_array['PAYMENTREQUEST_0_PAYMENTACTION'] = 'Sale';
$nvp_array['VERSION'] = $this->version;
// https://developer.paypal.com/docs/classic/api/merchant/SetExpressCheckout_API_Operation_NVP/
......@@ -427,7 +457,7 @@ class Paypal extends Service
$nvp_array['ADDROVERRIDE'] = 0;
//ADDROVERRIDE
// 得到购物车的信息,通过购物车信息填写。
$orderInfo = Yii::$service->order->getCurrentOrderInfo();
$orderInfo = Yii::$service->order->getInfoByPaymentToken($token);
//$cartInfo = Yii::$service->cart->getCartInfo();
$currency = Yii::$service->page->currency->getCurrentCurrency();
......@@ -437,25 +467,25 @@ class Paypal extends Service
$discount_amount = Yii::$service->helper->format->number_format($orderInfo['subtotal_with_discount']);
$subtotal = $subtotal - $discount_amount;
$nvp_array['PAYMENTREQUEST_0_SHIPTOSTREET'] = $orderInfo['customer_address_street1'].' '.$orderInfo['customer_address_street2'];
$nvp_array['PAYMENTREQUEST_0_SHIPTOCITY'] = $orderInfo['customer_address_city'];
$nvp_array['PAYMENTREQUEST_0_SHIPTOSTATE'] = $orderInfo['customer_address_state_name'];
$nvp_array['PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE'] = $orderInfo['customer_address_country'];
$nvp_array['PAYMENTREQUEST_0_SHIPTOZIP'] = $orderInfo['customer_address_zip'];
$nvp_array['PAYMENTREQUEST_0_SHIPTONAME'] = $orderInfo['customer_firstname'].' '.$orderInfo['customer_lastname'];
$nvp_array['PAYMENTREQUEST_0_INVNUM'] = $orderInfo['increment_id'];
$nvp_array['PAYMENTREQUEST_0_CURRENCYCODE'] = $currency;
$nvp_array['PAYMENTREQUEST_0_AMT'] = $grand_total;
$nvp_array['PAYMENTREQUEST_0_ITEMAMT'] = $subtotal;
$nvp_array['PAYMENTREQUEST_0_SHIPPINGAMT'] = $shipping_total;
$nvp_array['PAYMENTREQUEST_0_SHIPTOSTREET'] = $orderInfo['customer_address_street1'].' '.$orderInfo['customer_address_street2'];
$nvp_array['PAYMENTREQUEST_0_SHIPTOCITY'] = $orderInfo['customer_address_city'];
$nvp_array['PAYMENTREQUEST_0_SHIPTOSTATE'] = $orderInfo['customer_address_state_name'];
$nvp_array['PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE'] = $orderInfo['customer_address_country'];
$nvp_array['PAYMENTREQUEST_0_SHIPTOZIP'] = $orderInfo['customer_address_zip'];
$nvp_array['PAYMENTREQUEST_0_SHIPTONAME'] = $orderInfo['customer_firstname'].' '.$orderInfo['customer_lastname'];
$nvp_array['PAYMENTREQUEST_0_INVNUM'] = $orderInfo['increment_id'];
$nvp_array['PAYMENTREQUEST_0_CURRENCYCODE'] = $currency;
$nvp_array['PAYMENTREQUEST_0_AMT'] = $grand_total;
$nvp_array['PAYMENTREQUEST_0_ITEMAMT'] = $subtotal;
$nvp_array['PAYMENTREQUEST_0_SHIPPINGAMT'] = $shipping_total;
$i = 0;
foreach ($orderInfo['products'] as $item) {
$nvp_array['L_PAYMENTREQUEST_0_QTY'.$i] = $item['qty'];
$nvp_array['L_PAYMENTREQUEST_0_NUMBER'.$i] = $item['sku'];
$nvp_array['L_PAYMENTREQUEST_0_AMT'.$i] = Yii::$service->helper->format->number_format($item['price']);
$nvp_array['L_PAYMENTREQUEST_0_NAME'.$i] = Yii::$service->store->getStoreAttrVal($item['name'], 'name');
$nvp_array['L_PAYMENTREQUEST_0_NAME'.$i] = $item['name'];
$nvp_array['L_PAYMENTREQUEST_0_CURRENCYCODE'.$i] = $currency;
$i++;
}
......@@ -523,70 +553,101 @@ class Paypal extends Service
return $this->getRequestUrlStrByArray($nvp_array);
}
/**
* 从request get 中取出来token,然后保存到session中.
* @property $landingPage | String ,访问api的类型,譬如login
* 【paypal快捷支付部分】通过购物车中的数据,组合成访问paypal express api的url
* 这里返回的的字符串,是快捷支付部分获取token和payerId的参数。
* 通过这些参数最终得到paypal express的token和payerId
*/
public function setExpressToken()
public function getStandardTokenNvpStr($landingPage = 'Login')
{
$token = Yii::$app->request->get('token');
$token = \Yii::$service->helper->htmlEncode($token);
if ($token) {
Yii::$app->session->set(self::EXPRESS_TOKEN, $token);
return true;
}
$nvp_array = [];
$nvp_array['LANDINGPAGE'] = $landingPage;
$nvp_array['RETURNURL'] = Yii::$service->payment->getStandardReturnUrl('paypal_standard');
$nvp_array['CANCELURL'] = Yii::$service->payment->getStandardCancelUrl('paypal_standard');
$nvp_array['PAYMENTREQUEST_0_PAYMENTACTION'] = 'Sale';
$nvp_array['VERSION'] = $this->version;
// 得到购物车的信息,通过购物车信息填写。
$orderInfo = Yii::$service->order->getCurrentOrderInfo();
//var_dump($orderInfo);
$currency = $orderInfo['order_currency_code'];
return false;
}
$grand_total = Yii::$service->helper->format->number_format($orderInfo['grand_total']);
$subtotal = Yii::$service->helper->format->number_format($orderInfo['subtotal']);
$shipping_total = Yii::$service->helper->format->number_format($orderInfo['shipping_total']);
$discount_amount= $orderInfo['subtotal_with_discount'] ? $orderInfo['subtotal_with_discount'] : 0;
//$subtotal = $subtotal - $discount_amount;
/**
* 从request get 中取出来PayerID,然后保存到session中.
*/
public function setExpressPayerID()
{
$PayerID = Yii::$app->request->get('PayerID');
$PayerID = \Yii::$service->helper->htmlEncode($PayerID);
if ($PayerID) {
Yii::$app->session->set(self::EXPRESS_PAYER_ID, $PayerID);
$nvp_array['PAYMENTREQUEST_0_CURRENCYCODE'] = $currency;
$nvp_array['PAYMENTREQUEST_0_AMT'] = $grand_total;
$nvp_array['PAYMENTREQUEST_0_ITEMAMT'] = $subtotal;
$nvp_array['PAYMENTREQUEST_0_SHIPPINGAMT'] = $shipping_total;
$i = 0;
return true;
foreach ($orderInfo['products'] as $item) {
$nvp_array['L_PAYMENTREQUEST_0_QTY'.$i] = $item['qty'];
$nvp_array['L_PAYMENTREQUEST_0_NUMBER'.$i] = $item['sku'];
$nvp_array['L_PAYMENTREQUEST_0_AMT'.$i] = Yii::$service->helper->format->number_format($item['price']);
$nvp_array['L_PAYMENTREQUEST_0_NAME'.$i] = $item['name'];;
$nvp_array['L_PAYMENTREQUEST_0_CURRENCYCODE'.$i] = $currency;
$i++;
}
return false;
$nvp_array['L_PAYMENTREQUEST_0_NAME'.$i] = 'Discount';
$nvp_array['L_PAYMENTREQUEST_0_AMT'.$i] = '-'.$discount_amount;
//var_dump($nvp_array);
return $this->getRequestUrlStrByArray($nvp_array);
}
/**
* 从session 中取出来token.
* 从get参数里得到express支付的token
*/
public function getExpressToken()
{
return Yii::$app->session->get(self::EXPRESS_TOKEN);
if(!$this->expressToken){
$token = Yii::$app->request->get('token');
$token = \Yii::$service->helper->htmlEncode($token);
if ($token) {
$this->expressToken = $token;
}
}
return $this->expressToken;
}
/**
* 从session 中取出来PayerID.
* 从get参数里得到express支付的PayerID
*/
public function getExpressPayerID()
{
return Yii::$app->session->get(self::EXPRESS_PAYER_ID);
if(!$this->expressPayerID){
$PayerID = Yii::$app->request->get('PayerID');
$PayerID = \Yii::$service->helper->htmlEncode($PayerID);
if ($PayerID) {
$this->expressPayerID = $PayerID;
}
}
return $this->expressPayerID;
}
/**
* @property $doExpressCheckoutReturn | Array , 上面的 函数 doExpressCheckoutPayment 返回的数据
* 快捷支付付款状态提交后,更新订单的支付部分的信息。
*/
public function updateExpressOrderPayment($DoExpressCheckoutReturn)
public function updateExpressOrderPayment($DoExpressCheckoutReturn,$token)
{
if ($DoExpressCheckoutReturn) {
//echo 'aaa';
$increment_id = Yii::$service->order->getSessionIncrementId();
//$increment_id = Yii::$service->order->getSessionIncrementId();
//echo "\n $increment_id \n\n";
$order = Yii::$service->order->getByIncrementId($increment_id);
//$order = Yii::$service->order->getByIncrementId($increment_id);
echo '########'.$token.'#####';
$order = Yii::$service->order->getByPaymentToken($token);
$order_cancel_status = Yii::$service->order->payment_status_canceled;
// 如果订单状态被取消,那么不能进行支付。
if ($order['order_status'] == $order_cancel_status) {
Yii::$service->helper->error->add('The order status has been canceled and you can not pay for item ,you can create a new order to pay');
Yii::$service->helper->errors->add('The order status has been canceled and you can not pay for item ,you can create a new order to pay');
return false;
}
......@@ -609,10 +670,15 @@ class Paypal extends Service
$order['payment_type'] = $DoExpressCheckoutReturn['PAYMENTINFO_0_PAYMENTTYPE'];
$order['paypal_order_datetime'] = date('Y-m-d H:i:s', $DoExpressCheckoutReturn['PAYMENTINFO_0_ORDERTIME']);
$PAYMENTINFO_0_PAYMENTSTATUS = $DoExpressCheckoutReturn['PAYMENTINFO_0_PAYMENTSTATUS'];
echo $this->payment_status_completed.'##'.$PAYMENTINFO_0_PAYMENTSTATUS."<br>";
if (strtolower($PAYMENTINFO_0_PAYMENTSTATUS) == $this->payment_status_completed) {
//echo 222;
// 判断金额是否相符
echo $currency."<br/>";
echo $order['order_currency_code']."<br/>";
echo $PAYMENTINFO_0_AMT."<br/>";
echo $order['grand_total']."<br/>";
if ($currency == $order['order_currency_code'] && $PAYMENTINFO_0_AMT == $order['grand_total']) {
//echo 222;
$order->order_status = Yii::$service->order->payment_status_processing;
......
......@@ -141,10 +141,12 @@ class Stock extends Service
* [
* 'product_id' => 'xxxxx',
* 'qty' => 2,
* 'name' => 'xxxx',
* 'custom_option_sku' => 'cos_1', # 存在该项,则应该到产品的
* ],
* [
* 'product_id' => 'yyyyy',
* 'name' => 'xxxx',
* 'qty' => 1,
* ],
* ]
......@@ -175,6 +177,7 @@ class Stock extends Service
foreach ($items as $k=>$item) {
$product_id = $item['product_id'];
$sale_qty = (int)$item['qty'];
$product_name = Yii::$service->store->getStoreAttrVal($item['product_name'], 'name');
$custom_option_sku = $item['custom_option_sku'];
if ($product_id && $sale_qty) {
if(!$custom_option_sku){
......@@ -189,7 +192,7 @@ class Stock extends Service
'product_id' => $product_id
])->one();
if(!$productFlatQty['qty'] || $productFlatQty['qty'] < 0){
Yii::$service->helper->errors->add('productId:'.$product_id.' Product inventory is less than 0 ');
Yii::$service->helper->errors->add('product: [ '.$product_name.' ] is stock out ');
return false;
}
}else{
......@@ -206,7 +209,7 @@ class Stock extends Service
'custom_option_sku' => $custom_option_sku,
])->one();
if($productCustomOptionQty['qty'] < 0){
Yii::$service->helper->errors->add('productId:'.$product_id.' && customOptionSku:'.$custom_option_sku.' Product inventory is less than 0 ');
Yii::$service->helper->errors->add('product: [ '.$product_name.' ] is stock out ');
return false;
}
}
......@@ -220,6 +223,139 @@ class Stock extends Service
}
/**
* @property $items | Array , example:
* [
* [
* 'product_id' => 'xxxxx',
* 'qty' => 2,
* 'custom_option_sku' => 'cos_1', # 存在该项,则应该到产品的
* ],
* [
* 'product_id' => 'yyyyy',
* 'qty' => 1,
* ],
* ]
* @return Array 有库存返回的数据格式如下:
* [
* 'stockStatus' => 1,
* 'outStockProducts' => '',
* ];
* 无库存返回的数据格式,2代表库存返回失败
* [
* 'stockStatus' => 2,
* 库存不足的产品数组。
* 'outStockProducts' => [
* [
* 'product_id' => $product_id,
* 'custom_option_sku' => '',
* 'stock_qty' => 0,
* ],
* [
* 'product_id' => $product_id,
* 'custom_option_sku' => $custom_option_sku,
* 'stock_qty' => $productCustomOptionM['qty'],
* ],
*
* ],
* ];
*
*/
protected function actionCheckItemsQty()
{
$cartInfo = Yii::$service->cart->getCartInfo();
$items = isset($cartInfo['products']) ? $cartInfo['products'] : '';
/**
* $this->checkItemsStock 函数检查产品是否都是上架状态
* 如果满足上架状态 && 零库存为1,则直接返回。
*/
if ($this->zeroInventory) {
// 零库存模式 不会更新产品库存。
return [
'stockStatus' => 1,
'outStockProducts' => '',
];
}
$outStockProducts = [];
// 开始扣除库存。
if (is_array($items) && !empty($items)) {
foreach ($items as $k=>$item) {
$product_id = $item['product_id'];
$sale_qty = (int)$item['qty'];
$product_name = $item['product_name'];
$custom_option_sku = $item['custom_option_sku'];
if ($product_id && $sale_qty) {
if(!$custom_option_sku){
$productM = ProductFlatQty::find()->where([
'product_id' => $product_id
])->one();
if($productM['qty']){
//echo $productM['qty'].'####'.$sale_qty.'<br>';
if($productM['qty'] < $sale_qty){
$outStockProducts[] = [
'product_id' => $product_id,
'custom_option_sku' => '',
'product_name' => $product_name,
'stock_qty' => $productM['qty'],
];
}
}else{
$outStockProducts[] = [
'product_id' => $product_id,
'custom_option_sku' => '',
'product_name' => $product_name,
'stock_qty' => 0,
];
}
}else{
$productCustomOptionM = ProductCustomOptionQty::find()->where([
'product_id' => $product_id,
'custom_option_sku' => $custom_option_sku,
])->one();
if($productCustomOptionM['qty']){
if($productCustomOptionM['qty'] < $sale_qty){
$outStockProducts[] = [
'product_id' => $product_id,
'custom_option_sku' => $custom_option_sku,
'product_name' => $product_name,
'stock_qty' => $productCustomOptionM['qty'],
];
}
}else{
$outStockProducts[] = [
'product_id' => $product_id,
'product_name' => $product_name,
'custom_option_sku' => $custom_option_sku,
'stock_qty' => 0,
];
}
}
}
}
if(empty($outStockProducts)){
return [
'stockStatus' => 1,
'outStockProducts' => '',
];
}else{
return [
'stockStatus' => 2,
'outStockProducts' => $outStockProducts,
];
}
}else{
Yii::$service->helper->errors->add('cart products is empty');
return false;
}
}
/**
* @property $product_items | Array , example:
......@@ -292,6 +428,7 @@ class Stock extends Service
return true; // 零库存模式不扣产品库存,也不需要返还库存。
}
$product_id = $product['_id'];
$product_name = Yii::$service->store->getStoreAttrVal($product['name'], 'name');
if ($this->checkOnShelfStatus($is_in_stock)) {
if ($custom_option_sku) {
......@@ -303,10 +440,13 @@ class Stock extends Service
if($productCustomOptionQty['qty'] >= $sale_qty){
return true;
}else{
Yii::$service->helper->errors->add('Product Id:'.$product['_id'].' && customOptionSku:'.$custom_option_sku.' , Product inventory is less than '.$sale_qty);
Yii::$service->helper->errors->add('product: [ '.$product_name.' ] is stock out ');
//Yii::$service->helper->errors->add('Product Id:'.$product['_id'].' && customOptionSku:'.$custom_option_sku.' , Product inventory is less than '.$sale_qty);
}
}else{
Yii::$service->helper->errors->add('Product Id:'.$product['_id'].' && customOptionSku:'.$custom_option_sku.' , The product has no qty');
Yii::$service->helper->errors->add('product: [ '.$product_name.' ] is stock out ');
//Yii::$service->helper->errors->add('Product Id:'.$product['_id'].' && customOptionSku:'.$custom_option_sku.' , The product has no qty');
}
} elseif (($product_qty > 0) && ($product_qty > $sale_qty)) {
$productFlatQty = ProductFlatQty::find()->where([
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册