微信小程序支付java后端 (V2版本)

前言:
其实小程序支付官网V2版本写的有点模糊了,主要是没具体代码的demo 哈哈 下面教大家一步一步的写
大体思路就是:
1.服务后台生成预支付交易单(也就是API列表里的统一下单)
2.对统一下单返回的结果进行加密才是小程序端的正确签名

1.组装好正确的参数去请求,返回正确预支付交易信息

1.1导入hutool包

写接口用的工具类hutool里面大部分都有为了省事,有一点点工具类还得自己写

<dependency>
  <groupId>cn.hutool</groupId>
  <artifactId>hutool-all</artifactId>
  <version>4.5.7</version>
</dependency>
1.2创建统一下单的参数

一定按照官网要求的参数名进行创建不要有驼峰命名,官网是啥参数就写成啥,这是所有的参数。
生成签名不需要sign这个参数所以先把它注释掉

Map<String,String> params = new HashMap<String,String>(10);
params.put("appid","");
params.put("mch_id","");
params.put("nonce_str","");
params.put("sign_type","");
params.put("body","");
params.put("out_trade_no","");
params.put("total_fee","");
params.put("spbill_create_ip","");
params.put("notify_url","");
//params.put("sign","自己生成的签名");

1.3 对上面的params的sign进行加密得到用到的签名

1.对参数按照key=value的格式,并按照参数名ASCII字典序排序(a–>b–>c),
2.然后转换成key=value&key1=value1
出来的效果就是这个样子 stringA=“appid=wxd930ea5d5a258f4f&body=test&device_info=1000…”;
3.注意这里生成签名不需要sign这个参数
4.最后拼接上商户key

//转换成key=value&key1=value1
String urlMap = MapUrlParamsUtils.sortMap(paramMap, wxBean.getPartnerKey());
 
//使用hutool SecureUtil进行MD5加密并转换成大写
String sign = SecureUtil.md5(urlMap).toUpperCase();

1.sortMap()这个方法就是对map参数进行拼接,ASCII字典序排序。具体代码如下:

    /**
     * 参数名ASCII字典序排序a->b->c
     * 生成字符串末尾拼接商户key去支付的参数不需要商户key只有加密才用到
     * @param map  这个map里的key没有sign
     * @param partnerKey 商户key
     * @return
     */
    public static String sortMap(Map<String, Object> map, String partnerKey) {
        if (map == null) {
            return "";
        }
        TreeMap<String, Object> sort = MapUtil.sort(map);
        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, Object> entry : sort.entrySet()) {
            //把商户key放到最后拼接
            if (entry.getKey().equals("key")) {
                continue;
            }
            sb.append(entry.getKey() + "=" + entry.getValue());
            sb.append("&");
        }
        String s = sb.toString();
        if (s.endsWith("&")) {
            s = StrUtil.subBefore(s, "&", true);
        }
        s += "&key=" + partnerKey;
        return s;
    }
1.4 参数转换成xml的String字符串

至此已经得到签名了,把生成的签名put到上面的paramMap里面,使用hutool的XmlUtil并转换成xml的String类型

//put刚才生成的签名
paramMap.put("sign", sign);

/**
 * 使用 XmlUtil把map转换成xml的String类型,出来的效果就是
 * String xml = "<xml> <appid>aaa</appid><mch_id>bbb</mch_id>...</xml>"
 */
String xmlStr = XmlUtil.mapToXmlStr(paramMap, "xml");
1.5 对签名进行验证

用微信支付接口签名校验工具进行验证。如图所示
。。。

1.6发送统一下单的请求

用hutool里的HttpUtil发送请求

  //发送请求(响应也是xml)
  String responseXml = HttpUtil.post("统一下单url", xmlStr);
  
  //再把响应的xml转换成map
  Map<String, Object> responseMap = XmlUtil.xmlToMap(responseXml);
  
  //也可以把响应也封装成对象,再用responseMap转换成对象
  
  //...进行后续逻辑处理
  String isSuccess = responseMap.get("return_msg").toString();
  
  if("SUCCESS".equals(isSuccess )){
 	//prepay_id
 	//nonce_str
  }

2.生成小程序支付所用到参数

2.1 提取responseMap里的prepay_id和nonce_str

先看一下官方文档的对nonceStr的解释是随机字符串,乍一看随机生成一个就行了。这里你再生成一个随机字符串就大错特错了,得使用上面responseMap里的nonce_str这个才行。太TM的坑了。
还有变量名 单单是小程序ID就有三种变量名 appid、app_id、appId 巨TM的坑

拼接好小程序支付用到的签名的参数 appId、timeStamp、nonceStr、package、signType,然后调用上面写的sortMap(Map map,String partnerKey)这个方法。
示例: appId=wxd678efh567hg6787&nonceStr=5K8264ILTKCH16CQ2502SI8ZNMTM67VS&package=prepay_id=wx2017033010242291fcfe0db70013231072&signType=MD5&timeStamp=1490840662&key=qazwsxedcrfvtgbyhnujmikolp111111

 //nonceStr和package  这两个参数必须是统一下单返回的参数
 
 Map<String,Object> WeChatAppletParam = new HashMap<>(5);
 
 String timeStampStr = DateUtil.currentSeconds() + "";
 WeChatAppletParam.put("appId","你的appid");
 WeChatAppletParam.put("timeStamp", timeStampStr);
 WeChatAppletParam.put("nonceStr",responseMap.get("nonce_str").toString());
 // package 需要拼接prepay_id=
 WeChatAppletParam.put("package","prepay_id="+responseMap.get("prepay_id").toString());
 WeChatAppletParam.put("signType","MD5");

 //转换成key=value&key1=value1
 String urlMap = MyMapUtil.sortMap2Url(WeChatAppletParam , wxBean.getPartnerKey());
 
 //小程序支付的签名就得到啦
 String miniPaySign = SecureUtil.md5(urlMap).toUpperCase();
 
2.2 返回小程序所用的参数

小程序端的wx.requestPayment({})这个方法,需要用到 timeStamp、nonceStr、package、signType、paySign,这5个参数后台全部能返回


Map<String,String> result = new HashMap<String,String>(5);

result.put("timeStamp",timeStampStr);
result.put("nonceStr","上面responseMap里的nonce_str");
result.put("package","prepay_id="+"上面responseMap里的prepay_id");
result.put("signType","MD5");
result.put("paySign","上面的miniPaySign ");

return result;

我就是说个思路,不对的地方可以提出来,不懂的可以留言问我。其实V2版的也不难就是把参数拼接好然后发送Post请求就好了

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值