微信支付之小程序支付总结

写在前面:虽然很多人说官方文档有很多坑,但是根据我一路踩坑的经验来说还是要相信官方文档的。

官方文档传送门:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1

生成apiKey地址(微信商户平台)
https://pay.weixin.qq.com/index.php/core/home/login?return_url=%2Findex.php%2Fcore%2Fcert%2Fapi_cert

我遇到最大的问题:-------------------支付校验签名失败-------------------

先说我的问题出在哪:

  1. 调用统一下单接口之前没有进行签名操作;
  2. 第一次签名参数没有写全(文档里面说是必传的字段一定要传);
  3. 第二次签名用到的随机字符串字段“nonce_str”要和第一次签名生成的一致,也就是说第一次签名生成一次随机字符串,第二次签名的时候用的还是这次生成的随机字符串;
  4. 官方文档说小程序支付默认签名是“MD5”那就是MD5,不要听信其他人说是“HMAC-SHA256”或者其他类型;
  5. 时间戳是10位的就是精确到秒(文档中有提到);
  6. 第二次签名时appId请注意大小写(这个是驼峰,第一次签名appid全是小写);
  7. 完成两次签名之后把第二次签名用到的参数(appId,timeStamp,nonceStr,package,signType,paySign)以及第二次签名生成的签名共六个参数(这几个是必传的,如果其他需要传递的,比如说商户号什么的也可以一同传过去)传递给小程序前段。
    **

看代码才最直观

**
ps:代码不全只列出了关键点

第一次签名+调用统一支付接口

	   //写在前面:我这段代码入参 totalAmount、openid
     WXPayConfigSmallUtils wxPayConfigSmallUtils=new WXPayConfigSmallUtils();//工具配置类
        WXPay wxPay=new WXPay(wxPayConfigSmallUtils);
        
        //生成订单流水号
        String outTradeNo = xxxx;//随便找个工具类生成不重复的一串数字就行
       
        String nonceStr=WXPayUtil.generateNonceStr();//生成随机字符串
        Map paramMap = new HashMap();
        paramMap.put("trade_type", "JSAPI");
        paramMap.put("out_trade_no", outTradeNo);
        paramMap.put("notify_url", "http://xxxx");
        paramMap.put("body", "xxxx");
        paramMap.put("total_fee",  totalAmount.multiply(new BigDecimal(100)).toBigInteger().toString());
        paramMap.put("spbill_create_ip", "xxx");
        paramMap.put("openid",openid);

        paramMap.put("nonce_str",nonceStr);
        String sign=WXPayUtil.generateSignature(paramMap,wxPayConfigSmallUtils.getKey(),WXPayConstants.SignType.MD5);
        paramMap.put("sign",sign);

        LOGGER.info("[WxpayBiz][createWxAppPayOrder]-微信支付请求参数:{}", JSON.toJSONString(paramMap));

        Map wxResponseMap = wxPay.unifiedOrder(paramMap);//调用统一支付接口

        LOGGER.info("[WxpayBiz][createWxAppPayOrder]-微信支付平台返回结果:{}", JSON.toJSONString(wxResponseMap));

	 resultVo.setStatus(RetStatus.Ok.getValue());
        wxResponseMap.put("outTradeNo",outTradeNo);//添加订单号
        wxResponseMap.put("nonceStr",nonceStr);//随机字符串
        resultVo.setData((HashMap) wxResponseMap);
  
	  return resultVo;

第二次签名
//我这是写了两个方法,下面第一行代码是调用上个方法的返回值

 Map wxResponseMap = wxPayRes.getData();

        String nonceStr =wxResponseMap.get("nonceStr");//统一支付接口返回的随机字符串
        String timeStamp=System.currentTimeMillis()/1000+"";//时间戳
        //二次签名
        Map paramMap = new HashMap();
        paramMap.put("appId",wxResponseMap.get("appid"));
        paramMap.put("timeStamp",timeStamp);
        paramMap.put("nonceStr", nonceStr);
        paramMap.put("package","prepay_id="+wxResponseMap.get("prepay_id"));
        paramMap.put("signType","MD5");
        LOGGER.info("[小程序支付二次签名传入参数] patamMap={}" ,JSON.toJSONString(paramMap));
        String newSign= WXPayUtil.generateSignature(paramMap,new WXPayConfigSmallUtils().getKey(), WXPayConstants.SignType.MD5);

工具类

public class WXPayConfigSmallUtils implements WXPayConfig {
//appid
    @Override
    public String getAppID() {
        return "xxx";
    }
//商户号
    @Override
    public String getMchID() {
        return "xxx";
    }
//商户平台生成的apiKey
    @Override
    public String getKey() {
        return "xxx";
    }

@Override
public InputStream getCertStream() {
    return null;
}

@Override
public int getHttpConnectTimeoutMs() {
    return 0;
}

@Override
public int getHttpReadTimeoutMs() {
    return 0;
}

}

到此小程序的两次生成签名就完事了,剩下的就是把需要的参数传递到小程序前段拉起微信支付。
最后,祝你好运,少踩点坑→_→

你可能感兴趣的:(微信)