• 小程序支付详解


    和其他方式的微信支付方式区别不大,也都需要经过统一下单、支付结果通知(回调),具体流程如下:

    1、小程序内调用登录接口,获取到用户的openid,api参见公共api【小程序登录API

    2、商户server调用支付统一下单,api参见公共api【统一下单API

    3、商户server调用再次签名,api参见公共api【再次签名

    4、商户server接收支付通知,api参见公共api【支付结果通知API

    5、商户server查询支付结果,api参见公共api【查询订单API

    下面结合源码详解下流程:

    第一步: 获取客户的openid

    统一下单中需要用到openid

    小程序:

    首先需要调用微信登录接口获取用户的code:

    1. var that = this;

    2. wx.login({

    3. success: function(res) {

    4. that.getOpenId(res.code);

    5. }

    6. });

    通过code获取openid:

    01. //获取openid

    02. getOpenId: function(code){

    03. var that = this;

    04. wx.request({ 

    05. url: 'https://www.see-source.com/weixinpay/GetOpenId'

    06. method: 'POST',

    07. header: {

    08. 'content-type''application/x-www-form-urlencoded'

    09. },

    10. data: {'code':code},

    11. success: function(res) {

    12. var openId = res.data.openid;

    13. that.xiadan(openId);

    14. }

    15. })

    16. }

    java:

    1. String code = request.getParameter("code");

    2. HttpGet httpGet = new HttpGet("https://api.weixin.qq.com/sns/jscode2session?appid="+Configure.getAppID()+"&secret="+Configure.getSecret()+"&js_code="+code+"&grant_type=authorization_code");

    3. //设置请求器的配置

    4. HttpClient httpClient = HttpClients.createDefault();

    5. HttpResponse res = httpClient.execute(httpGet);

    6. HttpEntity entity = res.getEntity();

    7. String result = EntityUtils.toString(entity, "UTF-8");

    8. response.getWriter().append(result);

    第二步:统一下单

    调用微信的统一下单接口,返回预订单id(prepay_id)

    小程序:

    01. var that = this;

    02. wx.request({

    03. url: 'https://www.see-source.com/weixinpay/xiadan'

    04. method: 'POST',

    05. header: {

    06. 'content-type''application/x-www-form-urlencoded'

    07. },

    08. data: {'openid':openId},

    09. success: function(res) {

    10. var prepay_id = res.data.prepay_id;

    11. console.log("统一下单返回 prepay_id:"+prepay_id);

    12. that.sign(prepay_id);

    13. }

    14. })

    java:

    01. String openid = request.getParameter("openid");

    02. OrderInfo order = new OrderInfo();

    03. order.setAppid(Configure.getAppID());

    04. order.setMch_id(Configure.getMch_id());

    05. order.setNonce_str(RandomStringGenerator.getRandomStringByLength(32));

    06. order.setBody("dfdfdf");

    07. order.setOut_trade_no(RandomStringGenerator.getRandomStringByLength(32));

    08. order.setTotal_fee(10);

    09. order.setSpbill_create_ip("123.57.218.54");

    10. order.setNotify_url("https://www.see-source.com/weixinpay/PayResult");

    11. order.setTrade_type("JSAPI");

    12. order.setOpenid(openid);

    13. order.setSign_type("MD5");

    14. //生成签名

    15. String sign = Signature.getSign(order);

    16. order.setSign(sign);

    17.  

    18. String result = HttpRequest.sendPost("https://api.mch.weixin.qq.com/pay/unifiedorder", order);

    19. System.out.println(result);

    20. L.info("---------下单返回:"+result);

    21. XStream xStream = new XStream();

    22. xStream.alias("xml", OrderReturnInfo.class); 

    23.  

    24. OrderReturnInfo returnInfo = (OrderReturnInfo)xStream.fromXML(result);

    25. JSONObject json = new JSONObject();

    26. json.put("prepay_id", returnInfo.getPrepay_id());

    27. response.getWriter().append(json.toJSONString());

    Notify_url  是支付完成后就收微信的通知的,告诉你用户是否付款了

    注意:Total_fee单位是分,必须是整数,不能是小数

    Trade_type字段对于小程序来说固定写成JSAPI

    第三步:再次签名

    这是小程序的不同之处,要求对拿到的repay_id进行再次签名。

    注意这里有坑了:package字段的值是个键值对,格式prepay_id=12312333333333333

    小程序:

    01. var that = this;

    02. wx.request({

    03. url: 'https://www.see-source.com/weixinpay/sign'

    04. method: 'POST',

    05. header: {

    06. 'content-type''application/x-www-form-urlencoded'

    07. },

    08. data: {'repay_id':prepay_id},

    09. success: function(res) {

    10. that.requestPayment(res.data);

    11.  

    12. }

    13. })

    java:

    01. String repay_id = request.getParameter("repay_id");

    02. SignInfo signInfo = new SignInfo();

    03. signInfo.setAppId(Configure.getAppID());

    04. long time = System.currentTimeMillis()/1000;

    05. signInfo.setTimeStamp(String.valueOf(time));

    06. signInfo.setNonceStr(RandomStringGenerator.getRandomStringByLength(32));

    07. signInfo.setRepay_id("prepay_id="+repay_id);

    08. signInfo.setSignType("MD5");

    09. //生成签名

    10. String sign = Signature.getSign(signInfo);

    11.  

    12. JSONObject json = new JSONObject();

    13. json.put("timeStamp", signInfo.getTimeStamp());

    14. json.put("nonceStr", signInfo.getNonceStr());

    15. json.put("package", signInfo.getRepay_id());

    16. json.put("signType", signInfo.getSignType());

    17. json.put("paySign", sign);

    18. L.info("-------再签名:"+json.toJSONString());

    19. response.getWriter().append(json.toJSONString());

    第四步:调起支付

    最后一步调起小程序支付api

    01. wx.requestPayment({

    02. 'timeStamp': obj.timeStamp,

    03. 'nonceStr': obj.nonceStr,

    04. 'package': obj.package,

    05. 'signType': obj.signType,

    06. 'paySign': obj.paySign,

    07. 'success':function(res){

    08. },

    09. 'fail':function(res){

    10. }

    11. })

    之后就等着用户去输入支付密码完成支付了

    还有个接口是查询订单,这个不是必须的,你根据需要使用

    1. </div>
    2. </div>
  • 相关阅读:
    实战Docker未授权访问提权
    applyMiddleware 原理
    SpringBoot漏洞大全
    使用SQL查询ES:SpringBoot+Jdbc+Mybatis+Elasticsearch整合方案
    水能自发变成“消毒水”,83岁斯坦福教授:揭示冬天容易得流感的部分原因...
    【C++】模板初阶 【 深入浅出理解 模板 】
    洛谷P4560 Wall 砖墙
    Android入门第4天-开发第一个Android
    2020-09-04
    【C++11算法】is_sorted、is_sorted_until
  • 原文地址:https://blog.csdn.net/apple_51426592/article/details/127628449