在項目中用到小程序支付,費話不多說上代碼
因為我這涉及么微信的很多開發功能 所以我把公共的方法放到的公共類中
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('支付失敗');
}
});
});
},
