在項目中用到小程序支付,費話不多說上代碼
因為我這涉及么微信的很多開發功能 所以我把公共的方法放到的公共類中
WechatPublic
<?php namespace app\zhonglian\controller\wechat; use app\BaseController; use think\facade\Config; use EasyWeChat\Factory; use app\zhonglian\controller\ZhonglianPublic; class WechatPublic extends ZhonglianPublic{ public $config; //公眾號配置文件 public $app; //公眾號配置 public $minConfig; //小程序配置 public $wechatPay; //微信支付配置 public function __construct(){ $this->config = [ /** * 賬號基本信息,請從微信公眾平台/開放平台獲取 */ 'app_id' => Config::get('zhonglian.wechat.AppID'), // AppID 'secret' => Config::get('zhonglian.wechat.AppSecret'), // AppSecret 'token' => Config::get('zhonglian.wechat.token'), // Token 'aes_key' => Config::get('zhonglian.wechat.aes_key'), // EncodingAESKey,安全模式與兼容模式下請一定要填寫!!! 'response_type' => 'array', ]; // 小程序 $this->minConfig = [ 'app_id' => Config::get('zhonglian.minWechat.AppID'), 'secret' => Config::get('zhonglian.minWechat.AppSecret'), // 下面為可選項 // 指定 API 調用返回結果的類型:array(default)/collection/object/raw/自定義類名 'response_type' => 'array', 'log' => [ 'level' => 'debug', 'file' => __DIR__.'/wechat.log', ], ]; $this->webHost = 'https:://'.$_SERVER['HTTP_HOST']; //站點域名 //微信支付 $this->wechatPay = [ // 必要配置 'app_id' => Config::get('zhonglian.wechatPay.app_id'), 'mch_id' => Config::get('zhonglian.wechatPay.mch_id'), 'key' => Config::get('zhonglian.wechatPay.key'), // API 密鑰 // 如需使用敏感接口(如退款、發送紅包等)需要配置 API 證書路徑(登錄商戶平台下載 API 證書) 'cert_path' => 'V6/wechatpay/apiclient_cert.pem', // XXX: 絕對路徑!!!! 'key_path' => 'V6/wechatpay/apiclient_key.pem', // XXX: 絕對路徑!!!! 'notify_url' => $this->webHost.'/zhonglian/zl/pay_notify', // 你也可以在下單時單獨設置來想覆蓋它 ]; $this->app = Factory::officialAccount($this->config); $this->minApp = Factory::miniProgram($this->minConfig); $this->pay = Factory::payment($this->wechatPay); } }
Pay
<?php namespace app\zhonglian\controller\wechat; use app\zhonglian\controller\wechat\WechatPublic; use app\zhonglian\model\UserAccessToken; use app\zhonglian\model\UserZhonglianOrder; use think\Controller; use EasyWeChat\Foundation\Application; use think\exception\ValidateException; use EasyWeChat\Factory; use EasyWeChat\Kernel\Messages\Text; use think\facade\Log; use app\zhonglian\validate\Pay as PayV; class Pay extends WechatPublic{ public function pay(){ if(request()->isPost()){ $data = input('post.'); try { validate(PayV::class) ->scene('pay') ->check($data); } catch (ValidateException $e) { // 驗證失敗 輸出錯誤信息 return json(['code'=>10001,'msg'=>$e->getError()]); } $data['orderId'] = date('YmdHis', time()).rand(10000,99999); $data['userId'] = UserAccessToken::where('accessToken',$data['access_token'])->value('userId'); //存入數據至本地表 $res = UserZhonglianOrder::addData($data); $result = $this->pay->order->unify([ 'body' => $data['body'], 'out_trade_no' => $date['orderId'], 'total_fee' => floatval($data['total_fee'] * 100), 'spbill_create_ip' => '', // 可選,如不傳該參數,SDK 將會自動獲取相應 IP 地址 'notify_url' => $this->webHost.'/zhonglian/zl/pay_notify', // 支付結果通知網址,如果不設置則會使用配置里的默認地址 'trade_type' => 'JSAPI', // 請對應換成你的支付方式對應的值類型 'openid' => $data['openid'], ]); /*$result返回數據如下 $result = [ "return_code" => "SUCCESS", "return_msg" => "OK", "appid" => "****************", "mch_id" => ""****************",", "nonce_str" => "oYRmqEGsfV95H221", "sign" => "37DC4CB564102893FC8C09C488D2FA00", "result_code" => "SUCCESS", "prepay_id" => "wx0411540670981758f0ccc5845afd110000", "trade_type" => "JSAPI" ]; */ if($result['return_code'] != 'SUCCESS' || $result['result_code'] != 'SUCCESS'){ return json(['code'=>1,'msg'=>'獲取支付訂單失敗']); }else{ if ($res) { $jssdk = $this->pay->jssdk; $config = $jssdk->bridgeConfig($result['prepay_id'], false); return json(['code'=>0,'data'=>$config]); } else { return json(['code'=>1,'msg'=>'創建訂單失敗!']); } } /*$config返回如下 [ 'appId' => 'wx9ae6b16168110e36', 'timeStamp' => '1604475465', 'nonceStr' => '5fa25a49a887b', 'package' => 'prepay_id=wx0411540670981758f0ccc5845afd110000', 'signType' => 'MD5', 'paySign' => 'A332227D36EC94B3610A86C8049F069C', ] */ } } //支付回調 public function pay_notify(){ $response = $this->pay->handlePaidNotify(function($message, $fail){ $order = Db::name('order')->where(['order'=> $message['out_trade_no']])->find(); if (!$order || $order['status']==2) { // 如果訂單不存在 或者 訂單已經支付過了 return true; } if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信狀態,不代表支付狀態 // 用戶是否支付成功 if ($message['result_code'] === 'SUCCESS') { //成功處理操作 略
//$message['out_trade_no'] 商戶訂單號
// 用戶支付失敗 } elseif ($message['result_code'] === 'FAIL') { return true; } } else { return false; } }); return $response; }
public function get_openid() { $code = $this->request->param('code'); $res = $this->app->auth->session($code); return json($res); }
}
小程序
getUserInfo: function (e){ var that = this; if (e.detail.userInfo) { wx.login({ success: res_user => { http.Get("/zhonglian/zl/get_openid", {code:res_user.code}, function (res) { console.log(res.data) wx.setStorageSync('openid', res.data.openid); wx.setStorageSync('nickname', e.detail.userInfo.nickName); wx.setStorageSync('image', e.detail.userInfo.avatarUrl); wx.setStorageSync('sex', e.detail.userInfo.gender); that.setData({login:false}) }); } }) } else { console.log('用戶拒絕了授權') wx.showToast({ title: "為了您更好的體驗,請同意授權登陸", icon: 'none', duration: 2000 }); } }, pay:function (){ var that = this var formData = { access_token: '***********', total_fee: 0.01, openid: wx.getStorageSync('openid'), body: '支付產品', } http.Post("/zhonglian/zl/pay", formData, function (res) { console.log(res.data); console.log('調起支付'); wx.requestPayment({ 'timeStamp': res.data.timeStamp, 'nonceStr': res.data.nonceStr, 'package': res.data.package, 'signType':'MD5', 'paySign': res.data.paySign, 'success':function(resa){ console.log('支付成功') }, 'fail':function(err){ console.log('支付失敗'); } }); }); },