微信小程序支付踩的坑(支付验证签名失败)

最近有需求是微信小程序支付,用的是微信自带的sdk,曾做过微信APP支付,微信扫用户码支付,都是OK的,现在把做微信小程序支付流程写下来,还有在调用过程踩的坑,下面为步骤

一.先查看API

地址: https://pay.weixin.qq.com/wiki/doc/api/index.html
官网API
我是后端的,前端调用是用我们返回的值
地址: https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1
在这里插入图片描述
查看api可以知道我们需要的值,其他的还好说,其中有一个需要特别注意一下:刚好小程序的trade_type就是JSAPI
在这里插入图片描述

二.查看流程图

开始我以为这个前端来传就可以了,后来前端也说他只能获得一个登录code,于是我看了流程:
在这里插入图片描述

三.获取openid

那就我们来获取openid吧,后端还比较安全,于是我找到了这个地址:
地址: https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html
具体调用如下代码:

//拼成get方式的请求体
String params = "appid=" + tParamPayment.getApp_id() + "&secret=" + tParamPayment.getPay_key() + "&js_code=" + authcode + "&grant_type="
                    + Consts.GRANT_TYPE;
String responseContent = WXPayRequest.sendGet(Consts.GET_OPENID_URL, params);
Map mSepRet = gson.fromJson(responseContent, Map.class);
logger.info("get openid:" + gson.toJson(mSepRet));
if (null == mSepRet.get("openid")) {
     //自定义错误
     return ResultUtil.error(PltResult.RESULT_PA36.getpCode(), PltResult.RESULT_PA36.getpName());
}
String openid = (String) mSepRet.get("openid");
//注:appid是小程序appid,秘钥是小程序的appSecret
public static String GET_OPENID_URL = "https://api.weixin.qq.com/sns/jscode2session";//请求地址
public static String GRANT_TYPE = "authorization_code";//grant_type:固定的
四.调用统一下单接口(防坑)

放上微信的SDK,做了简单改动,更贴近现实开发
链接:https://pan.baidu.com/s/1AEpdsXyVzcFvXXrOpJeFug
提取码:9bif
然后我在调用接口的时候也发现是没问题的,代码如下:

Map<String, String> parameters = new HashMap<String, String>();
MyConfig config = new MyConfig(tParamPayment.getMerchant_key(), tParamPayment.getMerchant_id(), tParamPayment.getApp_id());
WXPay wxpay = new WXPay(config);
parameters.put("body", "根据实际情况填写");// 商品详情
parameters.put("nonce_str", WXPayUtil.generateNonceStr());
parameters.put("out_trade_no", "根据实际情况填写" ); parameters.put("spbill_create_ip", "127.0.0.1");// 调用微信支付API的机器IP
parameters.put("total_fee", ordamt);// 总额
parameters.put("openid", openid);// 上面获取的openid
parameters.put("notify_url", tParamPayment.getNotify_url());// 回调地址
parameters.put("trade_type", "JSAPI");// 类型
String sign = WXPayUtil.generateSignature(parameters, tParamPayment.getMerchant_key());
parameters.put("sign", sign);// 签名
 logger.debug("wxpay request:" + gson.toJson(parameters));
Map<String, String> resXmlMap = wxpay.unifiedOrder(parameters);
logger.debug("wxpay response:" + gson.toJson(resXmlMap));
if (Consts.SUCCESS.equals(resXmlMap.get("return_code")) && Consts.OK.equals(resXmlMap.get("return_msg"))) {
    Map<String, String> payparamsMap = new HashMap<String, String>();
    Date currDate = new Date();
    long timestamp = currDate.getTime() / 1000;
    payparamsMap.put("appId", tParamPayment.getApp_id());
    payparamsMap.put("package", "prepay_id=" + resXmlMap.get("prepay_id"));
    payparamsMap.put("timeStamp", timestamp + "");
    payparamsMap.put("nonceStr", WXPayUtil.generateNonceStr());// 
    payparamsMap.put("signType", WXPayConstants.MD5);
    String newSign = WXPayUtil.generateSignature(payparamsMap, tParamPayment.getMerchant_key());
    payparamsMap.put("paySign", newSign);
    logger.debug("response data:" + gson.toJson(payparamsMap));
    returnParam.put("payparams", payparamsMap);
    //注:MyConfig config = new MyConfig("商户秘钥", "商户id", "小程序appid");

}
wxpay.unifiedOrder(parameters)中的unifiedOrder