随着微信小程序越来越广泛的应用,现在小程序几乎无所不能(绝对啦,哈哈),那么就会有很多微信小程序需要有支付的需求,那么该文章将带领大家走一遍如何实现微信小程序的支付功能.
第一步,微信小程序管理后台 -> 微信支付->接入微信支付 及关联(设置)商户信息
如果是第一次接入, 直接申请接入,然后选择弹出窗口的"我还没有商户号"选项接入即可
接入商户,过程比较简单,随着指引一步一步走即可. 做完引导后所需的工作后,你需要确认做下面的两步,因为在后面的code时需要:
1.设置支付授权目录: 依次找到 商户平台->产品中心->开发配置,然后点击下面的添加进行添加支付目录
个人感觉类似微信小程序开发添加的request合法域名, 上面添加的这个目录,应该和你在后期在程序后台写的最终方法调用名一致,假设这里你设置的是 https://abc.cn/mypay/payOP
2. 设置API密钥: 依次找到 商户平台->账号中心->API安全->设置APIv2密钥 设置后,可以把密钥拷贝出来记住,下面的code部分也需要该信息
第二步:开发小程序的支付页面,此处只简单介绍页面,重点介绍js部分
1.配置页面信息, 假设页面只有一个输入金额的输入框,加一个按钮,那么在点击按钮后,执行js的操作部分如:
formSubmit:function(e){
let pp = e.detail.value;
if(pp.money.trim()=="")
{
wx.showToast({
title: "请输入捐赠金额!", //显示文本
icon: 'none', //使用图标
duration: 1000 //显示时间
})
return false;
}
// 注意,下面的reqest代码部分,that.data.userInfo.wid存储的就是当前用户的openid,这个信息一般会在用户登录后进行了存储,如果你没有存储,可以通过wx.login去获取,此处不再赘述
let that = this;
wx. request({
url:'刚刚在上面设置的安全支付目录地址/'+that.data.userInfo.wid+'/'+pp.money,
header: {
'content-type': 'application/json' // 默认值
},
success: function (ress){
// success
let res = ress.data;
if (res.status){
let out_trade_no = res.out_trade_no;//记录商户订单号 ,为后续缴费成功回调做记录
wx.requestOrderPayment ({
'timeStamp': res.timeStamp,
'nonceStr': res.nonceStr,
'package': res.package,
'signType': 'MD5',
'paySign': res.paySign,
'success': function(res3){
wx.showToast({
title: "支付成功,感谢您的善心!",
icon: 'success', //使用图标
duration: 1000 //显示时间
})
//此处负责回调,把先前的订单状态值为已付款
},
'fail':function (res2){
console.log (res2);
}
})
}
},
fail: function () {
//后台没连上
} ,
complete: function () {
// 处理结束
}
})
},
第三步: 服务器后台代码部分,这里以php为例进行讲解,其它语言可以适当翻译改动
//支付调用的主函数, 名称需要和设置的商户支付授权目录一致
public function payOP(){
//获取opid和fee
$wid= $this->uri->segment(3,0); //获取小程序传过来的openid
$fee = $this->uri->segment(4,0);//获取小程序传过来的捐款
//设置参数
$appid = 'xxxxx';//小程序的appid ,如果是公众号 就是公众号的appid
$body = '本次支付的介绍,文字信息随便写';
$mch_id = '商户平台登录账号';
$nonce_str = $this->nonce_str();//随机字符串,下面会提供函数
$notify_url = '微信支付回调函数,说实话这个没啥用,不设应该不行,你就设置成你的reqest域名吧';
$openid = $wid;//当前支付用户的openid
$out_trade_no = date('YmdHis_', time()).ceil(microtime()*1000);//商户订单号,需唯一
$spbill_create_ip = '114.114.114.114';//随便一个真实存在的ip,必须要设置
$total_fee = $fee*100;//因为充值金额最小是1 而且单位为分 如果是充值1元所以这里需要*100
$trade_type = 'JSAPI';//交易类型 默认
//这里是按照顺序的 因为下面的签名是按照顺序 排序错误 肯定出错
$post['appid'] = $appid;
$post['body'] = $body;
$post['mch_id'] = $mch_id;
$post['nonce_str'] = $nonce_str;//随机字符串
$post['notify_url'] = $notify_url;
$post['openid'] = $openid;
$post['out_trade_no'] = $out_trade_no;
$post['spbill_create_ip'] = $spbill_create_ip;//终端的ip
$post['total_fee'] = $total_fee;//总金额 最低为一块钱 必须是整数
$post['trade_type'] = $trade_type;
$sign = $this->sign($post);//签名
$post_xml = '
'.$appid.'
'.$body.'
'.$mch_id.'
'.$nonce_str.'
'.$notify_url.'
'.$openid.'
'.$out_trade_no.'
'.$spbill_create_ip.'
'.$total_fee.'
'.$trade_type.'
'.$sign.'
';
//统一接口prepay_id
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
$xml = $this->http_request($url,$post_xml);
$array = $this->xml($xml);//全要大写
if($array['RETURN_CODE'] == 'SUCCESS' && $array['RESULT_CODE'] == 'SUCCESS'){
$time = time();
$tmp='';//临时数组用于签名
$tmp['appId'] = $appid;
$tmp['nonceStr'] = $nonce_str;
$tmp['package'] = 'prepay_id='.$array['PREPAY_ID'];
$tmp['signType'] = 'MD5';
$tmp['timeStamp'] = "$time";
$data['status'] = true;
$data['timeStamp'] = "$time";//时间戳
$data['nonceStr'] = $nonce_str;//随机字符串
$data['signType'] = 'MD5';//签名算法,暂支持 MD5
$data['package'] = 'prepay_id='.$array['PREPAY_ID'];//统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*
$data['paySign'] = $this->sign($tmp);//签名,具体签名方案参见微信公众号支付帮助文档;
$data['out_trade_no'] = $out_trade_no;
echo json_encode($data);
}else{
$data['status'] = false;
$data['text'] = "错误";
$data['RETURN_CODE'] = $array['RETURN_CODE'];
$data['RETURN_MSG'] = $array['RETURN_MSG'];
echo json_encode($data);
}
}
下面是一些上述代码需要调用的函数
//随机32位字符串
private function nonce_str(){
$result = '';
$str = 'QWERTYUIOPASDFGHJKLZXVBNMqwertyuioplkjhgfdsamnbvcxz';
for ($i=0;$i<32;$i++){
$result .= $str[rand(0,48)];
}
return $result;
}
//签名 $data要先排好顺序
private function sign($data){
$stringA = '';
foreach ($data as $key=>$value){
if(!$value) continue;
if($stringA) $stringA .= '&'.$key."=".$value;
else $stringA = $key."=".$value;
}
$wx_key = '***************';//这里就是我上面讲解的设置了API的那个密钥 !!!
$stringSignTemp = $stringA.'&key='.$wx_key;
return strtoupper(md5($stringSignTemp));
}
private function xml($xml)
{
$p = xml_parser_create();
xml_parse_into_struct($p, $xml, $vals, $index);
xml_parser_free($p);
$data = "";
foreach ($index as $key=>$value) {
if($key == 'xml' || $key == 'XML') continue;
$tag = $vals[$value[0]]['tag'];
$value = $vals[$value[0]]['value'];
$data[$tag] = $value;
}
return $data;
}
private function http_request($url,$data = null,$headers=array())
{
$curl = curl_init();
if( count($headers) >= 1 ){
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
}
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
if (!empty($data)){
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($curl);
curl_close($curl);
return $output;
}
上述代码是亲测有效并且能正常支付的,请需要的朋友拿去测试, 我是活雷锋,不谢