前言
临时接到中信通知,之前接中信的微信通道要临时关闭。需要紧急接入直连微信,也就是用微信直接连接的方式进行扫码支付和app原生支付。时间比较紧急,而且之前做金融服务这块的同事又请假不在只好亲自上马(线上使用微信渠道支付的客户比较多,一旦银行关闭这个通道而我们后台服务又不能及时的切到微信直连上去的话,那么就意味着整个交易的闭环就断了)。经总结下来不管事情多么紧急也需要从头去锊一遍需要对接渠道的所有流程否则只会浪费时间在无数次的猜测和尝试上,切记切记(虽然微信这块尤其是sdk这块介绍的确实是太粗糙了)
下面大体介绍一下我们对接金融托管平台的一些时序;未直接对接微信存管的时候,所有的交易都是从存管银行的对接来处理。(银行存管封装了其一套对接的api和数据格式,而直接连接微信的话又是另外一套api和数据格式)
直接对接微信渠道以后时序图就变成了如下的结构,经分析客户端,网关两个服务基本上不用动,主要需要修改统一支付平台,如果能正常处理网关的请求和通知即可达到平缓切换的目的
有了上面的基础时序的分析,准备开始动手修改。主要修改内容统一支付平台数据格式及微信api处理。
基本介绍
本以为非常简单的一件事件,但是在操作过程中确被一些问题给卡住了;前面说了 主要是因为微信官方的sdk确实介绍的比较少,需要一点一点阅读其开发文档才能做到完全理解其很多步骤的用意;正常对接微信api的过程还是比较简单的按照微信官网一步一步操作即可;
下面这三个微信提供的地址是在开发里必须要一步一步去看的
- 商户服务后台 申请商户信息,Api秘钥key等;
- 微信开放平台:主要来申请appId ,以及关联商户号,关联app的,app的签名绑定等
- 验证签名sign:主要来判断当前程序生成的请求微信支付的数据xml是否异常
这里重点看几个关键步骤(下图的商户Server对应的是前面我们说的统一支付平台)
- app 发起支付请求
- 生成预付单package包添加签名(这里重点介绍一下,这一步的作用是向微信发起支付请求用于获取付单号prepay_id )
这里我就暂时叫他第一次加签。
这里直接用 java_sdk_v3.0.9的统一下单的代码,这里会得到resp这里就包含了下一步需要的预付单号prepay_id 。
MyConfig config = new MyConfig();
WXPay wxpay = new WXPay(config);
Map<String, String> data = new HashMap<String, String>();
data.put("appid", "wx93ced548c884d8a2");
data.put("body", "xx商城-商品名");
data.put("trade_type", "APP");
data.put("out_trade_no", "901020190805052258923749");
data.put("nonce_str", "03KojDbU7Ei2k41LWxNfEveLbgSUuuuZ");
data.put("notify_url", "http://devpay.11wlw.cn/wxPayProxy/appPayBatchAppB2BNotify.do");
data.put("sign_type", "HMAC-SHA256");
data.put("fee_type", "CNY");
data.put("total_fee", "300");
data.put("spbill_create_ip", "127.0.0.1");
data.put("mch_id", "1489046542");
try {
Map<String, String> resp = wxpay.unifiedOrder(data);
} catch (Exception e) {
}
这里我们重点看一下WxPayConfig的几个重要参数
appId
申请的应用id (微信开放平台)mchId
商户号 (商户服务后台申请)key
这个key值也很关键,主要用作和微信通讯的数据加密的key值,这个key值由自己设定 (商户服务后台申请),api安全栏目里。如下图
- 获取prepare_id值(从同一下单api的返回值里获取)
- 拿3步骤获取的prepayid再次签名生成app需要的sign参数;再次签名需要的几个参数如下;
这里的签名和统一支付方式完全一致也就是入参的值有所改变
,其中partnerid为商户的id,prepayid也就是第三步获取的prepare_id
参数全部小写,且如下这些基本参数都要有
Map<String, String> signData = new HashMap<String, String>();
signData.put("appid", response.getAppId());
signData.put("noncestr", response.getNonceStr());
signData.put("package", "Sign=WXPay");
signData.put("partnerid", weChatPay.getConfig().getMchID());
signData.put("prepayid",response.getPrepayId());
signData.put("timestamp", response.getTimeStamp());
log.info("二次加签参数:"+signData);
response.setPaySign(weChatPay.generateSign(signData));
5.返回app掉起APP需要的参数,注意这一步返回的sign参数是第四步中的二次加签生成的paySign值,而不是第一步获取prepare_id的时候微信返回的sign值(这里一定要注意,因为微信提供的sdk里没有提到这一点,只是在流程图里提到了)
然后经过上面几步,也就生成了app需要的几个参数如下
{"appid":"wx3f789fe1fc342fb1","noncestr":"uOLpMmqaYMLg2QlZ","partnerid":"1339275401","prepayid":"wx01160553900018dbd64691f21675143800","sign":"3D601D33870EAD883A1D13575C625D2FEC99EA39FC89815408869940C8515D62","timestamp":"1564646753","package":"Sign=WXPay"}
问题
- 第一次加签和第二次加签如果需要验证的话直接通过 验证签名sign即可
- 一定注意需要两步加签,第一步先加签后获取prepareId, 第二步加入prepareId再次加签 然后返回给app
- 注意鉴别,我看网上有很多程序员说是微信的sdk, 只能
md5
签名而不能使用HMAC-SHA256
这完全是胡说八道的。注意一定要理解整个流程在去动手写代码 - 注意本文和微信通讯未使用证书p12,这个按照微信的sdk去配置即可