微信支付沙箱测试踩坑总结

问题:return_msg=沙箱验证签名失败,请确认沙箱签名key是否正确(通过getsignkey调用生成), return_code=FAIL

原因:1.没有填写正确的商家商户号mch_id或商家APPID导致获取沙箱密匙失败。返回response如下:

<xml>
  <return_code><![CDATA[FAIL]]></return_code>
  <retmsg><![CDATA[请确认请求参数是否正确merchant invalid mch_id(149514062)]]></retmsg>
  <retcode><![CDATA[1]]></retcode>
</xml>

2.可能由于在使用WXPay wxpay = new WXPay(config)时没有正确加载沙箱签名

博主在这方面遇到不少坑,但是网上的很多说法都没有提到这种情况,有必要在这里进行总结一下

在做测试的过程中,发现返回的沙箱签名是正确的(如下),但是仍然返回return_msg=沙箱验证签名失败,请确认沙箱签名key是否正确(通过getsignkey调用生成), return_code=FAIL,让我很郁闷,花了两天时间才得到解决。

<xml>
  <return_code><![CDATA[SUCCESS]]></return_code>
  <return_msg><![CDATA[ok]]></return_msg>
  <sandbox_signkey><![CDATA[32669873e826eea3dsfsdwdtr21371c82d]]></sandbox_signkey>
</xml>

3.代码如下:

public class WXPayConfigImpl implements WXPayConfig {


    private static final String AppID = "xxxxxx";
    private static final String MchID = "xxxxxx";
	private String Key = "xxxxxxx";

    private byte[] certData;

    public WXPayConfigImpl(boolean useSandbox)  {
        if (useSandbox) {
            Key = getSandboxSignKey();
        }
    }

    @Override
    public String getAppID() {
        return AppID;
    }

    @Override
    public String getMchID() {
        return MchID;
    }

    @Override
    public String getKey() {
        return Key;
    }

    @Override
    public InputStream getCertStream() {
        ByteArrayInputStream certBis = new ByteArrayInputStream(this.certData);
        return certBis;
    }

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

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

    public String getSandboxSignKey() {
        WXPay wxPay = new WXPay(this);
        try {
            Map<String, String> params = new HashMap<String, String>();
            params.put("mch_id", this.getMchID());
            params.put("nonce_str", WXPayUtil.generateNonceStr());
            params.put("sign", WXPayUtil.generateSignature(params, this.getKey()));
            String strXML = wxPay.requestWithoutCert("https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey",
                    params, this.getHttpConnectTimeoutMs(), this.getHttpReadTimeoutMs());

            Map<String, String> result = WXPayUtil.xmlToMap(strXML);
            System.out.println("retrieveSandboxSignKey:" + result);
            if ("SUCCESS".equals(result.get("return_code"))) {
                return result.get("sandbox_signkey");
            }
            return null;
        } catch (Exception e) {
            System.out.println("获取sandbox_signkey异常" + e.getMessage());
            return null;
        }
    }

}

如上:需要在WXConfig的实现类中将KEY的值替换为沙箱的KEY,否则在如下代码中会出现上述出现的问题,明明正确得到了沙箱的KEY,但仍然返回沙箱验证签名失败。

boolean useSandbox = true;
WXPayConfigImpl config = new WXPayConfigImpl(useSandbox); //若config对象里的KEY没有替换成沙箱的KEY,则会出现上述出现的情况
WXPay wxpay = new WXPay(config, WXPayConstants.SignType.MD5, useSandbox);
String sign = WXPayUtil.generateSignature(microPayData, "API密钥", WXPayConstants.SignType.MD5); // 

// 刷卡支付
Map<String, String> rsp1 = wxpay.microPay(microPayData);
System.out.println("microPayData" + rsp1);

正确返回:​{transaction_id=4976550223320190226131747370975, nonce_str=da30ece1ca7e4f70af9d62329cbeacd9, bank_type=CMC, openid=xxxxxx, sign=xxxxxx, err_code=SUCCESS, err_code_des=ok, return_msg=OK, fee_type=CNY, mch_id=xxxxxx, cash_fee=1, device_info=15403437, out_trade_no=121288d9d77b4599b3b5f908e1a952eb, cash_fee_type=CNY, total_fee=1, appid=xxxxxx, trade_type=MICROPAY, result_code=SUCCESS, time_end=20190226131747, attach=sandbox_attach, is_subscribe=Y, return_code=SUCCESS} ​


版权声明:本文为weltven原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。