前言

微信新出的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支付相关推荐

  1. 阿里IOT 应用托管部署 (2020/12/02)

    当前时间: 2020/12/02 阿里更新迭代比较快, 不能保证文档的参考价值有多大 --------------------------------------------------------- ...

  2. JAVA生成二维码扫码进入h5微信支付宝支付

    第一步准备 (1)微信需要的公众服务号和商户号:沙箱有很多问题,所以本人以正式的配置实现,其中公众号需要配置授权路径 其中公众号需配置 商户号需到产品中心 -> 开发配置 -> 支付配置 ...

  3. js获取微信状态栏高度_人人商城打包app教程 方法 hbuilder打包支持支付宝微信原生支付...

    使用hbuilder打包人人商城app 方法支持微信支付宝原生支付 介绍 人人商城打包使用hbuilder打包app需要的文件,目前支持微信原生支付,支付宝原生支付,原生退出app ,还没有写分享和原 ...

  4. 2020年02月编程语言排行榜

    2020年02月编程语言排行榜 最新 TIOBE 编程语言排行榜,关注编程语言动态 February Headline: Objective-C on its way out Objective-C ...

  5. 微信APP支付之IJpay的使用

    写在开始:一个搬砖程序员的随缘记录 微信支付相对其他支付,比如支付宝支付坑比较多.一直报签名失败.签名参数顺序.数据类型,加密类型这些都需要注意,用第三方的比较省心. IJpay介绍: 聚合支付,IJ ...

  6. 用hbuilder打包php项目,hbuilder打包人人商城app教程方法 支持支付宝微信原生支付...

    使用hbuilder打包人人商城app 方法支持微信支付宝原生支付 介绍 人人商城打包使用hbuilder打包app需要的文件,目前支持微信原生支付,支付宝原生支付,原生退出app ,还没有写分享和原 ...

  7. 【跃迁之路】【658天】程序员高效学习方法论探索系列(实验阶段415-2018.12.02)...

    @(收集箱(每日一记,每周六整理))专栏 实验说明 从2017.10.6起,开启这个系列,目标只有一个:探索新的学习方法,实现跃迁式成长 实验期2年(2017.10.06 - 2019.10.06) ...

  8. JAVA微信APP支付接口整合

    2019独角兽企业重金招聘Python工程师标准>>> 上次我们看到了支付宝的APP支付工具,那么这次就来封装封装微信的APP支付;如果已经清楚了支付宝的支付流程,那么微信支付也和它 ...

  9. h5通过php微信支付宝支付,用H5调用支付微信公众号支付的解析

    这篇文章主要为大家详细介绍了微信公众号支付H5调用支付,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 最近项目需要微信支付,然后看了下微信公众号支付,虽然不难,但是细节还是需要注意的,用了大半天时 ...

最新文章

  1. Vivado 随笔(5) 行为仿真(Behavior Simulation)相关事宜?
  2. windows nginx站点分割日志_Nginx 基础用途拾遗
  3. python操作dom_Python Dom 的介绍和使用day1
  4. matlab randn 范围,请问randn产生的数据在什么范围内变化
  5. java中报错convension_LambdaConversionException与泛型:JVM错误?
  6. linux禁用root登录
  7. javascript座标_javascript JS元素位置和位置坐标
  8. python游戏制作软件_10 个最值得 Python 新人练手的有趣项目
  9. 阿里面试官的分享Java面试中需要准备哪些多线程并发的技术要点
  10. mockjs的介绍、基本使用和封装
  11. hdu 1890 Robotic SortI(splay区间旋转操作)
  12. Linux常用指令指南
  13. 未来的外科手术可能由气泡代劳
  14. 低配置享受3D立体游戏 手把手教你设置
  15. 百度的镜像网站,有意思…………
  16. Python调用百度API进行动植物识别
  17. 阿里云创始人王坚:别人可以背弃理想,我不可以
  18. rust建造一键升级_rust 使用国内镜像,快速安装方法
  19. (转)《达·芬奇密码》解读解密
  20. DataGrip 禁用自动同步

热门文章

  1. Js获取当前日期和农历日期
  2. python子域名扫描脚本
  3. CSS 内边距与外边距
  4. LeetCode_Stack_331. Verify Preorder Serialization of a Binary Tree 验证二叉树的前序序列化(Java)【栈,字符串处理】
  5. 4-逻辑控制器:Logic Controller
  6. Java程序:jstack
  7. 统计手机号耗费的总上行流量、下行流量、总流量(序列化)
  8. 第七届青年地学论坛女科学家论坛学习
  9. Ubuntu 16.04 无线网络 设备未就绪(device not ready)
  10. vue2 通过 axios  访问koa2,从mysql 拿到数据更新vue2中的内容