2015 年 12 月 5 日

微信支付开发中的“坑”与解决之道

微信支付是腾讯公司的支付业务品牌,它提供公众号支付、扫码支付、APP支付、刷卡支付等支付方式,并且还提供代金券、现金红包、企业付款等营销工具。微信支付结合微信公众号,全面打通O2O生活消费领域,提供专业的互联网+行业解决方案,是移动支付的首选。

2013年8月5日,微信5.0版本引入了微信支付功能。2015年6月1日,腾讯发布了“2015微信用户数据报告”,报告称微信支付用户数达到4亿左右,可见微信支付的发展速度非常惊人。

我有幸于2013年6月微信支付内测期间就开始接触微信支付开发,亲眼见证了微信支付的每一次成长。在此期间,有许多初学者向我咨询微信支付开发。今天,我就来吐槽一下微信支付开发中的各种“坑”。

V2和V3差异大

微信支付接口现在分为V2版和V3版,2014年9月10日之前申请的为V2版,之后申请的为V3版。这两个版本在功能和接口上都有很大差别,不能互用,开发时要特别注意这一点,否则可能会走很多弯路。

开发文档混乱

微信公众平台开发者文档位于http://mp.weixin.qq.com/wiki/,相信大家都比较熟悉,然而有意思的是,这里面唯独没有微信支付的接口文档。微信支付的接口文档要登录微信公众平台才能看得到,如图1所示。

北京网站建设资讯 - 微信支付开发中的“坑”与解决之道 - (1)

图1 微信支付接口文档

噢,原来藏在这里,也不算难找嘛!然而,仔细观察会发现这里没有代金券、现金红包、企业付款等接口的说明。如果要查看所有的微信支付接口文档,需要去微信支付商户平台,访问地址为https://pay.weixin.qq.com/wiki/doc/api/index.html,如图2所示。

北京网站建设资讯 - 微信支付开发中的“坑”与解决之道 - (2)

图2 微信支付商户平台开发者文档

签名算法

为了保证数据安全,微信支付要求所有发送或接收的数据都必须经过签名,相信不少开发者都在签名算法上吃过亏。下面是生成签名时的一些注意事项和经验分享。

【参数按字典序排序】

需要特别注意的是,参数名严格区分大小写,并且值为空的参数不参与签名。最让我记忆犹新的是开发“收货地址共享接口”,调用接口需要传递的参数(appId、timeStamp和nonceStr)在签名时都必须小写。

至于参数按字典序排序,在Java中,可以采用SortedMap来实现,非常简便,不建议开发者自己实现排序算法。

【MD5和SHA1算法】

在微信支付相关的接口中,“收货地址共享接口”使用SHA1算法进行签名,除此之外的其他接口都使用MD5算法进行签名。对于大多数开发者而言,编写SHA1和MD5算法是有一定难度的,虽然最终的实现代码只有几行。

在Java中,可以采用Apache Commons Codec工具包来实现标准的MD5和SHA-1,示例代码如下:

String source = "签名测试";
String md5 = DigestUtils.md5Hex(source);
System.out.println("md5签名结果:" + md5);
String sha1 = DigestUtils.sha1Hex(source);
System.out.println("sha1签名结果:" + sha1);

说明:运行以上示例需要在工程中引入jar包commons-codec-1.9.jar。

另外,需要注意的是,在“收货地址共享接口”中,官方给出的SHA1签名示例的结果是错误的,这估计误导了很多开多者,让他们误以为自己的签名算法有误。官方示例如下北京网站建设资讯 - 微信支付开发中的“坑”与解决之道 - (3)

经我测试,上述示例中SHA1签名后的正确结果为:

北京网站建设资讯 - 微信支付开发中的“坑”与解决之道 - (4)

双向证书

首先,我们来简单认识一下SSL证书、单向认证和双向认证。

SSL证书是由受信任的数字证书颁发机构CA(如GlobalSign,WoSign),在验证服务器身份后颁发的,具有服务器身份验证和数据传输加密的功能。单向认证是指在SSL通信过程中,客户端需要验证服务器证书的合法性,而服务器端不对客户端证书进行校验。双向认证是指在SSL通信过程中,客户端需要验证服务器证书的合法性,服务器端也需要验证客户端证书的合法性。

在微信支付开发中,申请退款、发放现金红包、发放裂变红包等接口需要用到商户证书,微信服务器会验证商户证书的合法性。API证书文件可按以下路径下载:

北京网站建设资讯 - 微信支付开发中的“坑”与解决之道 - (5)

下载到API证书之后,该如何在程序中使用呢?这就需要使用KeyManagerFactory类和KeyStore类,在程序中设定客户端使用的证书。核心代码如下:

// 证书文件(微信商户平台-账户设置-API安全-API证书-下载证书)
String keyStorePath = "D:/apiclient_cert.p12";
// 证书密码(默认为商户ID)
String password = WxPayUtil.partner;
// 实例化密钥库
KeyStore ks = KeyStore.getInstance("PKCS12");  
// 获得密钥库文件流
FileInputStream fis = new FileInputStream(keyStorePath);  
// 加载密钥库
ks.load(fis, password.toCharArray());
// 关闭密钥库文件流
fis.close();
 
// 实例化密钥库
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());  
// 初始化密钥工厂
kmf.init(ks, password.toCharArray());
 
// 创建SSLContext
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());
// 获取SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
 
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod(requestMethod);
// 设置当前实例使用的SSLSocketFactory
conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.connect();

希望本篇文章能够帮助开发者顺利避开微信支付开发的各种“坑”,快速掌握微信支付接口的使用。

最新文章

  1. 网站推广想要降低推广费用这些事情要做好
  2. 企业移动端网站建设需要考虑哪些因素
  3. 模板网站建设这么流行,为什么还要选择定制开发?
  4. 网站推广选择百度竞价有哪些好处
  5. 域名是什么,作用有哪些?
  6. 怎么才能做好网站营销工作?这几点不容忽视!
  7. 网站建设工作流程是什么,要注意哪些问题?
  8. 导致网站优化失败的原因有哪些
  9. 网站优化不同阶段的优化策略
  10. 北京网站建设有哪些要点需要注意?这些不容忽视!