微信H5支付(V3)
最近在做一个涉及支付的项目,其中对支付模块的内容涉及的比较多,记录一点心得。如果有错误,希望各位大佬斧正。
关于测试环境
sdk和git上有一个postman的脚本,但是也仅仅是下载证书的,没有调测支付接口的。链接
总之就是没有测试环境。你只能先弄H5的支付申请,然后开通之后再进行开发。
关于开通H5支付
开通H5支付必须需要一个备案过的顶级域名(这东西要钱),可以在阿里云上买一个,备案一下,有过建站经验的小伙伴应该比较熟悉,我不太懂,让客户自己买的。
至于实际使用的是顶级域名下面的二级域名这个是无所谓的。例如备案的是www.baidu.com,实际部署和使用的是www.test.baidu.com。这都可以
还需要一个H5商品的介绍页。这里我是做了一个产品介绍页,并没有实际售卖的产品,类似于奔驰官网那种布局,上面导航栏,下面产品介绍(不知道啥时候能码出奔驰的钱)。
然后部署在二级域名下面,就可以了。
这里要着重说一下,你的域名下的官网或产品介绍页或商城必须能够打开,如果打不开就被申请驳回。
申请需要3-5个工作日,但是也不一定,我的一个工作日就通过了
支付参数
开通之后你是不是准备码代码了,别着急,你还需要配置一下各种参数。
首先你需要申请一下证书,参考上面的文档就好了。
你需要以下参数
商户号
证书序列号:申请API证书之后点API证书那一栏的查看证书,就能在弹出页里面看到序列号了
apiV3Key:需要你在API安全里设置
这样就ok了,准备写代码
支付下单
写代码之前你需要查阅文档
文档里下单发起支付有两段代码,拼在一起就行了
这一段里面涉及一个privateKey,比较坑,你需要自己用代码把证书里面的privateKey解出来。或者从文件里读取出来
代码如下
ClassPathResource resource = new ClassPathResource(WxPayConfig.mchSerialFileName); File file=resource.getFile(); byte[] readBytes = FileUtil.readBytes(file);
这个mchSerialFileName 就是你申请的证书文件的.pem文件的路径
@Before public void setup() throws IOException { // 加载商户私钥(privateKey:私钥字符串) PrivateKey merchantPrivateKey = PemUtil .loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8"))); // 加载平台证书(mchId:商户号,mchSerialNo:商户证书序列号,apiV3Key:V3秘钥) AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier( new WechatPay2Credentials(mchId, new PrivateKeySigner(mchSerialNo, merchantPrivateKey)),apiV3Key.getBytes("utf-8")); // 初始化httpClient httpClient = WechatPayHttpClientBuilder.create() .withMerchant(mchId, mchSerialNo, merchantPrivateKey) .withValidator(new WechatPay2Validator(verifier)).build(); } @After public void after() throws IOException { httpClient.close(); }
这样你就下单成功了。
接口会返回一个
{ "h5_url": "https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx2016121516420242444321ca0631331346&package=1405458241" }
的json,这个就是发起请求的链接了。
但是这个链接不能通过浏览器直接打开,会报下面的错误
所以你需要在app或者H5里面使用代码打开。
例如:先用ajax请求后台,后台下单返回链接,然后打开。至于网上说的通过response.sendRedirect的方法,反正我是没有成功。
h5PayTest(){ httpGet(/members/WxPayController/createOrder,{},res=>{ // debugger // alert(res.data) // let data = JSON.parse(res.data) let data = res.data; alert(data.h5_url) location.href = data[h5_url] }) }
然后就能完成支付了。
注意:
这里有几个坑
- 发送请求的参数一定要和文档一样,必填的填写好。否则下单会失败
- 你的请求必须是从添加的H5域名相同,否则下单链接可以获取,但是支付不能成功。有的小伙伴会问,我备案的域名试服务器的linux的,不能写代码,只能部署,总不能写一点部署一点,然后测试一点吧。其实只有申请的时候是需要备案的,申请通过之后,你可以在开发配置里面添加一个本地内网穿透的地址,例如花生壳或者netapp,亲测是可以配置上去的,然后穿透到你的eclipse 的server上, 然后不久可以开发了吗,上线了再把这个删掉。
- 参数的description字段中文会在请求显示的时候乱码,你可以转成utf8,这样写 StringEntity entity = new StringEntity(reqdata,Charset.forName("utf8"));
后面会涉及到notify和查询订单、对账单这些。我会在后面的过程中分享。
以及一些支付选择的策略模式我也会分享
我的代码和上面的优点出入,我是用springboot开发的,如果感兴趣我也可以再分享。
总之,这一步支付成功后,后面的功能都比较简单了。