全棧微信小程式商城 學習筆記10.3 編寫支付介面
阿新 • • 發佈:2022-02-17
Pay服務層
<?php namespace app\api\service; use app\api\model\Order as OrderModel; use app\lib\exception\OrderException; use app\lib\exception\TokenException; use think\Exception; use think\Loader; use think\Log; //Loader::import('WxPay.WxPay', EXTEND_PATH, '.Data.php'); Loader::import('WxPay.WxPay', EXTEND_PATH, '.Api.php'); class Pay { private $orderNo; private $orderID; // private $orderModel; function __construct($orderID) { if (!$orderID) { throw new Exception('訂單號不允許為NULL'); } $this->orderID = $orderID; } public function pay() { $this->checkOrderValid(); $order = new Order(); $status = $order->checkOrderStock($this->orderID); if (!$status['pass']) { return $status; } return $this->makeWxPreOrder($status['orderPrice']); // $this->checkProductStock(); } // 構建微信支付訂單資訊 private function makeWxPreOrder($totalPrice) { $openid = Token::getCurrentTokenVar('openid'); if (!$openid) { throw new TokenException(); } $wxOrderData = new \WxPayUnifiedOrder(); $wxOrderData->SetOut_trade_no($this->orderNo); $wxOrderData->SetTrade_type('JSAPI'); $wxOrderData->SetTotal_fee($totalPrice * 100); $wxOrderData->SetBody('零食商販'); $wxOrderData->SetOpenid($openid); $wxOrderData->SetNotify_url(config('secure.pay_back_url')); return $this->getPaySignature($wxOrderData); } //向微信請求訂單號並生成簽名 private function getPaySignature($wxOrderData) { $wxOrder = \WxPayApi::unifiedOrder($wxOrderData); // 失敗時不會返回result_code if($wxOrder['return_code'] != 'SUCCESS' || $wxOrder['result_code'] !='SUCCESS'){ Log::record($wxOrder,'error'); Log::record('獲取預支付訂單失敗','error'); // throw new Exception('獲取預支付訂單失敗'); } $this->recordPreOrder($wxOrder); $signature = $this->sign($wxOrder); return $signature; } private function recordPreOrder($wxOrder){ // 必須是update,每次使用者取消支付後再次對同一訂單支付,prepay_id是不同的 OrderModel::where('id', '=', $this->orderID) ->update(['prepay_id' => $wxOrder['prepay_id']]); } // 簽名 private function sign($wxOrder) { $jsApiPayData = new \WxPayJsApiPay(); $jsApiPayData->SetAppid(config('wx.app_id')); $jsApiPayData->SetTimeStamp((string)time()); $rand = md5(time() . mt_rand(0, 1000)); $jsApiPayData->SetNonceStr($rand); $jsApiPayData->SetPackage('prepay_id=' . $wxOrder['prepay_id']); $jsApiPayData->SetSignType('md5'); $sign = $jsApiPayData->MakeSign(); $rawValues = $jsApiPayData->GetValues(); $rawValues['paySign'] = $sign; unset($rawValues['appId']); return $rawValues; } /** * @return bool * @throws OrderException * @throws TokenException */ private function checkOrderValid() { $order = OrderModel::where('id', '=', $this->orderID) ->find(); if (!$order) { throw new OrderException(); } // $currentUid = Token::getCurrentUid(); if(!Token::isValidOperate($order->user_id)) { throw new TokenException( [ 'msg' => '訂單與使用者不匹配', 'errorCode' => 10003 ]); } if($order->status != 1){ throw new OrderException([ 'msg' => '訂單已支付過啦', 'errorCode' => 80003, 'code' => 400 ]); } $this->orderNo = $order->order_no; return true; } }