Java整合微信商家转账到个人&开通流程

一、简介

  微信作为现在人民的使用,并且微信成为众多商家做活动的首选项,基于微信以前企业微信付款到零钱改为了企业微信商家转账到零钱。因为开发需求,亲自实现了企业微信商家转账到零钱的功能。

二、微信企业商家转账到零钱开通

开通条件:
1,商户号需入驻90天;
2,需要有连续30天的交易流水(截止今日回推30天)

流程:
找到产品中心,点击开通商家转账到零钱功能。
在这里插入图片描述
额度限制:
   跟以前微信企业支付到零钱一样,目前商户号企业转账功能开通后,初始额度统一为单用户单日单笔200元,单日总额度10W元,如果是初始商家账户,一个用户每日只能转账10次。
在这里插入图片描述
默认情况下,企业付款到零钱使用商户号基本户(或余额账户)余额。如商户号已开通运营账户,则企业付款到零钱使用运营账户内的资金。

三、实现商家转账到零钱(该功能需要跟微信公众号一起)

   微信公众号和商户号需要关联,可以在公众号查看是否关联。如图:
在这里插入图片描述
在这里插入图片描述

四、商户号实现转账方式

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

五、 Java代码实现案例

1、首先引入封装好的jar包

        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>wx-java-pay-spring-boot-starter</artifactId>
            <version>4.4.0</version>
        </dependency>

2、yml里面支付配置

wx:
  # 微信公众号
  mp:
    app-id: 微信公众号appid
    secret: 微信公众号密钥
    token: arecatoken
  # 微信企业支付
  pay:
    appId: 微信公众号appid
    mchId: 微信企业商户号
    apiv3-key: api3key密钥
    private-key-path: 证书apiclient_key
    private-cert-path: 证书apiclient_cert

3、具体Java代码如下

controller代码:

public class WxEntPayController {

    @Autowired
    private WxEntPayService wxEntPayService;

    /**
     * 支付接口
     *
     * @param entPayReq
     * @return
     */
    @AutoLog(value = "支付接口")
    @ApiOperation(value = "支付接口", notes = "支付接口")
    @PostMapping(value = "/entPay")
    public Result<?> entPay(@RequestBody EntPayReq entPayReq) {
        wxEntPayService.entPay(entPayReq);
        return Result.OK("支付成功!");
    }
}

EntPayReq 实体类:

@ApiModel("企业支付请求")
@Data
public class EntPayReq {
    /**
     * <pre>
     * 字段名:金额.
     * 变量名:amount
     * 是否必填:是
     * 示例值:10099
     * 类型:int
     * 描述:企业付款金额, 单位为分
     * </pre>
     */
    @NotNull(message = "金额不能为空")
    @Min(value = 30, message = "最小金额30分")
    @ApiModelProperty(value = "金额(单位分)", required = true)
    private Integer amount;

    /**
     * <pre>
     * 字段名:校验用户姓名选项.
     * 变量名:check_name
     * 是否必填:是
     * 示例值:OPTION_CHECK
     * 类型:String
     * 描述:NO_CHECK:不校验真实姓名 
     * FORCE_CHECK:强校验真实姓名(未实名认证的用户会校验失败,无法转账) 
     * OPTION_CHECK:针对已实名认证的用户才校验真实姓名(未实名认证用户不校验,可以转账成功)
     * </pre>
     */
    @ApiModelProperty(value = "校验用户姓名选项 [NO_CHECK:不校验真实姓名,FORCE_CHECK:强校验真实姓名(未实名认证的用户会校验失败,无法转账),OPTION_CHECK:针对已实名认证的用户才校验真实姓名(未实名认证用户不校验,可以转账成功)]")
    private String checkName;

    /**
     * <pre>
     * 字段名:收款用户姓名.
     * 变量名:re_user_name
     * 是否必填:可选
     * 示例值:马花花
     * 类型:String
     * 描述:收款用户真实姓名。
     * 如果check_name设置为FORCE_CHECK或OPTION_CHECK,  则必填用户真实姓名
     * </pre>
     */
    @ApiModelProperty("收款用户真实姓名")
    private String reUserName;

    /**
     * <pre>
     * 字段名:设备号.
     * 变量名:device_info
     * 是否必填:否
     * 示例值:13467007045764
     * 类型:String(32)
     * 描述:微信支付分配的终端设备号
     * </pre>
     */
    @ApiModelProperty("设备号")
    private String deviceInfo;

    /**
     * <pre>
     * 字段名:Ip地址.
     * 变量名:spbill_create_ip
     * 是否必填:是
     * 示例值:192.168.0.1
     * 类型:String(32)
     * 描述:调用接口的机器Ip地址
     * </pre>
     */
    @NotBlank(message = "不能为空")
    @ApiModelProperty(value = "Ip地址", required = true)
    private String spbillCreateIp;

    /**
     * 支付订单号
     */
    @ApiModelProperty(value = "支付订单号[非必填]")
    private String partnerTradeNo;

    /**
     * 批次订单号
     */
    @ApiModelProperty(value = "批次订单号")
    private String batchTradeNo;
}


业务层代码:

public interface WxEntPayService {
    /**
     * 微信支付
     *
     * @param entPayReq
     */
    void entPay(EntPayReq entPayReq);
} 

//业务实现代码

@Service
@Slf4j
public class WxEntPayServiceImpl implements WxEntPayService {

    @Autowired
    private WxPayService wxPayService;
    /**
     * 不校验真实姓名.
     */
    public static final String NO_CHECK = "NO_CHECK";

    /**
     * 微信支付
     *
     * @param req
     */
    @Override
    public void entPay(EntPayReq req) {
        log.info("开始企业支付到零钱 [req:{}]",req);
        req.setCheckName(StringUtils.isBlank(req.getCheckName()) ? NO_CHECK : req.getCheckName());
        //商户订单号
        String partnerTradeNo = StringUtils.isNotBlank(req.getPartnerTradeNo()) ? req.getPartnerTradeNo() : RandomUtil.randomInt(20);
        req.setPartnerTradeNo(partnerTradeNo);
        //随机获取批次号  切记仅用于测试
        String s =  RandomNumber.GetRandom();
        req.setBatchTradeNo(s);
        TransferService transferService = wxPayService.getTransferService();
        //获取appId
        String appId = wxPayService.getConfig().getAppId();
        //创建批次对象
        TransferBatchesRequest transferBatchesRequest=new TransferBatchesRequest();
        transferBatchesRequest.setAppid(appId);
        //设置批次名称 可不写
        transferBatchesRequest.setBatchName("测试批次");
        //设置批次备注 可不写
        transferBatchesRequest.setBatchRemark("测试");
        //设置该批次编号
        transferBatchesRequest.setOutBatchNo(s);
        //设置该批次总个数
        transferBatchesRequest.setTotalNum(1);
        //设置该批次总金额
        transferBatchesRequest.setTotalAmount(req.getAmount());
        //创建收款人请求对象
        ArrayList<TransferBatchesRequest.TransferDetail> transferDetails = new ArrayList<>();
        TransferBatchesRequest.TransferDetail transferDetail=new TransferBatchesRequest.TransferDetail();
        //转账的编号
        transferDetail.setOutDetailNo(req.getPartnerTradeNo());
        //转账的金额
        transferDetail.setTransferAmount(req.getAmount());
        //转账的注释
        transferDetail.setTransferRemark("转账金额");
        //以实际微信公众号那边的openid为准
        transferDetail.setOpenid("获取到用户的openid");
        //把收款人对象放到批次里面
        transferDetails.add(transferDetail);
        transferBatchesRequest.setTransferDetailList(transferDetails);
        TransferBatchesResult transferBatchesResult=null;
        try {
            transferBatchesResult = transferService.transferBatches(transferBatchesRequest);
            log.info("企业支付完成:[msg:{}]",transferBatchesResult);
        } catch (WxPayException e) {
            e.printStackTrace();
            log.info("企业支付失败:[msg:{}]",e.getMessage());
        }

    }


工具类代码:

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.locks.ReentrantLock;

public class RandomNumber {

    // 使用单例模式,不允许直接创建实例
    private RandomNumber() {
    }

    // 创建一个空实例对象,类需要用的时候才赋值
    private static RandomNumber instance = null;

    // 单例模式--懒汉模式
    public static synchronized RandomNumber getInstance() {
        if (instance == null) {
            instance = new RandomNumber();
        }
        return instance;
    }

    // 全局自增数
    private static int count = 1;
    // 格式化的时间字符串
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");

    // 获取当前时间年月日时分秒毫秒字符串
    private static String getNowDateStr() {
        return sdf.format(new Date());
    }

    // 记录上一次的时间,用来判断是否需要递增全局数
    private static String now = null;
    //定义锁对象
    private final static ReentrantLock lock = new ReentrantLock();

    //调用的方法
    public static String GetRandom() {
        String Newnumber = null;
        String dateStr = getNowDateStr();
        //加锁
        lock.lock();
        //判断是时间是否相同
        if (dateStr.equals(now)) {
            try {
                if (count >= 10000) {
                    count = 1;
                }
                if (count < 10) {
                    Newnumber = "N" + getNowDateStr() + "000" + count;
                } else if (count < 100) {
                    Newnumber = "N" + getNowDateStr() + "00" + count;
                } else if (count < 1000) {
                    Newnumber = "N" + getNowDateStr() + "0" + count;
                } else {
                    Newnumber = "N" + getNowDateStr() + count;
                }
                count++;
            } catch (Exception e) {

            } finally {
                lock.unlock();
            }
        } else {
            count = 1;
            now = getNowDateStr();
            try {
                if (count >= 10000) {
                    count = 1;
                }
                if (count < 10) {
                    Newnumber = "N" + getNowDateStr() + "000" + count;
                } else if (count < 100) {
                    Newnumber = "N" + getNowDateStr() + "00" + count;
                } else if (count < 1000) {
                    Newnumber = "N" + getNowDateStr() + "0" + count;
                } else {
                    Newnumber = "N" + getNowDateStr() + count;
                }
                count++;
            } catch (Exception e) {
            } finally {
                lock.unlock();
            }
        }
        return Newnumber;//返回的值
    }
}

这样就可以实现商家转账到零钱(单个人),该方法仅用于测试。
批量转账到零钱是为了实现一批次转账到多个账户的方法,这里我只用了一个用户转账

异常处理需要自己去写,暂时没有测试完全。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值