如微信支付的文档,不再多说
https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_4&index=3
一一分析一下每一步我们具体要做什么:
1、小程序内调用登录接口,获取到用户的openid,api参见公共api【小程序登录API】
一般我们在数据库保存了用户openid,所以我们是去数据库取。
2、商户server调用支付统一下单,api参见公共api【统一下单API】
这一步是拿到用户openid、订单详情等文档中要求的信息后,转换成xml格式(转换格式是有微信接口的),调用微信封装好的统一下单接口,便会返回包含prepay_id的一些参数。
3、商户server调用再次签名,api参见公共api【再次签名】
我认为这个步骤名称写的不好,“再次签名”的链接打开,标题写的却是调起支付API。实际上分两步:再次签名、调起支付API。就是说,获取到上一步的一些参数后,按照签名算法处理数据,然后调用微信API再次签名,这样就有了签名参数。最后将被要求的参数填入调起支付API就可以了。
4、商户server接收支付通知,api参见公共api【支付结果通知API】
在第二步的xml中要求填入我们服务器上的通知地址,这样第三步的微信支付结果就会发送到这个地址。 在这个方法里面,我们要校对微信发来的支付结果是哪个订单的,然后可以修改订单的支付状态,还要返回给微信接受成功的xml信息,不然微信会一直发通知过来。
5、商户server查询支付结果,api参见公共api【查询订单API】
查询支付订单详情见文章最后一块代码。
首先小程序要绑定商户,不然没法做也没法测试。
开通微信支付后,下载微信支付API的包(我用的是PHP)
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
用户已下单(还未付款),当用户点击付款时,执行PayOrder函数。
函数主要有三个请求接口:Order/get获取订单详情(省略)、Order/getPrepay(统一下单/再次签名/支付通知)、wx.requestPayment(发起微信支付)。
PayOrder: function(t) {
var that = this;
var order_id = t.currentTarget.dataset.id;//订单id
wx.request({
url: 'https://XX.com/Order/get',//这是获取订单详情的请求
data:{
id:order_id
},
success:function(a){
//统一下单并再次签名
wx.request({
url: 'https://wechat.cdd.jianfengweb.com/Order/getPrepay',
data: {
total_fee: a.data.data.total_price*100,
order_number: a.data.data.order_number,
},
success: function (res) {
// 返回参数和sign后调起微信支付
wx.requestPayment(
{
'timeStamp': new Date().getTime().toString(),
'nonceStr': res.data.data['nonce_str'],
'package': "prepay_id=" + res.data.data['prepay_id'],
'signType': 'MD5',
'paySign': res.data.data['sign'],
'success': function (e) {
console.log('success')
},
'fail': function (e) {
console.log(e)
},
'complete': function (e) { }
})
}
})
}
})
}
Order/getPrepay方法(统一下单、再次签名)
public function getPrepay()
{
extract(generateRequestParamVars());
//获取openid
$user = D(self::$WECHAT_USER_MODEL)->find($user_id);
$openid = $user['openid'];
//引用微信支付API
require_once C('APPLICATION_DIR') . '/Home/Libs/WechatPay/lib/WxPay.Api.php';
require_once C('APPLICATION_DIR') . '/Home/Libs/WechatPay/lib/WxPay.Notify.php';
require_once C('APPLICATION_DIR') . '/Home/Libs/WechatPay/lib/WxPay.Data.php';
require_once C('APPLICATION_DIR') . '/Home/Libs/WechatPay/example/log.php';
require_once C('APPLICATION_DIR') . '/Home/Libs/WechatPay/example/WxPay.NativePay.php';
require_once C('APPLICATION_DIR') . '/Home/Libs/WechatPay/example/WxPay.JsApiPay.php';
// WxPayUnifiedOrder类会直接设置xml
$xml = new \WxPayUnifiedOrder();
$xml->SetBody("购买商品");
$xml->SetAttach("attach");
$xml->SetOpenid($openid);
$xml->SetOut_trade_no($product_id);
$xml->SetTotal_fee($total_fee * 100);
$xml->SetTime_start(date("YmdHis", time()));
$xml->SetTime_expire(date("YmdHis", time() + 600));
$xml->SetNotify_url("https://XX.com/Order/getNotify");
$xml->SetGoods_tag("goods_tag");
$xml->SetTrade_type("JSAPI");
//统一下单(获取prepay_id)
$nativepay = new \NativePay();
$result = $nativepay->GetPayUrl($xml);
//再次签名
$sign_array = array();
$sign_array['appId'] = $result['appid'];
$sign_array['nonceStr'] = $result['nonce_str'];
$sign_array['package'] = 'prepay_id=' . $result['prepay_id'];
$sign_array['signType'] = 'MD5';
$sign_array['timeStamp'] = floor($result['startTimeStamp'] / 1000);
$sign = new \WxPayDataBase();
$sign_two = $sign->MakeSigns($sign_array);
$result['paySign'] = $sign_two;
$ajaxReturnData['data'] = $result;
$this->ajaxReturn($ajaxReturnData);
}
Order/getNotify方法(接收微信通知)
public function getNotify()
{
$xmlData = file_get_contents('php://input');
libxml_disable_entity_loader(true);
$data = json_decode(json_encode(simplexml_load_string($xmlData, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
ksort($data);
$buff = '';
foreach ($data as $k => $v) {
if ($k != 'sign') {
$buff .= $k . '=' . $v . '&';
}
}
$save = [];
foreach ($data as $k => $v) {
$save['key'] = $k . '';
$save['value'] = $v . '';
D(self::$NOTIFY_TEST)->add($save);
}
$stringSignTemp = $buff . 'key=1d8r14jiu58fs12qsd824j1o52d8r14c';//key为证书密钥
$sign = strtoupper(md5($stringSignTemp));
$conditions = [];
$conditions['order_number'] = $data['out_trade_no'];
$order = D(self::$ORDER_MODEL)->where($conditions)->find();
//判断算出的签名和通知信息的签名是否一致
if ($order && $sign == $data['sign'] && $order['total_price']*100 == $data['total_fee']) {
$test = [];
$test['key'] = '校验是否成功';
$test['value'] = 'yes';
D(self::$NOTIFY_TEST)->add($test);
$order_data = [];
$order_data['shop_status'] = 1;
D(self::$ORDER_MODEL)->where($conditions)->save($order_data);
//处理完成之后,告诉微信成功结果
echo '
';
exit();
}else{
echo '
';
exit();
}
}
Order/findOrder方法(查询支付订单)
public function findOrder()
{
try{
extract(generateRequestParamVars());
require_once C('APPLICATION_DIR') . '/Home/Libs/WechatPay/lib/WxPay.Api.php';
$input = new \WxPayOrderQuery();
$input->SetOut_trade_no($order_number); // 设置好要查询的订单
$order = \WxPayApi::orderQuery($input); // 进行查询
$ajaxReturnData['status'] = 1;
$ajaxReturnData['message'] = '操作成功';
$ajaxReturnData['data'] = $order;
}catch (\Exception $e){
$ajaxReturnData['status'] = 0;
$ajaxReturnData['message'] = '操作失败' . $e->getMessage();
}
$this->ajaxReturn($ajaxReturnData);
}