业务场景:用户点击会员中心的不同等级,进行支付
前台代码:
参数解释:
用户点击对应等级时,对应获取到需要支付的金额,在获取到用户的对应id和openid
这里的openid和user_id都是在用户登录授权后获取的信息
/*
* author:咔咔
* address:陕西西安
* wechat:fangkangfk
* content:微信小程序支付
* */
pay: function (e) {
// 获取到需要支付的价钱
var price = e.currentTarget.dataset.price;
var user_id = wx.getStorageSync('user_id');
// 验证是否获取到值
if (typeof (price) == "undefined") {
wx.showToast({
title: '支付数据错误'
})
return false;
}
//后台订单生成
wxb.Post('/api/automatic.pay/creatOrder', {
openid: wxb.getOpenId(),
price: price,
user_id: user_id
}, function (data) {
var data = JSON.parse(data);
console.log(data)
wx.requestPayment({
'timeStamp': data.timeStamp,
'nonceStr': data.nonceStr,
'package': data.package,
'signType': 'MD5',
'paySign': data.paySign,
'success': function (res) {
wxb.Post('/api/cards.member/confirm_integral', {
// 支付成功的业务逻辑代码
}, function (datas) {
wx.redirectTo({
url: '/pages/mine/index'
})
});
},
'fail': function (res) {
wxb.Post('/api/cards.member/confirm_integral', {
// 支付失败或者取消支付代码
}, function (datas) {
});
}
});
});
},
后台代码:
获取到前台传的数据,进行创建订单,在进行请求获取统一下单的数据
public function creatOrder(){
$orderData = $this->request->param();
$opneid = $orderData['openid'];
if($orderData['user_id']){
//appid
$data['member_miniapp_id'] = $orderData['appid'];
//支付金额
$data['pay_money'] = $orderData['price'];
//用户id
$data['user_id'] = $orderData['user_id'];
$orderModel = new OrderModel();
$order = $orderModel->save($data);
if($order){
//获取到订单id
$orderId = $orderModel->order_id;
//支付的金额
$orderPrice = $orderModel->pay_money;
}
if($orderId>=0){
$orderinfo = $this->buy($opneid);
$this->result($orderinfo, 200, '订单生成成功', 'json');
}
}
}
public function buy($opneid){
$params = [
'appid' => '小程序id',
'mch_id' => '商户号',
// 随机串,32字符以内
'nonce_str' => (string) mt_rand(10000, 99999),
// 商品名
'body' => '购买vip',
// 订单号,自定义,32字符以内。多次支付时如果重复的话,微信会返回“重复下单”
'out_trade_no' => '20170823001' . time(),
// 订单费用,单位:分
'total_fee' => 1,
'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
// 支付成功后的回调地址,服务端不一定真得有这个地址
'notify_url' => 'https://myserver.com/notify.php',
'trade_type' => 'JSAPI',
// 小程序传来的OpenID
'openid' =>$opneid,
];
// 按照要求计算sign
ksort($params);
$sequence = '';
foreach ($params as $key => $value) {
$sequence .= "$key=$value&";
}
$sequence = $sequence . "key=你的秘钥";
$params['sign'] = strtoupper(md5($sequence));
// 给微信发出的请求,整个参数是个XML
$xml = '' . PHP_EOL;
foreach ($params as $key => $value) {
$xml .= "<$key>$value$key>" . PHP_EOL;
}
$xml .= ' ';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.mch.weixin.qq.com/pay/unifiedorder');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$output = curl_exec($ch);
if (false === $output) {
echo 'CURL Error:' . curl_error($ch);
}
// 下单成功的话,微信返回个XML,里面包含prepayID,提取出来
if (0 === preg_match('/<\!\[CDATA\[(\w+)\]\]><\/prepay_id>/', $output, $match)) {
echo $output;
exit(0);
}
// 这里不是给小程序返回个prepayID,而是返回一个包含其他字段的JSON
// 这个JSON小程序自己也可以生成,放在服务端生成是出于两个考虑:
//
// 1. 小程序的appid不用写在小程序的代码里,appid、secret信息全部由服务器管理,比较安全
// 2. 计算paySign需要用到md5,小程序端使用的是JavaScript,没有内置的md5函数,放在服务端计算md5比较方便
$prepayId = $match[1];
$response= [
'appId' => '小程序id',
// 随机串,32个字符以内
'nonceStr' => (string) mt_rand(10000, 99999),
// 微信规定
'package' => 'prepay_id=' . $prepayId,
'signType' => 'MD5',
// 时间戳,注意得是字符串形式的
'timeStamp' => (string) time(),
];
$sequence = '';
foreach ($response as $key => $value) {
$sequence .= "$key=$value&";
}
$response['paySign'] = strtoupper(md5("{$sequence}key=你的秘钥"));
return json_encode($response);
}
测试结果: