最近在做自助洗车项目中,因每个门店需要使用自己的商户收款,所以需要wxjava多商户支持,在百度查了些资料,基本都是单个商户的使用案例,遂把项目中的一些总结分享。

先介绍下单商户的使用

  1. pom文件引入jar包
     <dependency><groupId>com.github.binarywang</groupId><artifactId>wx-java-pay-spring-boot-starter</artifactId><version>4.2.0</version></dependency>
  1. application.yml 配置商户信息
 wxpay:notifyUrl: 通知URIappId: 支付appidmchId: 微信支付商户IDmchKey: 商户api密匙#subAppId: 子商户appID  #服务商调用情况下需要#subMchId: 子商户微信支付商户ID #服务商调用情况下需要#keyPath: classpath:/static/apiclient_cert.p12 #需要退款等特殊操作需要证书,一般操作不用
  1. 然后在项目中注入service就可以使用了
     @Autowiredprivate WxPayService wxPayService;

单个商户使用非常简单,至于如何使用可以去wxjava github上面查看文档,或可以直接打开源码,每个方法上面都有详细的介绍

多商户如何使用

  1. 我们先分析下单商户是如何自动注入的
@Configuration
@EnableConfigurationProperties(WxPayProperties.class)
@ConditionalOnClass(WxPayService.class)
@ConditionalOnProperty(prefix = "wx.pay", value = "enabled", matchIfMissing = true)
public class WxPayAutoConfiguration {private WxPayProperties properties;@Autowiredpublic WxPayAutoConfiguration(WxPayProperties properties) {this.properties = properties;}/*** 构造微信支付服务对象.** @return 微信支付service*/@Bean@ConditionalOnMissingBean(WxPayService.class) //当没有WxPayService的时候就会自动创建此对象public WxPayService wxPayService() {final WxPayServiceImpl wxPayService = new WxPayServiceImpl();WxPayConfig payConfig = new WxPayConfig();payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppId()));payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey()));payConfig.setSubAppId(StringUtils.trimToNull(this.properties.getSubAppId()));payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId()));payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));//以下是apiv3以及支付分相关payConfig.setServiceId(StringUtils.trimToNull(this.properties.getServiceId()));payConfig.setPayScoreNotifyUrl(StringUtils.trimToNull(this.properties.getPayScoreNotifyUrl()));payConfig.setPrivateKeyPath(StringUtils.trimToNull(this.properties.getPrivateKeyPath()));payConfig.setPrivateCertPath(StringUtils.trimToNull(this.properties.getPrivateCertPath()));payConfig.setCertSerialNo(StringUtils.trimToNull(this.properties.getCertSerialNo()));payConfig.setApiV3Key(StringUtils.trimToNull(this.properties.getApiv3Key()));wxPayService.setConfig(payConfig);return wxPayService;}}
  1. 通过注解 @ConditionalOnMissingBean(WxPayService.class) 可以知道当没有WxPayService的时候就会自动创建此对象,那我们不用spring创建,自己创建一个WxPayService,然后添加多个商户信息。
 @Beanpublic WxPayService wxPayService() {final WxPayServiceImpl wxPayService = new WxPayServiceImpl();//通过数据库或者配置文件读取出所有的wxpay配置,我们这里用空的list模拟;List<Object> payConfigList = new ArrayList<>();for (Object o : payConfigList) {WxPayConfig payConfig = new WxPayConfig();//通过代码 将 o 对应赋值到payConfig。 此处忽略/*payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppId()));payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey()));payConfig.setSubAppId(StringUtils.trimToNull(this.properties.getSubAppId()));payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId()));payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));//以下是apiv3以及支付分相关payConfig.setServiceId(StringUtils.trimToNull(this.properties.getServiceId()));payConfig.setPayScoreNotifyUrl(StringUtils.trimToNull(this.properties.getPayScoreNotifyUrl()));payConfig.setPrivateKeyPath(StringUtils.trimToNull(this.properties.getPrivateKeyPath()));payConfig.setPrivateCertPath(StringUtils.trimToNull(this.properties.getPrivateCertPath()));payConfig.setCertSerialNo(StringUtils.trimToNull(this.properties.getCertSerialNo()));payConfig.setApiV3Key(StringUtils.trimToNull(this.properties.getApiv3Key()));*///注意这里是addConfig,而不是setConfig//第一个参数的作用是以后可以通过设置的这个key去拿到对应的wxPayService,因为现在是多个商户,通过这个key就能拿到对             应每个商户的service去调用//理论上这个key是可以放其他数据的,但是这里一定要记住,如果你没有特殊需求,这里就放mchId,否则你会引起不必要的麻              烦。这个我在文末会说。wxPayService.addConfig(payConfig.getMchId(),payConfig);}return wxPayService;}
  1. 业务代码中如何使用
     @Autowiredprivate WxPayService wxPayService;@PostMapping("/create")@Loginpublic R create(@RequestBody WxPayUnifiedOrderRequest request) throws WxPayException {//忽略业务代码//我们这里模拟mchId是通过业务代码查询出来门店对应的微信支付商户IDlong mchId = "123"//switchoverTo 就是通过key找到对应的商户配置,返回service就可以调用了。WxPayService myWxPayService = wxPayService.switchoverTo(mchId);return R.ok().put("orderInfo", myWxPayService.createOrder(request));}

血泪教训,一定要注意的事项

  • 一定不能在服务商模式中这样使用,一定不能在服务商模式中这样使用,一定不能在服务商模式中这样使用。
  • 还是上条,因为我在业务中把之前直联通道改成服务商模式后,导致收款出现问题,应该是付给店A的,付到店B这样的严重问题,后来用了一天时间才把账目对上。最后检查发现是addConfig的 key问题导致,因为服务商模式下mchId都是同样的,这样获取到的永远是第一个使用过的,导致出现问题,血泪教训,这个问题我在下篇文章中将会具体说明。
文末补充为什么addConfig没有特殊需求就放mchId

我们先查看addConfig的源码

  @Overridepublic void addConfig(String mchId, WxPayConfig wxPayConfig) {synchronized (this) {if (this.configMap == null) {this.setConfig(wxPayConfig); //注意跳转这里根本没有使用你设置的key} else {WxPayConfigHolder.set(mchId);this.configMap.put(mchId, wxPayConfig);}}}@Overridepublic void setConfig(WxPayConfig config) {final String defaultMchId = config.getMchId();//注意这里map key使用的是什么this.setMultiConfig(ImmutableMap.of(defaultMchId, config), defaultMchId);}
  • wxPayService默认有个configMap用来缓存所有的配置信息
protected Map<String, WxPayConfig> configMap;
  • 第一次addConfig时,因为configMap == null 它就会调用setConfig,而setConfig代码你会发现,它根本没有设置你的key,而是用了WxpayConfig默认的mchId,所以说如果你要设置自己的key在这里就会出现问题,导致你以后switchoverTo(”你设置的key“)时拿不到你想要的wxPayService了。这也就是我为什么建议没有特殊需求就放mchId。
  • 如何解决这个问题呢,就是你自己写一个service继承WxPayServiceImpl,重写这个addConfig方法。

写文不易,如果对您有帮助,点赞支持下~

下篇文章将会分享服务商模式如何使用以及遇到的坑~

wxjava 多商户 微信支付在springBoot项目中使用以及血泪教训相关推荐

  1. 一步步教你如何在SpringBoot项目中引入支付功能

    听说微信搜索<Java鱼仔>会变更强哦! 本文收录于JavaStarter ,里面有我完整的Java系列文章,学习或面试都可以看看哦 (一)引言 支付功能如今已经成为一个需要盈利的网站的基 ...

  2. 基于springboot项目中使用docker-compose+es+kibana+logstash+mysql 提高数据查询效率

    基于springboot项目中使用docker-compose+es+kibana+logstash+mysql 提高数据查询效率 1.拉取logstash,kibana,es,mysql镜像 #命令 ...

  3. SpringBoot项目中集成第三方登录功能

    SpringBoot项目中集成第三方登录功能 引言 1 环境准备 2 代码实现 3 第三方平台认证申请 4 打包和部署项目 5 第三方平台登录认证测试 6 参考文章 引言 最近想把自己在公众号上介绍过 ...

  4. Spring-Boot:写出来的网站访问不到静态资源?怎样通过url访问SpringBoot项目中的静态资源?localhost:8989/favicon.ico访问不了工程中的图标资源?

    Spring-Boot:Spring-Boot写出来的网站访问不到静态资源?怎样通过url访问SpringBoot项目中的静态资源?localhost:8989/favicon.ico访问不了工程中的 ...

  5. 使用IDEA在SpringBoot项目中连接数据库

    使用IDEA在SpringBoot项目中连接数据库 文章目录 使用IDEA在SpringBoot项目中连接数据库 前言 连接数据库 正常操作数据库 移除数据库连接 前言 每次我在 IDEA 中用 Sp ...

  6. IDEA springboot项目中properties配置文件 {针对将对应GBK改为UTF-8并勾选转为ASCII后仍无效情况} 运行时中文乱码解决

    springboot项目中properties配置文件中,运行时中文乱码情况 file encoding里边进行设置,设为utf-8并勾选转为ascii,分别在setting.setting for ...

  7. springboot项目中pom.xml文件的颜色变成灰色,图标变成蜘蛛图形

    问题 今天springboot项目中pom.xml文件的图标突然变成蜘蛛图案,pom.xml的内容大量报红,但项目任然可以正常运行 解决方法 点击idea右侧的 AntBuild,找到pom.xml, ...

  8. springboot项目中使用shiro 自定义过滤器和token的方式___shiro使用token登录流程

    springboot项目中使用shiro 自定义过滤器和token的方式 实现步骤主要是以下几步: 1. 在项目中导入maven依赖 <dependency><groupId> ...

  9. springboot项目中mybatis实现数据的基本查询

    SpringBoot项目中mybatis实现数据的基本查询 本章内容概述: mapper 查询 xml 文件基本使用 通过 mybatis 实现一条数据的查询 1 用户数据表 2 用户信息对应的实体类 ...

  10. SpringBoot项目中遇到的BUG

    1.启动项目的时候报错 1.Error starting ApplicationContext. To display the auto-configuration report re-run you ...

最新文章

  1. Pyhton 模块和包
  2. JavaScript中的基本数据类型与引用数据类型
  3. Oracle使用goldengate分别向Oracle和mysql双路的单向复制
  4. html5有foreach吗,JavaScript中的map()和forEach()有什么区别?
  5. AndroidStudio取消撤销、AS取消撤销;Ctrl+Shift+Z;
  6. openshift安装_云幸福–如何在几分钟内安装新的OpenShift Container Platform 3.7
  7. IE Firefox通用DOM
  8. JS最简单的IPv4转换成IPv6 方法
  9. Java毕设项目会议室预约管理系统(java+VUE+Mybatis+Maven+Mysql)
  10. Get Out of My Lab: Large-scale, Real-Time Visual-Inertial Localization文章理解
  11. 文章《Deep Image Homography Estimation》
  12. 纽约大学计算机和信息科学专业排名,纽约大学计算机科学与信息系统世界排名2021年最新排名第21(QS世界排名)...
  13. 你的童年经历过放牛,放羊,干农活吗?然后你现在对这些都怀念吗?
  14. 浏览器自动旋转图片问题的解决方式
  15. 大连医科大学中山学院模拟医院信息系统实验室建设完成
  16. IAR for MSP430 无法破解 的 解决办法
  17. 低代码开发平台如何支撑微服务/云原生架构
  18. Extends和Implement的不同?
  19. [附源码]计算机毕业设计的在线作业批改系统Springboot程序
  20. python打开谷歌浏览器新标签页_【Python】爬虫系列 | 3、谷歌浏览器的基本使用...

热门文章

  1. 常用输入法快速输入自定义格式的时间和日期(搜狗/QQ/手心/微软拼音)
  2. 入学人数突破1000人! 阿里云大学云学院,开启创新育才实践之路!
  3. 服务器物理硬盘序列号,查看硬盘物理序列号的程序源代码
  4. 如何用css设置文字加粗,css如何设置文字加粗
  5. RBAC 模型是什么?
  6. 【计算机视觉】exe视频转mp4、采集视频中图片记录、删除ABC看图王等软件
  7. 深度思考:到底什么是面向接口编程?
  8. 【软件推荐】电脑控制手机软件Scrcpy
  9. linux常识 菜鸟教程
  10. 图解: 线程状态转换(线程生命周期这一篇够用了)