小程序开发 —— 微信支付
小程序很好入门,做一个完整的商城也很方便。
对于微信产品,用微信支付也是顺理成章的。
本文的后台用 Laravel 实现(easywechat)。
一、前期准备
1、小程序 appid;
2、微信商户号;
3、商户秘钥;
二、小程序部分
1、支付按钮绑定 pay 事件
<button bindtap="pay" data-oid="{{item.order_id}}">付款</button>
2、编写 pay 方法
思路:调用后台接口返回一些数据,然后在小程序端调用 wx.requestPayment 返回支付结果是否成功。
/**
* 付款
*/
pay: function (e) {
wx.request({
url: app.globalData.baseUrl + 'api/wechat/pay',
method: 'POST',
data: {
openId: app.globalData.openid,
orderId: e.currentTarget.dataset.oid,
appId: app.globalData.appId
},
header: {
'Content-Type': 'application/json'
},
success: function (res) {
var data = res.data.data;
wx.requestPayment({
'timeStamp': data.timeStamp,
'nonceStr': data.nonceStr,
'package': data.package,
'signType': data.signType,
'paySign': data.paySign,
'success': function (res) {
wx.showToast({
title: '支付成功',
icon: 'success',
duration: 2000
});
},
'fail': function (res) {
wx.showToast({
title: '支付失败',
icon: 'none',
duration: 2000
});
}
});
}
})
},
三、后台部分
思路:安装 wechat 开发包,配置小程序及支付信息,调用方法生成支付订单,进行二次签名返回数据给小程序。
1、安装 wechat 开发包
composer require overtrue/wechat -vvv
php artisan vendor:publish --provider="Overtrue\LaravelWeChat\ServiceProvider"
2、配置基本信息
在第一步生成的 config/wechat.php 文件中,修改成自己的信息。
/*
* 小程序配置
*/
'mini_program' => [
'default' => [
'app_id' => env('WECHAT_MINI_PROGRAM_APPID', ''),
'secret' => env('WECHAT_MINI_PROGRAM_SECRET', ''),
'token' => env('WECHAT_MINI_PROGRAM_TOKEN', ''),
'aes_key' => env('WECHAT_MINI_PROGRAM_AES_KEY', ''),
],
],
/*
* 微信支付配置
*/
'payment' => [
'default' => [
'sandbox' => env('WECHAT_PAYMENT_SANDBOX', false),
'app_id' => env('WECHAT_PAYMENT_APPID', ''),
'mch_id' => env('WECHAT_PAYMENT_MCH_ID', 'your-mch-id'),
'key' => env('WECHAT_PAYMENT_KEY', 'key-for-signature'),
'cert_path' => env('WECHAT_PAYMENT_CERT_PATH', 'path/to/cert/apiclient_cert.pem'),
'key_path' => env('WECHAT_PAYMENT_KEY_PATH', 'path/to/cert/apiclient_key.pem'),
'notify_url' => 'http://example.com/payments/wechat-notify', // Default payment result notification address
],
// ...
],
3、支付功能
public function __construct(Request $request
, Order $order){
$wechat = \EasyWeChat::miniProgram();
$pay = \EasyWeChat::payment();
$this->wechat = $wechat;
$this->pay = $pay;
$this->request = $request;
$this->order = $order;
}
/**
* 通过 js_code 获取 openid
*/
public function getOpenId(){
$code = $this->request->js_code;
$out = $this->wechat->auth->session($code);
return $this->success($out);
}
/**
* wechat pay
*/
public function pay(){
$appid = $this->request->appId;
$openid = $this->request->openId;
$orderid = $this->request->orderId;
$order = $this->order->findOrFail($orderid);
if(! $order){
return $this->failed('order is not exist!');
}
// generate order
$out = $this->pay->order->unify([
'body' => 'order name', // order name
'out_trade_no' => $order->order_num, // order number
'trade_type' => 'JSAPI', // must 'JSAPI'
'openid' => $openid, // user openid
'total_fee' => $order->price, // order total price
]);
// second sign
if($out['return_code'] == 'success'){
$param = [
'appId' => $appid,
'timeStamp' => time(),
'nonceStr' => $out['nonce_str'],
'package' => 'prepay_id=' . $out['prepay_id'],
'signType' => 'MD5',
];
// 注意文件最上面添加 use function EasyWeChat\Kernel\Support\generate_sign;
$params['paySign'] = generate_sign($params, config('wechat.payment.default.key'));
return $this->success($param);
}else{
return $this->failed('wechat pay failed!');
}
}
4、支付结果通知
支付回调路径在上面配置文件中已经设置好了。
/**
* payment result notify
*/
public function notify(){
$res = $this->wechat->handlePaidNotify(function($message, $fail){
// find order
$order = $this->order->where('order_num', $message['out_trade_no'])->get();
if(!$order || $order->status == 3){
return true;
}
// payment finish
if($message['return_code'] == 'SUCCESS'){
// payment success
if($message['result_code'] == 'SUCCESS'){
$order->status = 3;
$order->save();
// payment fail
}elseif($message['result_code'] == 'FAIL'){
return $fail('payment fail');
}
}else{
return $fail('connect fail');
}
return true;
});
$res->send();
}
四、调试
。。