1.去官網下載easyWechat(我下的是4.x版本)
composer require overtrue/wechat:~4.0 -vvv
2.開始使用,先封裝代碼
public function init() // 支付配置初始化 { $config = [ // 必要配置 'app_id' => config('xcx_appid'), 'mch_id' => config('mch_id'), 'key' => config('pay_secret'), // API 密鑰 // 如需使用敏感接口(如退款、發送紅包等)需要配置 API 證書路徑(登錄商戶平台下載 API 證書) 'cert_path' => '/www/wwwroot/項目名/extend/cert/apiclient_cert.pem', // XXX: 絕對路徑!!!! 'key_path' => '/www/wwwroot/項目名/extend/cert/apiclient_key.pem', // XXX: 絕對路徑!!!! 'notify_url' => '域名/callback', // 你也可以在下單時單獨設置來想覆蓋它 ]; $app = Factory::payment($config); return $app; } //寫日志 public function logs($msg, $type = 'info') { Log::init([ 'type' => 'File', 'path' => Env::get('root_path') . 'testLog', 'max_files' => 20, ]); Log::write($msg, $type); Log::close(); }
3.支付,前端請求pay 接口
public function pay() // 統一支付接口 { $app = $this->init(); $orderId = time(); $result = $app->order->unify([ // H5 支付,公眾號支付,掃碼支付,支付中簽約,全部都是用這個接口下單。 'body' => '測試支付', 'out_trade_no' => $orderId, // 商戶訂單號 'total_fee' => 1, // 金額 分 'trade_type' => 'JSAPI', // 請對應換成你的支付方式對應的值類型 'openid' => '你的openId', //'spbill_create_ip' => '123.12.12.123', // 可選,如不傳該參數,SDK 將會自動獲取相應 IP 地址 //'notify_url' => 'https://pay.weixin.qq.com/wxpay/pay.action', // 支付結果通知網址,如果不設置則會使用配置里的默認地址 ]); $res = Order::create(['orderId' => $orderId, 'status' => 0,'userId'=>random_int(1,10000)]); // 生成未支付的訂單 if ($result['return_code'] != 'SUCCESS' || $result['result_code'] != 'SUCCESS') return json(['code' => 1, 'msg' => '獲取支付訂單失敗']); else { if ($res) { // 返回給前端,生成支付頁面 $jssdk = $app->jssdk; $config = $jssdk->bridgeConfig($result['prepay_id'], false); return ($config); } else return json(['code' => 1, 'msg' => '創建訂單失敗!']); } } //支付回調 public function callBack() { $app = $this->init(); $response = $app->handlePaidNotify(function ($message, $fail) use ($app){ // 回調 $order = Order::where(['orderId' => $message['out_trade_no']])->find()->toArray(); if (!$order || $order['status'] == 1) // 如果訂單不存在 或者 訂單已經支付過了 return true; // 告訴微信,我已經處理完了,訂單沒找到,別再通知我了 //$res = $app->order->queryByOutTradeNumber($message['out_trade_no']); // 訂單查詢 if ($message['return_code'] === 'SUCCESS' ) { // return_code 表示通信狀態,不代表支付狀態 if ($message['result_code'] === 'SUCCESS') { // 支付成功 $order['status'] = 1; $this->logs('商戶訂單號:'.$message['out_trade_no'].' 支付成功'); } else{ // 支付失敗 $order['status'] = -1; $this->logs('商戶訂單號:'.$message['out_trade_no'].' 支付失敗'); } Order::update($order,['orderId'=>$message['out_trade_no']]); // 更新數據 } else // 通訊失敗 return $this->create([],'connect fail'); return true; // 返回處理完成 }); return $response; }
4.前端接受參數,生成支付
pay: function () { wx.request({ url: 'http://域名/pay', header: { "X-Requested-With": " XMLHttpRequest" }, data: { }, success(res) { console.log(res.data) let ress = res.data //let ress = JSON.parse(res.data) // console.log(ress.data) wx.requestPayment({ // 生成支付頁面的參數 "timeStamp": ress.timeStamp, "nonceStr": ress.nonceStr, "package": ress.package, "signType": ress.signType, "paySign": ress.paySign, 'appId': ress.appId, "success": function (res) { console.log(res) }, "fail": function (res) { console.log(res) }, "complete": function (res) { console.log(res) } }) } }) },
結果:
5.退款,可以通過接口工具請求,傳入支付的訂單號即可
//退款 public function refund() { $out_trade_no = '1628739348'; // 商戶訂單號 $app = $this->init(); // 參數分別為:商戶訂單號、商戶退款單號、訂單金額、退款金額、其他參數 $result = $app->refund->byOutTradeNumber($out_trade_no, uniqid(), 1, 1, [ 'refund_desc' => '退款', 'notify_url' => 'http://域名/refundBack', ]); if ($result['return_code'] == 'SUCCESS') return true; else{ $this->logs('退款失敗','error'); return false; } } //退款回調 public function refundBack(){ $app = $this->init(); $response = $app->handleRefundedNotify(function ($message, $reqInfo, $fail) { // 其中 $message['req_info'] 獲取到的是加密信息 // $reqInfo 是解密后的信息 $order = Order::where(['orderId' => $reqInfo['out_trade_no']])->find()->toArray(); if (!$order || $order['status'] == 2) // 如果訂單不存在 或者 訂單已經退款了 return true; // 告訴微信,我已經處理完了,訂單沒找到,別再通知我了 if($message['return_code']=='SUCCESS'){ // 通信成功 if($reqInfo['refund_status']=='SUCCESS'){ $order['status'] = 2; $this->logs('商戶訂單號:'.$reqInfo['out_trade_no'].' 退款成功'); }else{ $order['status'] = -2; $this->logs('商戶訂單號:'.$reqInfo['out_trade_no'].' 退款失敗'); } Order::update($order,['orderId'=>$reqInfo['out_trade_no']]); // 更新數據 } else // 通訊失敗 return $this->create([],'connect fail'); return true; // 返回 true 告訴微信“我已處理完成” // 或返回錯誤原因 $fail('參數格式校驗錯誤'); }); return $response; }
結果: