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

最近在做自助洗车项目中,因每个门店需要使用自己的商户收款,所以需要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 配置商户信息
 wx
   pay:
    notifyUrl: 通知URI
    appId: 支付appid
    mchId: 微信支付商户ID
    mchKey: 商户api密匙
    #subAppId: 子商户appID  #服务商调用情况下需要
    #subMchId: 子商户微信支付商户ID #服务商调用情况下需要
    #keyPath: classpath:/static/apiclient_cert.p12 #需要退款等特殊操作需要证书,一般操作不用
  1. 然后在项目中注入service就可以使用了
 	@Autowired
    private 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;

  @Autowired
  public 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,然后添加多个商户信息。
	@Bean
    public 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. 业务代码中如何使用
 	@Autowired
    private WxPayService wxPayService;
    
    
    @PostMapping("/create")
    @Login
    public R create(@RequestBody WxPayUnifiedOrderRequest request) throws WxPayException {
        
        //忽略业务代码
        //我们这里模拟mchId是通过业务代码查询出来门店对应的微信支付商户ID
		long 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的源码

  @Override
  public 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);
      }
    }
  }
  
  @Override
  public 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方法。

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

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

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
### 回答1: 微信小程序是一款通过微信平台开发的应用,可以在微信内直接运行。SpringBoot是一个基于Spring框架的开发工具,可以简化Spring项目的配置和部署。 在开发微信小程序的过程,可以使用SpringBoot来构建后端服务器,提供数据接口和业务逻辑的实现。SpringBoot可以快速地搭建一个基于Java的后端开发环境,简化了配置,提高了开发效率。 首先,我们可以使用SpringBoot来创建一个基础的项目结构。通过使用Maven或者Gradle构建工具,可以快速生成项目的骨架代码,并引入所需的SpringBoot依赖。 其次,我们可以在项目引入微信小程序的SDK,例如微信小程序开发工具提供的Java SDK。通过SDK提供的API,我们可以进行用户登录验证、获取用户信息、发送模板消息等功能的实现。 然后,我们可以使用SpringBoot来处理前端请求并返回相应的数据。通过注解方式配置接口路由,并使用SpringBoot提供的@RestController注解来标识一个控制器,处理前端请求。可以在控制器调用微信小程序SDK提供的接口,从而获取用户信息、发送消息等。 最后,我们可以使用SpringBoot的数据库操作支持来进行数据的增删改查。可以使用ORM框架,如MyBatis或者Hibernate,来简化数据库操作的实现。通过使用SpringBoot的数据源配置,可以快速地配置数据库连接。 综上所述,微信小程序SpringBoot项目是一种通过使用SpringBoot构建后端服务器,实现微信小程序的功能和业务逻辑的开发方式。通过SpringBoot的快速开发特性和丰富的生态系统,可以减少开发成本,提高开发效率。 ### 回答2: 微信小程序是一种基于微信平台开发的应用程序,而Spring Boot是一种基于Java语言的开发框架。在开发微信小程序的过程,我们可以选择使用Spring Boot作为后端开发工具,来构建和管理我们的项目使用Spring Boot搭建微信小程序项目可以带来以下好处: 1. 快速搭建:Spring Boot提供了自动化配置和快速启动的特性,可以让我们快速建立一个基础的项目框架,省去了繁琐的配置过程。 2. 简单易用:Spring Boot提供了丰富的开箱即用功能和规范,可以轻松集成微信小程序的功能模块,如用户登录、数据交互等。 3. 强大的生态圈:Spring Boot拥有庞大的社区和丰富的第三方库支持,可以快速解决常见问题,提高开发效率。 4. 易于维护和扩展:Spring Boot的代码规范和模块化设计使得项目易于维护和扩展,可以快速响应需求变化。 在使用Spring Boot开发微信小程序项目时,我们可以通过使用Spring Boot的Web开发框架来处理小程序的请求和响应,使用Spring的数据访问框架来实现与数据库的交互,使用Spring Security来实现用户认证和授权等功能。 总之,将Spring Boot应用于微信小程序开发,可以帮助我们构建高效、可扩展和易维护的项目,提升开发效率并满足用户需求。 ### 回答3: 微信小程序是一种基于微信平台的应用程序,可以在手机上进行快速的开发和分享。而Spring Boot是一种开发框架,它可以简化Java应用程序的开发过程,并提供快速的开源工具和库。 结合微信小程序和Spring Boot可以实现一个强大的移动应用后端,提供数据接口和业务逻辑处理。在微信小程序,前端部分负责展示界面和用户交互,而后端Spring Boot项目则负责数据的处理和提供接口。 首先,需要建立一个Spring Boot项目,设置好相关的开发环境。然后,通过引入一些必要的依赖,如Spring Boot的Web模块、数据库连接、安全验证等,来支持项目的开发。 接下来,可以编写后端的逻辑代码,处理微信小程序的请求,如登录、支付、获取数据等等。同时,可以使用Spring Boot提供的ORM框架,如MyBatis或Spring Data JPA,来操作数据库,存储和读取数据。 在整个开发过程,可以使用一些辅助工具,如Spring Boot的开发工具包、微信小程序SDK等,来提高开发效率和便利性。 最后,需要对项目进行测试和部署。可以使用一些自动化测试工具,如JUnit或Postman,来验证接口的正确性。然后,可以将项目打包成可执行的jar文件,部署到服务器上,供微信小程序调用和访问。 综上所述,微信小程序Spring Boot项目可以通过前后端分离的方式,实现微信小程序的功能和服务,并提供高效的开发和管理。这种组合可以满足移动应用开发的需求,并提供稳定和可靠的后台支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值