Procházet zdrojové kódy

支付增加webhook 支付成功页面

kevin_zhangl před 3 roky
rodič
revize
6618af4ac2

+ 8 - 4
common/config/main.php

@@ -1,5 +1,8 @@
 <?php
-$mainConfig = require_once __DIR__ . '/config.php';
+// 运行环境
+$environment = 'production';
+// 根据运行环境加载不同的配置文件
+$mainConfig = $environment == 'local' ? require_once __DIR__ . '/config-local.php' : require_once __DIR__ . '/config.php';
 return [
     'language' => 'zh-CN',
     'timeZone' => 'PRC',
@@ -49,14 +52,15 @@ return [
         'swooleAsyncTimer' => [
             'class' => 'common\components\SwooleAsyncTimer',
         ],
+        'environment' => $environment ?? 'local',
         // payStack配置
         'Paystack' => [
             'class'         => 'smladeoye\paystack\Paystack',
-            'environment'   => 'test',
+            'environment'   => $environment,
             'testPublicKey' => 'pk_test_2eed10135c4a958c5073795b22854ded9d1a6c55',
             'testSecretKey' => 'sk_test_5ece72377432376f5cf6bb5c468395a650220309',
-            'livePublicKey' => '',
-            'liveSecretKey' => '',
+            'livePublicKey' => 'sk_live_b93c6bbee2cc0e9c594547bf4779ec9852b9d055',
+            'liveSecretKey' => 'sk_live_b93c6bbee2cc0e9c594547bf4779ec9852b9d055',
         ],
         // 配置SQL语句输出
         'log' => [

+ 132 - 73
common/helpers/PayStack.php

@@ -5,54 +5,103 @@ namespace common\helpers;
 class PayStack
 {
     /**
-     *
+     * 加载secretKey
+     * @return string
      */
-    public static function transactionInit($currency, $amount, $email){
-        $secretKey = \Yii::$app->Paystack->testSecretKey;
-        $url = "https://api.paystack.co/transaction/initialize";
-        $fields = [
-            'email' => $email,
-            'amount' => $amount * 100
-        ];
-        $fields_string = http_build_query($fields);
-        //open connection
-        $ch = curl_init();
-
-        //set the url, number of POST vars, POST data
-        curl_setopt($ch,CURLOPT_URL, $url);
-        curl_setopt($ch,CURLOPT_POST, true);
-        curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
-        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
-            "Authorization: Bearer {$secretKey}",
-            "Cache-Control: no-cache",
-        ));
-        //So that curl_exec returns the contents of the cURL; rather than echoing it
-        curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
-        //execute post
-        $result = curl_exec($ch);
-        $result =  json_decode($result, true);
-        return [
-            'status'    => $result['status'],
-            'message'   => $result['message'],
-            'data'      => $result['data'],
-        ];
+    public static function getSecretKey(): string
+    {
+        return \Yii::$app->Paystack->environment == 'local' ? \Yii::$app->Paystack->testSecretKey : \Yii::$app->Paystack->liveSecretKey;
+    }
+
+    /**
+     * 支付.
+     */
+    public static function transactionInit($currency, $amount, $email)
+    {
+        $secretKey = self::getSecretKey();
+
+        try {
+            $url = "https://api.paystack.co/transaction/initialize";
+            $fields = [
+                'email' => $email,
+                'amount' => $amount * 100
+            ];
+            $fields_string = http_build_query($fields);
+            //open connection
+            $curl = curl_init();
+
+            //set the url, number of POST vars, POST data
+            curl_setopt($curl,CURLOPT_URL, $url);
+            curl_setopt($curl,CURLOPT_POST, true);
+            curl_setopt($curl,CURLOPT_POSTFIELDS, $fields_string);
+            curl_setopt($curl, CURLOPT_HTTPHEADER, array(
+                "Authorization: Bearer {$secretKey}",
+                "Cache-Control: no-cache",
+            ));
+            //So that curl_exec returns the contents of the cURL; rather than echoing it
+            curl_setopt($curl,CURLOPT_RETURNTRANSFER, true);
+            //execute post
+            $result = curl_exec($curl);
+            $err = curl_error($curl);
+            curl_close($curl);
+            if ($err) {
+                return [
+                    'status'    => false,
+                    'message'   => $err,
+                ];
+            }
+
+            return json_decode($result, true);
+        } catch (\Exception $e) {
+            return [
+                'status'    => false,
+                'message'   => $e->getMessage(),
+            ];
+        }
     }
     /**
-     * 交易支付.
+     * 交易结果校验.
      * @param $ref
      * @return array
      */
     public static function transactionVerify($ref): array
     {
-        $payStack = \Yii::$app->Paystack;
-        $transaction = $payStack->transaction()->setRequestOptions($ref);
-        $transaction->verify();
-
-        return [
-            'status'    => $transaction->status,
-            'message'   => $transaction->message,
-            'data'      => $transaction->data,
-        ];
+        $secretKey = self::getSecretKey();
+
+        try {
+            $curl = curl_init();
+            curl_setopt_array($curl, [
+                CURLOPT_URL => "https://api.paystack.co/transaction/verify/{$ref}",
+                CURLOPT_RETURNTRANSFER => true,
+                CURLOPT_ENCODING => "",
+                CURLOPT_MAXREDIRS => 10,
+                CURLOPT_TIMEOUT => 30,
+                CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
+                CURLOPT_CUSTOMREQUEST => "GET",
+                CURLOPT_HTTPHEADER => array(
+                    "Authorization: Bearer {$secretKey}",
+                    "Cache-Control: no-cache",
+                ),
+            ]);
+
+            $response = curl_exec($curl);
+            $err = curl_error($curl);
+            curl_close($curl);
+
+            if ($err) {
+                return [
+                    'status'    => false,
+                    'message'   => $err,
+                ];
+            }
+
+            return json_decode($response, true);
+        } catch (\Exception $e) {
+            return [
+                'status'    => false,
+                'message'   => $e->getMessage(),
+            ];
+        }
     }
 
     /**
@@ -63,38 +112,48 @@ class PayStack
      */
     public static function transactionRefund(string $reference, int $amount)
     {
-        $secretKey = \Yii::$app->Paystack->testSecretKey;
-
-        $url = "https://api.paystack.co/refund";
-        $fields = [
-            'transaction' => $reference,
-            'amount'      => $amount,
-        ];
-        $fields_string = http_build_query($fields);
-        //open connection
-        $ch = curl_init();
-
-        //set the url, number of POST vars, POST data
-        curl_setopt($ch, CURLOPT_URL, $url);
-        curl_setopt($ch, CURLOPT_POST, true);
-        curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
-        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
-            "Authorization: Bearer {$secretKey}",
-            "Cache-Control: no-cache",
-        ));
-
-        //So that curl_exec returns the contents of the cURL; rather than echoing it
-        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-
-        //execute post
-        $response = curl_exec($ch);
-        $response = json_decode($response, true);
-
-        return [
-            'status'    => $response['status'],
-            'message'   => $response['message'],
-            'data'      => $response['data'],
-        ];
-    }
+        $secretKey = self::getSecretKey();
+
+        try {
+            $url = "https://api.paystack.co/refund";
+            $fields = [
+                'transaction' => $reference,
+                'amount'      => $amount,
+            ];
+            $fields_string = http_build_query($fields);
+            //open connection
+            $curl = curl_init();
 
+            //set the url, number of POST vars, POST data
+            curl_setopt($curl, CURLOPT_URL, $url);
+            curl_setopt($curl, CURLOPT_POST, true);
+            curl_setopt($curl, CURLOPT_POSTFIELDS, $fields_string);
+            curl_setopt($curl, CURLOPT_HTTPHEADER, array(
+                "Authorization: Bearer {$secretKey}",
+                "Cache-Control: no-cache",
+            ));
+
+            //So that curl_exec returns the contents of the cURL; rather than echoing it
+            curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+
+            //execute post
+            $response = curl_exec($curl);
+            $err = curl_error($curl);
+            curl_close($curl);
+
+            if ($err) {
+                return [
+                    'status'    => false,
+                    'message'   => $err,
+                ];
+            }
+
+            return json_decode($response, true);
+        } catch (\Exception $e) {
+            return [
+                'status'    => false,
+                'message'   => $e->getMessage(),
+            ];
+        }
+    }
 }

+ 2 - 1
common/models/ApproachOrder.php

@@ -47,6 +47,7 @@ use Yii;
  * @property int $DELETED_AT 删除时间
  * @property int $WAREHOUSE 发货仓
  * @property string $EMAIL 邮箱
+ * @property string $NOTE 备注说明
  */
 class ApproachOrder extends \common\components\ActiveRecord
 {
@@ -72,7 +73,7 @@ class ApproachOrder extends \common\components\ActiveRecord
             [['ORDER_TYPE'], 'string', 'max' => 12],
             [['EXPRESS_COMPANY'], 'string', 'max' => 128],
             [['FRONT_REMARK'], 'string', 'max' => 1000],
-            [['REMARK'], 'string', 'max' => 4000],
+            [['REMARK', 'NOTE'], 'string', 'max' => 4000],
             [['CONSIGNEE'], 'string', 'max' => 120],
             [['MOBILE'], 'string', 'max' => 11],
             [['ADDRESS'], 'string', 'max' => 255],

+ 2 - 1
common/models/Order.php

@@ -52,6 +52,7 @@ use Yii;
  * @property int $DELETED_AT 删除时间
  * @property int $WAREHOUSE 发货仓
  * @property string $EMAIL 邮箱
+ * @property string $NOTE 备注说明
  */
 class Order extends \common\components\ActiveRecord
 {
@@ -77,7 +78,7 @@ class Order extends \common\components\ActiveRecord
             [['ORDER_TYPE'], 'string', 'max' => 12],
             [['EXPRESS_COMPANY'], 'string', 'max' => 128],
             [['FRONT_REMARK'], 'string', 'max' => 1000],
-            [['REMARK'], 'string', 'max' => 4000],
+            [['REMARK', 'NOTE'], 'string', 'max' => 4000],
             [['CONSIGNEE'], 'string', 'max' => 120],
             [['MOBILE'], 'string', 'max' => 11],
             [['ADDRESS'], 'string', 'max' => 255],

+ 5 - 5
common/models/forms/ApproachOrderForm.php

@@ -33,6 +33,7 @@ class ApproachOrderForm extends Model
     public $orderTrackNo;
     public $status;
     public $remark;
+    public $note;
 
     public $type;
     public $addressId;
@@ -122,10 +123,10 @@ class ApproachOrderForm extends Model
         $customScenarios = [
             // 管理员修改订单状态
             'adminStatus' => ['sn', 'status'],
-            // 管理员修改订单状态
-            'verifyPayStack' => ['sn', 'remark', 'email'],
+            // 校验订单支付
+            'verifyPayStack' => ['sn', 'note'],
             // 会员下单
-            'userOrder' => ['type','addressId', 'payType','goodsId','goodsNum', 'remark', 'payPassword'/*, 'email'*/],
+            'userOrder' => ['type','addressId', 'payType','goodsId','goodsNum', 'note', 'payPassword'],
         ];
         return array_merge($parentScenarios, $customScenarios);
     }
@@ -293,7 +294,7 @@ class ApproachOrderForm extends Model
         try {
             // 更新准订单状态为已支付
             $this->_model->STATUS = \Yii::$app->params['orderStatus']['paid']['value'];
-            $this->_model->REMARK = json_encode($this->remark);
+            $this->_model->NOTE = json_encode($this->remark);
             $this->_model->PAY_AT = Date::nowTime();
             $this->_model->EMAIL = $this->email;
             if (!$this->_model->save()) {
@@ -302,7 +303,6 @@ class ApproachOrderForm extends Model
             // 更新订单商品的支付Email
             ApproachOrderGoods::updateAll(['EMAIL' => $this->email], 'ORDER_SN = :ORDER_SN', [':ORDER_SN' => $this->sn]);
 
-
             // 同步准订单到正式订单
             Order::insertOne($this->_model->toArray());
             // 同步准订单商品到正式订单商品

+ 1 - 1
frontendApi/config/urlManagerRules.php

@@ -68,7 +68,6 @@ return [
             'GET show-cart' => 'show-cart',
             'GET reconsume-cart' => 'reconsume-cart',
             'POST sure-order' => 'sure-order',
-            'POST verify-order' => 'verify-order',
             'POST reconsume-sure-order' => 'reconsume-sure-order',
             'GET pay-success' => 'pay-success',
             'GET order-list' => 'order-list',
@@ -78,6 +77,7 @@ return [
             'GET dec-order-export/<orderSn>' => 'dec-order-export',
             'POST sure-approach-order' => 'sure-approach-order',
             'POST delete-approach-order' => 'delete-approach-order',
+            'GET,POST verify-approach-order' => 'verify-approach-order',
         ],
     ],
     [

+ 10 - 5
frontendApi/modules/v1/controllers/ShopController.php

@@ -172,15 +172,20 @@ class ShopController extends BaseController {
     }
 
     /**
-     * 订单支付成功
+     * PayStack支付成功的webhook.
      * @throws \yii\web\HttpException
      */
-    public function actionVerifyOrder(){
-        if (\Yii::$app->request->isPost) {
-            return parent::edit(ApproachOrderForm::class, 'PayStack pay Success', 'verifyPayStack', ['verifyPayStack']);
+    public function actionVerifyApproachOrder() {
+        $request = \Yii::$app->request;
+        LoggerTool::info($request);
+
+        http_response_code(200);
+
+        if (parent::edit(ApproachOrderForm::class, 'PayStack pay Success', 'verifyPayStack', ['verifyPayStack'])) {
+            return http_response_code(200);
         }
 
-        return static::notice('非法请求', 400);
+        return http_response_code(500);
     }
 
     /**

+ 1 - 1
frontendEle/src/utils/userInfo.js

@@ -60,7 +60,7 @@ const userInfo = {
   },
   userEmail (...arg) {
     if (arg.length === 0) {
-      return localStorage.getItem('userEmail')
+      return localStorage.getItem('userEmail') ? localStorage.getItem('userEmail') : ''
     }
     if (arg[0] === '') {
       localStorage.removeItem('userEmail')

+ 36 - 32
frontendEle/src/views/shop/order.vue

@@ -159,7 +159,15 @@
                 <el-button type="primary" size="small">支 付</el-button>
 
             </paystack>
-            <el-button type="danger" size="small"  class="cancelButton" @click="handleClose">取 消</el-button>
+            <el-button type="danger" size="small" class="cancelButton" @click="handleClose">取 消</el-button>
+        </el-dialog>
+
+        <el-dialog title="提示" :visible.sync="payDialog" :show-close="false" width="350px" :close="handleOrderList">
+          <el-result icon="success" title="支付成功">
+            <template slot="extra">
+              <span style="color: #008efa; font-size: 30px;">{{ countdown }}</span>
+            </template>
+          </el-result>
         </el-dialog>
     </div>
 </template>
@@ -195,6 +203,8 @@
                 prefixSign: '₦',
                 unit: 'NGN',
                 sn: '',
+                payDialog: false,
+                countdown: 5,
                 visible: false,
                 payStackLoading: false,
                 form: {
@@ -209,9 +219,9 @@
                         cart_id: this.sn,
                         custom_fields: [
                             {
-                                "display_name": "orderSn",
-                                "variable_name": "orderSn",
-                                "value": this.sn
+                                display_name: 'orderSn',
+                                variable_name: 'orderSn',
+                                value: this.sn
                             },
                         ]
                     },
@@ -470,34 +480,13 @@
             },
             // 支付成功回调
             processPayment(response) {
-                // 支付失败
-                if (response.status !== 'success') {
-                    this.$message({
-                        message: 'Success!',
-                        type: 'error'
-                    })
-                    return false
-                }
-
-                this.payStackLoading = true
-                // 支付成功,更新订单
-                return network.postData('shop/verify-order', { sn: this.form.orderSn, remark: response, email: this.form.email }).then(_ => {
-                    this.$message({
-                        message: 'Success!',
-                        type: 'success'
-                    })
+                // 关闭支付页面
+                this.visible = false
+                this.payStackLoading = false
 
-                    this.visible = false
-                    this.payStackLoading = false
-                    this.$router.push({path: `/shop/order-list`})
-                }).catch((err) => {
-                    this.$message({
-                        message: err,
-                        type: 'error'
-                    })
-                    this.payStackLoading = false
-                    return false
-                })
+                // 显示支付成功模态框
+                this.payDialog = true
+                this.handleCountdown()
             },
             // 关闭支付回调
             processClose() {
@@ -507,7 +496,22 @@
                 sessionStorage.removeItem('order_goods')
                 sessionStorage.removeItem('category_type')
                 this.$router.push({path: `/shop/index`})
-            }
+            },
+            handleOrderList() {
+              this.$router.push({path: `/shop/order-list`})
+            },
+            // 启动倒计时
+            handleCountdown() {
+                //创建定时器
+                setInterval(() => {
+                    // 每隔1秒把time的值减一,赋值给span标签
+                    this.countdown--
+                    if (this.countdown === 0) {
+                        // 倒计时结束,跳转到订单列表
+                        this.$router.push({path: `/shop/order-list`})
+                    }
+                }, 1000)
+            },
         }
     }
 </script>