最近做了微信小程序的支付功能,实现了微信支付
支付流程
资料参考 => 微信支付关于小程序文档
官方文档也给出了实践步骤
商户系统和微信支付系统主要交互:
1、小程序内调用登录接口,获取到用户的openid,api参见公共api【小程序登录API】
2、商户server调用支付统一下单,api参见公共api【统一下单API】
3、商户server调用再次签名,api参见公共api【再次签名】
4、商户server接收支付通知,api参见公共api【支付结果通知API】
5、商户server查询支付结果,api参见公共api【查询订单API】
.
注意,这里文档部分文字说明其实是有问题的,跟着下面的步骤就行
小程序端获取身份token
在微信小程序端,调用登录接口,获取到凭证
wx.login({
success:(res)=> {
if (res.code) {
data.code = res.code;
// 发起网络请求
this.payRequest(data);
} else {
wx.reLaunch({
url: '这里填入你要跳转的地址',
});
}
}
})
这里的 data
是一些之前保存的支付信息,如支付金额,产品的 id
等等,传给 payRequest
,向后端 api
发起支付
服务器端PHP实现发起微信支付
1. 获取用户 openid
因为小程序微信支付,使用的也是 JSAPI
的方式,参数要求需要用户的 openid
$params = [
'appid' => \WxPayConfig::APPID,
'secret' => \WxPayConfig::APPSECRET,
'js_code' => $data['code'],
'grant_type' => 'authorization_code',
];
// 发起请求
$url = 'https://api.weixin.qq.com/sns/jscode2session?'. http_build_query($params);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
$userData = curl_exec($ch);
curl_close($ch);
$userData = json_decode($userData, true);
if (!$userData['openid']) {
$this->jsonReturn(602, 'get user openid fail');
}
返回示例:
{
"session_key":"RF***********KS23w==",
"openid":"oSEc75A*************B_2338",
"unionid":"oS***********Ly238"
}
我这里的 APPID
APPSECRET
是保存在 SDK
配置文件中的,下一步会说到,文档参考 => code2Session
这里的 jsonReturn
是我自己封装的接口返回函数,你也可以直接
echo json_encode([200, 'success', $data]);
你可以自己简单的封装
public function jsonReturn($code, $msg, $data)
{
$returnData = [
'code' => $code,
'msg' => $msg
];
if ($data) {
$returnData['code'] = $data;
}
echo json_encode($returnData);
exit;
}
2. 统一下单
在同一下单之后或者之前,一般都会在自己数据库中保存一份订单信息,这里就不做举例,根据自己实际情况操作就行
微信关于统一下单的文档链接: 统一下单
官方也提供了 SDK
给我们: 微信支付SDK
主要使用的是 lib
文件夹下,当然也提供了示例给你参考
将 lib
目录直接拷贝一份,重新命名放入你框架对应的扩展库中,并在代码中引入 Api
类
WxPay.Config.php
const APPID = 'wxa7*******13asdf';
const MCHID = '1*******4sdf';
const KEY = 'asdc6c5*******b65asdf';
const APPSECRET = '060******5csdf';
配置好小程序的 APPID
APPSECRET
, MCHID
和 KEY
则和公众号微信支付一样就行,也就是现在所谓的商户平台上面的
WxPay.Api.php
require_once "WxPay.Exception.php";
require_once "WxPay.Config.php";
require_once "WxPay.Data.php";
require_once "WxPay.Notify.php";
这里修改 WxPay.Api.php
文件,将 Notify
类也引入,然后控制器中只要引入 Api
类就行了
// 统一下单
$order = new \WxPayUnifiedOrder();
$order->SetBody('商品简要描述'); //设置商品或支付单简要描述
$order->SetAttach('商品属性描述,主要用户商家自定义数据');
$order->SetOut_trade_no('商家订单号');
$order->SetTotal_fee('金额,注意微信支付是以分为单位');
$order->SetOpenid('上面得到的openid');
$order->SetTime_start(date("YmdHis"));
$order->SetTime_expire(date("YmdHis", $time + 600));
$order->SetNotify_url("你的支付回调地址");
$order->SetTrade_type("JSAPI");
$orderResult = \WxPayApi::unifiedOrder($order);
具体的参数设置,你可以参考 Api
文档,根据自己需要设置哪些参数
返回示例:
{
"appid":"************a0b4",
"mch_id":"********01",
"nonce_str":"********qbT",
"prepay_id":"**********3358",
"result_code":"SUCCESS",
"return_code":"SUCCESS",
"return_msg":"OK",
"sign":"***********8DD9F39CA185",
"trade_type":"JSAPI"
}
解析下单返回的结果,得到小程序微信支付所需要的参数
$JsApiPay = new \JsApiPay();
$params = $JsApiPay->GetJsApiParameters($orderResult);
返回示例:
{
"appId":"**********b4",
"nonceStr":"***************0mw9p5",
"package":"*******************621705",
"signType":"MD5",
"timeStamp":"**2296891",
"paySign":"************4F253B"
}
3. 小程序发起支付
参考文档: 小程序支付
wx.requestPayment({
timeStamp: data.timeStamp,
nonceStr: data.nonceStr,
package: data.package,
signType: data.signType,
paySign: data.paySign,
success: (res)=> {
wx.showToast({
title: '成功',
icon: 'success'
})
},
fail: (res)=> {
if (res.errMsg == 'requestPayment:fail cancel') {
wx.showToast({
title: '您已取消支付',
icon: 'none',
success: function() {
setTimeout(function(){
wx.navigateBack({
delta: 1,
});
}, 1500);
}
});
}else {
wx.showToast({
title: '支付失败',
icon: 'none'
})
}
}
});
总结
如果你的 SDK
内容和我的不一样,可能是 版本更新的问题,但是流程一样,自己稍加研究就能完成,灵活运用
另外再贴下我当初查资料参考的博客文章:详解微信小程序支付流程