微信公众平台支付接口「」

微信公众平台支付接口

微信小程序支付流程

微信支付之小程序支付。
微信的支付方式有以下几种,不同的支付方式适用于不同的支付场景,而今天要给大家讲的就是小程序支付方式。
说到支付功能就要涉及到金钱交易,必定是有比较严格的规范及流程,如要求小程序必须具备企业性质,必须拥有微信支付商户平台的账号。
PS:申请微信支付商户平台需要一个微信小程序或公众号等,建议按照以下流程进行操作。
准备工作。
1、申请微信小程序账号。
申请成功可拿到AppID(小程序id)和AppSecret(小程序密钥)。
申请类型为企业性质,否则无法接入微信支付。
2、微信小程序认证。
通过认证的小程序才能接入微信支付和绑定商户平台。
3、申请商户平台账号。
需要第一步申请的AppID。
申请成功可拿到MchID(商户id)和MchKey(商户密钥)。
4、信小程序关联商户号。
微信和商户都认证成功后,在微信后台微信支付菜单中进行关联。
5、接入微信支付。
在微信后台微信支付菜单中进行接入。
小程序支付流程。
简要支付流程如下:
用户发起支付请求后端调用统一下单接口得到prepay_id把支付所需参数返回前端前端调用支付接口进行支付操作支付结果通知前端根据不同的支付结果给用户不同的提示。
PS:难点在第2、3、5步,一定要仔细查看相关接口文档,否则容易出错,接下来我们按照以上6个步骤详细讲解在微信小程序中的支付流程。
支付前的操作。
因为严格意义上来说这不属于支付流程中的步骤,但支付过程中需要用到用户唯一标识openid,所以建议在用户进入小程序时就进行这一步的操作。
调用wx.login()接口获取code,并把code传到服务器后端服务器拿到code后调用code2Session接口获取openid和session_key。
建议把openid存入数据库,方便随时获取,下面的步骤也会用到后端服务器保好appid,secret,mch_id,mch_key(这些数据分别在小程序后台和商户平台中获得,我是把它们做成commonjs模块并保存在config/wx.js文件中以方便调用)。
PS:开发者需要自行维护用户登录状态(用户登录状态的维护本文不做展开,请自行查阅相关资料)。

微信公众平台支付接口(网络配图)

微信公众平台支付接口(网络配图)

1、小程序端:用户向商户服务器发起支付请求。
这步没什么好说的,当用户点击支付按钮时,给我们自己的后端接口发起一个请求,携带必要的参数(如:body,total_fee等),接口地址需要自行编写,如我的接口地址为/payment/order。
//http对象为wx.request()的二次封装importhttpfrom"../utils";​//向后端发请请求constres=awaithttp.post("/payment/order",{body:"腾讯QQ-购买会员",//商品描述total_fee:998,//总金额,单位为分});if(res.status===200){try{//得到接口返回的数据,向微信发起支付constresult=awaitwx.requestPayment({...res.data,});wx.showToast({title:"支付成功",});console.log("支付结果:",result);}catch(err){wx.showToast({title:"支付失败",});}}。
PS:可能会有小伙伴产生疑惑,为什么不直接通过wx.requestPayment()在小程序端发起请求而要先请求商户自己的服务器呢?原因很简单,安全性问题,wx.requestPayment()需要2个重要参数paySign和package,需要appid,secret,openid,mch_key等私密数据,这些私密的数据不应该在前端暴露出来,而是放在自己的服务器中更安全,所以需要向自己的服务器发起这个请求拿到这些参数,下一步才能真正发起支付。接下来我们来看看后端是如果操作的。
2、商户后端服务器:签名生成预支付标识。
后端代码使用egg框架(基于NodeJSKoa)实现,文中涉及到egg用法和koa的用法不再额外说明,请自行查阅相关资料。
调用统一下单接口获取预支付会话标识prepay_id。
注意:该接口需要发送xml格式参数,同时返回xml格式数据,需自行转换(我使用的是xml-js第三方模块)。
该接口必填参数:appid,mch_id,nonce_str,sign_type,body,out_trade_no,total_fee,spbill_create_ip,notify_url,trade_type,sign,其中sign为前面所有参数加密后的字符。
asyncorder(ctx){//egg框架写法const{service,request}=ctx;//获取前端传入参数const{userid,total_fee,body}=request.body;//引入微信配置参数(上面准备工作中保存的config/wx.js文件,包含小程序id,密钥,商户id,商户密钥)const{config}=require("../../config/wx");//生成订单号(保证唯一性:我采用时间戳拼6位随机数的方式)consttradeNo=Date.now()''randomCode(100000,999999);//统一下单签名参数constorderParams={appid:config.appid,//小程序idmch_id:config.mch_id,//商户idnonce_str:service.wx.randomStr(),//自定义生成随机字符方法sign_type:"MD5",//加密类型body,//商品简单描述,有格式要求out_trade_no:tradeNo,//订单号total_fee,//单位:分spbill_create_ip:"121.34.253.98",//服务器ipnotify_url:"https://你的服务器域名/payment/wxnotify",//支付成功通知地址trade_type:"JSAPI",//支付方式(小程序支付选JSAPI)openid:user.openid,//用户openid,步骤0保存的数据};//签名:对上面所有参数加密(签名算法请查看接口文档,下同)constorderSign=service.wx.sign(orderParams);//json->xmlconstxmlData=convert.js2xml({xml:{...orderParams,sign:orderSign}},{compact:true});//调用统一下单接口(接口没说明,但必须为post请求)const{data}=awaitctx.curl("https://api.mch.weixin.qq.com/pay/unifiedorder",{method:"post",data:xmlData,});//xml->jsconstresult=convert.xml2js(data,{compact:true});if(result.prepay_id){//此处可以把订单信息保存到数据库//返回prepay_id后,接着就是把参数返回前端//=>为了更清晰,我把这里的代码写在下一步//...}}。

微信公众平台支付接口(网络配图)

微信公众平台支付接口(网络配图)

3、给前端返回支付参数签名。
//支付签名参数constpayParams={appId:config.appid,//商户idtimeStamp:Date.now(),//时间戳nonceStr:this.randomStr(),//随机字符package:"prepay_id="result.prepay_id,//预支付会话标识(格式为:prepay_id=统一下单接口返回数据)signType:"MD5",//签名类型(必须与上面的统一下单接口一致)};//签名constpaySign=service.wx.sign(payParams);​//把参数签名返回给前端ctx.body=formatData({data:{timeStamp:payParams.timeStamp,nonceStr:payParams.nonceStr,package:payParams.package,signType:payParams.signType,paySign,},})。
附上封装好的签名方法sign()和生成随机字符串的方法randomStr(),我写在service/wx.js。
"usestrict";const{Service}=require("egg");constcrypto=require("crypto");//微信基本配置const{weapp}=require("../../config/wx");classwxServiceextendsService{randomStr(len=24){conststr="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";letresult="";for(leti=0;i<len;i){result=str[Math.floor(Math.random()*str.length)];}returnresult;}sign(data,signType="MD5"){constkeys=[];for(constkeyindata){if(data[key]!==undefined){keys.push(key);}}//字典排序=>key=valueconststringA=keys.sort().map((key)=>`${key}=${decodeURIComponent(data[key])}`).join("&");//拼接商户keyconststringSignTemp=stringA"&key="weapp.mch_key;console.log("stringSignTemp",stringSignTemp);//加密lethash;if(signType==="MD5"){hash=crypto.createHash("md5");}else{hash=crypto.createHmac("sha256","laoxie");}hash.update(stringSignTemp);constpaySign=hash.digest("hex").toUpperCase();returnpaySign;}}module.exports=wxService。
4、小程序端:向微信服务器发起请求。
第1步的数据返回后,向微信服务器接口wx.requestPayment()发请求,唤起支付界面,请查看第一步try...catch中的代码。
5、微信服务器:支付结果通知。
在第2步向统一下单接口发起请求时附带了一个notify_url,此地址一定要是可外网访问的接口地址(商户自行编写),由微信服务器调用该接口,不管支付成功与否,此接口都会调用,并返回相应数据(查看接口数据),所以商户可以在此接口中编写相关业务逻辑、如支付成功后写入数据库等操作。

微信公众平台支付接口(网络配图)

微信公众平台支付接口(网络配图)

注意:商户需要在此接口中做接收处理,并向微信服务器返回应答(按接口规范返回特定数据)。如果微信收到商户的应答不是成功或超时,微信会认为通知失败,微信会通过一定的策略定期重新发起通知,通知频率为:15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h,但微信不保证通知最终一定能成功。
"usestrict";​constController=require("egg").Controller;constgetRawBody=require("raw-body");constcontentType=require("content-type");const{formatData,randomCode,params,formatParams}=require("../utils");​classPaymentControllerextendsController{//微信支付回调地址asyncnotify(ctx){const{req}=ctx;​//微信调用该接口时传入的数据为xml,所以先转换constdata=awaitgetRawBody(req,{length:req.headers["content-length"],limit:"1mb",encoding:contentType.parse(req).parameters.charset,});constresult=params.xml2js(data);​//验签:微信传入的除sign外的所有数据进行签名,拒后与sign进行对比是否一致//一致说明支付成功,否则支付失败//并根据不同的结果通知微信服务器(响应不同的xml数据,如下)constresultSign=result.sign;deleteresult.sign;constmySign=ctx.service.wx.sign(result);console.log("sign:",resultSign,mySign);​ctx.set("content-type","text/plain");​if(resultSign===mySign){//修改商户订单状态const{device_info,openid,trade_type,bank_type,total_fee,settlement_total_fee,fee_type,transaction_id,time_end,attach,}=result;​//格式化自定义参数letmyattach={};if(attach){myattach=params.parse(attach);}​//格式化支付时间:20200423161017=>2020/04/2316:10:17letpay_time=time_end.replace(/(d{4})(d{2})(d{2})(d{2})(d{2})(d{2})/,"$1/$2/$3$4:$5:$6");pay_time=newDate(pay_time);​//根据订单号更新数据库中的订单状态constnewData={device_info,openid,trade_type,bank_type,total_fee,settlement_total_fee,fee_type,transaction_id,pay_time,status:1,...myattach,};db.update("purchase",{out_trade_no:result.out_trade_no,},{$set:newData,});​ctx.body=`<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>`;}else{ctx.body=`<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[ERROR]]></return_msg></xml>`;}}}​module.exports=PaymentController。

微信公众平台支付接口(网络配图)

微信公众平台支付接口(网络配图)

附上以上代码中会用的封装好的方法parse()、xml2js()、js2xml(),我写在utils/index.js中。
constparams={parse(queryString){//'a=1&b=2'=>{a:1,b:2}returnqueryString.split("&").reduce((res,item)=>{constarr=item.split("=");res[arr[0]]=arr[1];returnres;},{});},js2xml(data){returnconvert.js2xml({xml:data},{compact:true});},xml2js(xml){constresult=convert.xml2js(xml,{compact:true,textKey:"value",cdataKey:"value",}).xml;constdata={};for(constkeyinresult){data[key]=result[key].value;}returndata;},};module.exports={params}。
到此微信支付之小程序支付就完成了,过程比较繁杂,一定要一步步去实现,也许会踩坑,但相信我,这是每个程序员的必经这路,面对它,勇敢地走过去,你对能到达胜利的彼岸。
注意事项appid、appsecret、mchid、mchkey、openid为小程序或商户私密信息,应保存在服务端注意参数大小写:每个接口大小写可能不同签名算法:请查看接口文档一定要注意看文档,根据我多冷踩坑的经历,90%以上的问题都是没有仔细看文档所致参考网址与接口微信支付商户平台:https://pay.weixin.qq.com微信公众平台:https://mp.weixin.qq.com微信支付接口:https://developers.weixin.qq.com/miniprogram/dev/api/open-api/payment/wx.requestPayment.html统一下单接口:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1支付结果通知接口:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_7&index=8签名算法:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_3。
[mp]https://mp.weixin.qq.com。
[pay]https://pay.weixin.qq.com。
[payment]https://developers.weixin.qq.com/miniprogram/dev/api/open-api/payment/wx.requestPayment.html。
[notify]https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_7&index=8。
[login]https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/wx.login.html。
[unifiedorder]https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1。
[code2session]https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html。
[sign]https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_3。

发表评论

免责声明:本站部分内容转载于网络,其中内容仅代表作者个人观点,与本网无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。若有来源标注错误或侵犯了您的合法权益,请作者持权属证明与本网联系,我们将及时更正、删除,谢谢。

本站联系邮箱:douxingdu02@163.co m