2020-12-02 微信JSAPIV3支付
前言
微信新出的V3支付接口,还没玩过,正好有做支付的需求,于是就看看怎么搞了,下面是集成第三方jar来调用的微信支付,如何使用可以查看我的另一篇文章,不过方式跟v2也是有些区别的。
微信jar V2支付(含内网穿透工具)
V3接口规则(个人理解)
微信文档
发送请求前,构造签名串,使用证书和密钥文件签名
将生成签名按照规则组装后,作为请求头,发送请求
整合binarywang.weixin-java-pay实现v3支付
jar
<dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-pay</artifactId><version>4.0.0</version>
</dependency>
下单
该库现在支持使用V3方式构造Http Client,从而使用该Client发送请求时,我们就无需关心签名的生成,只需要设置接口所需参数即可,不过这个Client也需要我们来生成!!
生成Http Client
/*** <p>* 生成v3 http client并返回WxPayConfig* </p>* @param mchId 商户号* @param apiV3Key api V3 密钥* @param privateKey 私钥* @param privateCert 证书* @param isUrl 私钥和证书是否为url资源,false则表示文件资源* @return com.github.binarywang.wxpay.config.WxPayConfig* @author guohaibin* @date 2020-12-02 13:53:14*/
private WxPayConfig createV3WxPayConfig(String mchId, String apiV3Key,String privateKey, String privateCert, boolean isUrl) {WxPayConfig wxPayConfig = new WxPayConfig();if (isUrl) {// 手动构建http client - 通过url的方式来读取证书/密钥Credentials credentials = new WxPayCredentials(mchId,new PrivateKeySigner(PemUtils.loadCertificate(URLUtil.getStream(URLUtil.url(privateCert))).getSerialNumber().toString(16),PemUtils.loadPrivateKey(URLUtil.getStream(URLUtil.url(privateKey)))));Validator validator = new WxPayValidator(new AutoUpdateCertificatesVerifier(credentials, apiV3Key.getBytes()));CloseableHttpClient client = WxPayV3HttpClientBuilder.create().withCredentials(credentials).withValidator(validator).build();wxPayConfig.setApiV3HttpClient(client);} else {// 自动构建apiV3HttpClient时以下参数必须设置// com.github.binarywang.wxpay.config.WxPayConfig.initApiV3HttpClientwxPayConfig.setMchId(mchId);wxPayConfig.setPrivateKeyPath(privateKey);wxPayConfig.setPrivateCertPath(privateCert);wxPayConfig.setApiV3Key(apiV3Key);}return wxPayConfig;
}
这里我使用两种方式来生成,一种是读文件的方式,一种是文件是url时的方式,因为我们项目时代小程序开发,所以如果用了V3,证书文件就会存在服务器上,因此考虑两种方式;但实际不适用,因为回调无法满足需求。
一般单独小程序使用,读文件的方式就足以使用了!
下单
微信文档
/*** <p>* JSAPI支付* </p>* @param appId 小程序appId* @param mchId 小程序绑定商户号* @param apiV3Key api V3 密钥* @param description 商品描述(128)* @param total 订单总金额(分)* @param outTradeNo 订单号(需要生成)* @param openId 用户openId* @param privateKey 私钥* @param privateCert 证书* @param isUrl 私钥和证书是否为url资源,false则表示文件资源* @return com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult* @author guohaibin* @date 2020-12-02 13:56:02*/
public WxPayMpOrderResult createOrderJSAPI(String appId, String mchId, String apiV3Key,String description, BigDecimal total, String outTradeNo,String openId, String privateKey, String privateCert, boolean isUrl) throws Exception {WxPayService wxPayService = new WxPayServiceImpl();WxPayConfig wxPayConfig = createV3WxPayConfig(mchId, apiV3Key, privateKey, privateCert, isUrl);wxPayService.setConfig(wxPayConfig);// 设置参数JSONObject data = new JSONObject();data.set("appid", appId);data.set("mchid", mchId);data.set("description", description);data.set("out_trade_no", outTradeNo);data.set("notify_url", v3PayNotifyUrl);JSONObject amount = new JSONObject();amount.set("total", BaseWxPayRequest.yuanToFen(total.toString()));data.set("amount", amount);JSONObject payer = new JSONObject();payer.set("openid", openId);data.set("payer", payer);// 调接口String result = wxPayService.postV3("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi",data.toString());JSONObject prepayObject = JSONUtil.parseObj(result);// 获取paySignif (prepayObject.containsKey("prepay_id")) {// 预支付签名String packageStr = "prepay_id=" + JSONUtil.parseObj(result).getStr("prepay_id");String nonceStr = SignUtils.genRandomStr();String timeStamp = String.valueOf(System.currentTimeMillis());String signType = "RSA";// 构造paySignString signStr = appId + "\n" + timeStamp + "\n" + nonceStr + "\n" + packageStr + "\n";String paySign = SignUtils.sign(signStr, getPrivateKey(privateKey, isUrl));return new WxPayMpOrderResult(null, timeStamp, nonceStr, packageStr, signType, paySign);} else {// TODO 报错并打印有用信息throw new WxPayException("v3获取预支付异常");}
}
后续的流程就是设置参数,调接口,再签名出paySign,和V2类似,不过这里再次签名方式不一样,要先构造签名串,用V3的方式签名。
签名文档
支付回调
controller
因为V3都是JSON做参和返回值了,所以直接接收即可。
@PostMapping("/payNotify")
public String payNotify(@RequestBody PayV3Notify payV3Notify) {// 需要考虑恶意调用,非法调用可以不考虑,因为有签名验证,但是要避免多次恶意调用return payV3Service.payNotify(payV3Notify);
}
service
V2:返回值中会包含信息,然后再用商户密钥去校验签名,可利用信息
V3:返回值中不包含任何明文,需要ApiV3密钥解密后,才可解析出订单号等信息
因此,在我们项目中,我们可以通过appId来获取商户信息,但由于V3不再提供信息,导致我们无法根据商户号/订单号来查找商户信息,那么就无法使用V3来实现我们的逻辑,并且,V3暂未提供退款接口,因此后续的退款我们也实现不了,综上,最后我还是选择使用V2来实现支付。
public String payNotify(PayV3Notify payV3Notify) {try {// 解密String decryptToString = AesUtils.decryptToString(payV3Notify.getResource().getAssociated_data(),payV3Notify.getResource().getNonce(), payV3Notify.getResource().getCiphertext(),wxConfig.getApiV3Key());PayV3NotifyDecrypt payV3NotifyDecrypt = JSONUtil.toBean(decryptToString, PayV3NotifyDecrypt.class);// 订单号String outTradeNo = payV3NotifyDecrypt.getOut_trade_no();// 判断订单状态// 修改订单状态return WxPayNotifyResponse.success("处理成功!");} catch (Exception e) {log.error("微信回调结果异常,异常原因{}", e.getMessage());return WxPayNotifyResponse.fail(e.getMessage());}
}
小结
就接口来说,V3调用的方式复杂了些,每次都需要构造签名,有点麻烦,不过配置好通用一下就行;
参数方面比V2好些,就不需要string -> xml或是xml -> string了,可以自定义对象来接收回调数据了
就支付回调来说,V2是先拿到数据,再校验数据,而V3是先解密,才能获取数据(个人感觉这样在代小程序开发中就不好用V3来搞,因为小程序是动态的,V2就能获取appId再连查密钥,而V3需要密钥才能获取信息,就不符合需求感觉!)
最后,用别人封装好的还是香啊,这个库后续估计还会对V3进行优化,到时候用起来就更滋润了!!
最后附上自己的demo,也包含V2接口!
demo
2020-12-02 微信JSAPIV3支付相关推荐
- 阿里IOT 应用托管部署 (2020/12/02)
当前时间: 2020/12/02 阿里更新迭代比较快, 不能保证文档的参考价值有多大 --------------------------------------------------------- ...
- JAVA生成二维码扫码进入h5微信支付宝支付
第一步准备 (1)微信需要的公众服务号和商户号:沙箱有很多问题,所以本人以正式的配置实现,其中公众号需要配置授权路径 其中公众号需配置 商户号需到产品中心 -> 开发配置 -> 支付配置 ...
- js获取微信状态栏高度_人人商城打包app教程 方法 hbuilder打包支持支付宝微信原生支付...
使用hbuilder打包人人商城app 方法支持微信支付宝原生支付 介绍 人人商城打包使用hbuilder打包app需要的文件,目前支持微信原生支付,支付宝原生支付,原生退出app ,还没有写分享和原 ...
- 2020年02月编程语言排行榜
2020年02月编程语言排行榜 最新 TIOBE 编程语言排行榜,关注编程语言动态 February Headline: Objective-C on its way out Objective-C ...
- 微信APP支付之IJpay的使用
写在开始:一个搬砖程序员的随缘记录 微信支付相对其他支付,比如支付宝支付坑比较多.一直报签名失败.签名参数顺序.数据类型,加密类型这些都需要注意,用第三方的比较省心. IJpay介绍: 聚合支付,IJ ...
- 用hbuilder打包php项目,hbuilder打包人人商城app教程方法 支持支付宝微信原生支付...
使用hbuilder打包人人商城app 方法支持微信支付宝原生支付 介绍 人人商城打包使用hbuilder打包app需要的文件,目前支持微信原生支付,支付宝原生支付,原生退出app ,还没有写分享和原 ...
- 【跃迁之路】【658天】程序员高效学习方法论探索系列(实验阶段415-2018.12.02)...
@(收集箱(每日一记,每周六整理))专栏 实验说明 从2017.10.6起,开启这个系列,目标只有一个:探索新的学习方法,实现跃迁式成长 实验期2年(2017.10.06 - 2019.10.06) ...
- JAVA微信APP支付接口整合
2019独角兽企业重金招聘Python工程师标准>>> 上次我们看到了支付宝的APP支付工具,那么这次就来封装封装微信的APP支付;如果已经清楚了支付宝的支付流程,那么微信支付也和它 ...
- h5通过php微信支付宝支付,用H5调用支付微信公众号支付的解析
这篇文章主要为大家详细介绍了微信公众号支付H5调用支付,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 最近项目需要微信支付,然后看了下微信公众号支付,虽然不难,但是细节还是需要注意的,用了大半天时 ...
最新文章
- Vivado 随笔(5) 行为仿真(Behavior Simulation)相关事宜?
- windows nginx站点分割日志_Nginx 基础用途拾遗
- python操作dom_Python Dom 的介绍和使用day1
- matlab randn 范围,请问randn产生的数据在什么范围内变化
- java中报错convension_LambdaConversionException与泛型:JVM错误?
- linux禁用root登录
- javascript座标_javascript JS元素位置和位置坐标
- python游戏制作软件_10 个最值得 Python 新人练手的有趣项目
- 阿里面试官的分享Java面试中需要准备哪些多线程并发的技术要点
- mockjs的介绍、基本使用和封装
- hdu 1890 Robotic SortI(splay区间旋转操作)
- Linux常用指令指南
- 未来的外科手术可能由气泡代劳
- 低配置享受3D立体游戏 手把手教你设置
- 百度的镜像网站,有意思…………
- Python调用百度API进行动植物识别
- 阿里云创始人王坚:别人可以背弃理想,我不可以
- rust建造一键升级_rust 使用国内镜像,快速安装方法
- (转)《达·芬奇密码》解读解密
- DataGrip 禁用自动同步
热门文章
- Js获取当前日期和农历日期
- python子域名扫描脚本
- CSS 内边距与外边距
- LeetCode_Stack_331. Verify Preorder Serialization of a Binary Tree 验证二叉树的前序序列化(Java)【栈,字符串处理】
- 4-逻辑控制器:Logic Controller
- Java程序:jstack
- 统计手机号耗费的总上行流量、下行流量、总流量(序列化)
- 第七届青年地学论坛女科学家论坛学习
- Ubuntu 16.04 无线网络 设备未就绪(device not ready)
- vue2 通过 axios 访问koa2,从mysql 拿到数据更新vue2中的内容