This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

Recently, there is a demand to withdraw cash from the merchant number of the enterprise. For example, if the user watches a video for a certain amount of time, the user will be rewarded with a certain amount of money. If the money is enough, the user can withdraw cash. This article is written wechat merchants withdraw cash to users wechat change.

Premise: The merchant number must have at least 30 days of running water. See wechat merchant withdrawal API for details

If you go to the API of wechat directly, and then write the interface, because wechat involves a lot of security issues, such as signature, various verification, if there is no third-party JAR, it is very difficult to write by yourself, and easy to make mistakes.

In the JAR written by a third party found in this paper, the developer only needs to pay attention to his own business, and the withdrawal logic only needs to call a method, which is very convenient. Basically, it can run through wechat to withdraw small change business in half an hour.

Pom.xml introduces the source code JAR package

< the dependency > < groupId > com. Making. Binarywang < / groupId > < artifactId > weixin - Java - pay < / artifactId > < version > 4.1.0 < / version > </dependency>Copy the code

The configuration file

Wx: pay: # public id appId wechat service id that requires user login AppID of the application APPID: 111111 # merchant id: 123456 # merchant key McHKey: 123456789 #p12 The absolute path to the certificate file or classpath keyPath: classpath:test.p12Copy the code

Both McHId and McHKey can be obtained at the merchant background. P12 certificate can be downloaded at the merchant background. The downloaded file is placed under Resources, which is the classpath starting with classpath:

Initialize the configuration file

import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; Created by Binary Wang on 2019/4/17. * </pre> ** @author <a href="https://github.com/binarywang">Binary Wang</a> */ @Data @ConfigurationProperties(prefix = "wx.pay") public class WxPayProperties {/** * private String appId; /** * private String McHId; /** * private String McHKey; /** * Sub-merchant public account ID in service provider mode. Do not set this parameter in common mode and delete the corresponding item in configuration file. */ private String subMchId; */ private String subMchId; */ private String subMchId; /** * The absolute path to the apiclient_cert.p12 file, or if placed in a project, specify it starting with classpath:. /** * private String serviceId; /** * Certificate serial number */ private String certSerialNo; /** * apiV3 key */ private String apiv3Key; /** * private String payScoreNotifyUrl; /** * private String privateKeyPath; /** * privateCertPath */ private String privateCertPath; }Copy the code

Wechat Pay is automatically configured

import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * <pre>
 *  微信支付自动配置
 *  Created by BinaryWang on 2019/4/17.
 * </pre>
 *
 * @author <a href="https://github.com/binarywang">Binary Wang</a>
 */
@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)
  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;
  }
}
Copy the code

The main withdrawal logic

EntPayRequest entPayRequest = new EntPayRequest(); Entpayrequest.setmchid (wxPayService.getConfig().getmchId ())); // Read from the configuration of the user login wechat service number application, if multiple service numbers read from their own database, This article only an application for a service number withdrawal appid entPayRequest. SetMchAppid (wxPayService. GetConfig () getAppId ()); Openid entpayRequest.setopenid (" openID "); openPayRequest.setopenid (" openID "); / / the current withdrawal order number - create your own entPayRequest. SetNonceStr (" oooopppxxx "); / / guarantee uniqueness idempotence ID create entPayRequest. SetPartnerTradeNo (" XXXXX "); entPayRequest.setCheckName("no_check"); Entpayrequest.setamount (100); / / Ip address Will not pass field entPayRequest. SetSpbillCreateIp (InetAddress. GetLocalHost () getHostAddress ()); EntPayRequest. SetDescription (" game show title "); / / call the withdrawal API EntPayResult EntPayResult = wxPayService. GetEntPayService () entPay (entPayRequest);Copy the code

Note: The cash unit of withdrawal is minute, other main parameters are compared with wechat official withdrawal to change API interface.

conclusion

Introduce the third-party payment JAR, configure merchant information, initialize the two configuration classes of wechat Pay, and then the business logic of cash withdrawal payment.

If it is an industrial-grade withdrawal, because cash is involved, a good suggestion is to make the withdrawal request and withdrawal to the user’s change asynchronous.

Verification strategy should be carried out in the cash-to-change business to prevent brushing. The cash-to-change business should be portable and can be stopped. Of course, the merchant background also has restrictions on the maximum number of withdrawals and the maximum withdrawal amount of users every day.

This paper simply runs through the main process of cash withdrawal, involving security and core development, so it is necessary to do security control by ourselves.