微信支付是腾讯公司的支付业务品牌,它提供公众号支付、扫码支付、APP支付、刷卡支付等支付方式,并且还提供代金券、现金红包、企业付款等营销工具。微信支付结合微信公众号,全面打通O2O生活消费领域,提供专业的互联网+行业解决方案,是移动支付的首选。 2013年8月5日,微信5.0版本引入了微信支付功能。2015年6月1日,腾讯发布了“2015微信用户数据报告”,报告称微信支付用户数达到4亿左右,可见微信支付的发展速度非常惊人。 我有幸于2013年6月微信支付内测期间就开始接触微信支付开发,亲眼见证了微信支付的每一次成长。在此期间,有许多初学者向我咨询微信支付开发。今天,我就来吐槽一下微信支付开发中的各种“坑”。 V2和V3差异大 微信支付接口现在分为V2版和V3版,2014年9月10日之前申请的为V2版,之后申请的为V3版。这两个版本在功能和接口上都有很大差别,不能互用,开发时要特别注意这一点,否则可能会走很多弯路。 开发文档混乱 微信公众平台开发者文档位于https://mp.weixin.qq.com/wiki/,相信大家都比较熟悉,然而有意思的是,这里面唯独没有微信支付的接口文档。微信支付的接口文档要登录微信公众平台才能看得到,如图1所示。 图1 微信支付接口文档 噢,原来藏在这里,也不算难找嘛!然而,仔细观察会发现这里没有代金券、现金红包、企业付款等接口的说明。如果要查看所有的微信支付接口文档,需要去微信支付商户平台,访问地址为https://pay.weixin.qq.com/wiki/doc/api/index.html,如图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签名示例的结果是错误的,这估计误导了很多开多者,让他们误以为自己的签名算法有误。官方示例如下
经我测试,上述示例中SHA1签名后的正确结果为:
双向证书
首先,我们来简单认识一下SSL证书、单向认证和双向认证。
SSL证书是由受信任的数字证书颁发机构CA(如GlobalSign,WoSign),在验证服务器身份后颁发的,具有服务器身份验证和数据传输加密的功能。单向认证是指在SSL通信过程中,客户端需要验证服务器证书的合法性,而服务器端不对客户端证书进行校验。双向认证是指在SSL通信过程中,客户端需要验证服务器证书的合法性,服务器端也需要验证客户端证书的合法性。
在微信支付开发中,申请退款、发放现金红包、发放裂变红包等接口需要用到商户证书,微信服务器会验证商户证书的合法性。API证书文件可按以下路径下载:
下载到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();
希望本篇文章能够帮助开发者顺利避开微信支付开发的各种“坑”,快速掌握微信支付接口的使用。
作者简介
刘运强,网名“柳峰”,Java软件开发工程师、Android/iOS移动应用开发工程师,国内微信公众平台应用开发的先驱之一,常年活跃在ImapBox社区,并在ImapBox博客撰写了系列微信公众平台二次开发的教程,深受欢迎并被广泛传播,也因此获得了ImapBox2013年度博客之星。著有《微信公众平台应用开发:方法、技巧与案例》一书。
本文选自程序员电子版2015年11月B刊,该期更多文章请查看这里。2000年创刊至今所有文章目录请查看程序员封面秀。欢迎订阅程序员电子版(含iPad版、Android版、PDF版)。
本文为ImapBox原创文章,未经允许不得转载,如需转载请联系market#csdn.net(#换成@)
本网页所有文字内容由 imapbox邮箱云存储,邮箱网盘, iurlBox网页地址收藏管理器 下载并得到。
ImapBox 邮箱网盘 工具地址: https://www.imapbox.com/download/ImapBox.5.5.1_Build20141205_CHS_Bit32.exe
PC6下载站地址:PC6下载站分流下载
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox 网页视频 工具地址: https://www.imapbox.com/download/ImovieBox4.7.0_Build20141115_CHS.exe
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 程序员专区