🆕 #3507 【微信支付】实现运营工具-商家转账API相关接口
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
package com.github.binarywang.wxpay.bean.transfer;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 运营工具-商家转账查询请求参数
|
||||
*
|
||||
* @author WxJava Team
|
||||
* @see <a href="https://pay.weixin.qq.com/doc/v3/merchant/4012711988">运营工具-商家转账API</a>
|
||||
*/
|
||||
@Data
|
||||
@Builder(builderMethodName = "newBuilder")
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BusinessOperationTransferQueryRequest implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 商户系统内部的商家单号
|
||||
* 与transfer_bill_no二选一
|
||||
*/
|
||||
@SerializedName("out_bill_no")
|
||||
private String outBillNo;
|
||||
|
||||
/**
|
||||
* 微信转账单号
|
||||
* 与out_bill_no二选一
|
||||
*/
|
||||
@SerializedName("transfer_bill_no")
|
||||
private String transferBillNo;
|
||||
|
||||
/**
|
||||
* 直连商户的appid
|
||||
* 可选
|
||||
*/
|
||||
@SerializedName("appid")
|
||||
private String appid;
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.github.binarywang.wxpay.bean.transfer;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 运营工具-商家转账查询结果
|
||||
*
|
||||
* @author WxJava Team
|
||||
* @see <a href="https://pay.weixin.qq.com/doc/v3/merchant/4012711988">运营工具-商家转账API</a>
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class BusinessOperationTransferQueryResult implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 直连商户的appid
|
||||
*/
|
||||
@SerializedName("appid")
|
||||
private String appid;
|
||||
|
||||
/**
|
||||
* 商户系统内部的商家单号
|
||||
*/
|
||||
@SerializedName("out_bill_no")
|
||||
private String outBillNo;
|
||||
|
||||
/**
|
||||
* 微信转账单号
|
||||
*/
|
||||
@SerializedName("transfer_bill_no")
|
||||
private String transferBillNo;
|
||||
|
||||
/**
|
||||
* 运营工具转账场景ID
|
||||
*/
|
||||
@SerializedName("operation_scene_id")
|
||||
private String operationSceneId;
|
||||
|
||||
/**
|
||||
* 用户在直连商户应用下的用户标示
|
||||
*/
|
||||
@SerializedName("openid")
|
||||
private String openid;
|
||||
|
||||
/**
|
||||
* 收款用户姓名
|
||||
* 已脱敏
|
||||
*/
|
||||
@SerializedName("user_name")
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 转账金额
|
||||
* 单位为"分"
|
||||
*/
|
||||
@SerializedName("transfer_amount")
|
||||
private Integer transferAmount;
|
||||
|
||||
/**
|
||||
* 转账备注
|
||||
*/
|
||||
@SerializedName("transfer_remark")
|
||||
private String transferRemark;
|
||||
|
||||
/**
|
||||
* 转账状态
|
||||
* WAIT_PAY:等待确认
|
||||
* PROCESSING:转账中
|
||||
* SUCCESS:转账成功
|
||||
* FAIL:转账失败
|
||||
* REFUND:已退款
|
||||
*/
|
||||
@SerializedName("transfer_state")
|
||||
private String transferState;
|
||||
|
||||
/**
|
||||
* 发起转账的时间
|
||||
* 遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE
|
||||
*/
|
||||
@SerializedName("create_time")
|
||||
private String createTime;
|
||||
|
||||
/**
|
||||
* 转账更新时间
|
||||
* 遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE
|
||||
*/
|
||||
@SerializedName("update_time")
|
||||
private String updateTime;
|
||||
|
||||
/**
|
||||
* 失败原因
|
||||
* 当transfer_state为FAIL时返回
|
||||
*/
|
||||
@SerializedName("fail_reason")
|
||||
private String failReason;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.github.binarywang.wxpay.bean.transfer;
|
||||
|
||||
import com.github.binarywang.wxpay.v3.SpecEncrypt;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 运营工具-商家转账请求参数
|
||||
*
|
||||
* @author WxJava Team
|
||||
* @see <a href="https://pay.weixin.qq.com/doc/v3/merchant/4012711988">运营工具-商家转账API</a>
|
||||
*/
|
||||
@Data
|
||||
@Builder(builderMethodName = "newBuilder")
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BusinessOperationTransferRequest implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 直连商户的appid
|
||||
* 必须
|
||||
*/
|
||||
@SerializedName("appid")
|
||||
private String appid;
|
||||
|
||||
/**
|
||||
* 商户系统内部的商家单号
|
||||
* 必须,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一
|
||||
*/
|
||||
@SerializedName("out_bill_no")
|
||||
private String outBillNo;
|
||||
|
||||
/**
|
||||
* 运营工具转账场景ID
|
||||
* 必须,用于标识运营工具转账的具体业务场景
|
||||
*/
|
||||
@SerializedName("operation_scene_id")
|
||||
private String operationSceneId;
|
||||
|
||||
/**
|
||||
* 用户在直连商户应用下的用户标示
|
||||
* 必须
|
||||
*/
|
||||
@SerializedName("openid")
|
||||
private String openid;
|
||||
|
||||
/**
|
||||
* 收款用户姓名
|
||||
* 可选,传入则校验收款用户姓名
|
||||
* 使用RSA加密,使用OAEP填充方式
|
||||
*/
|
||||
@SpecEncrypt
|
||||
@SerializedName("user_name")
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 转账金额
|
||||
* 必须,单位为"分"
|
||||
*/
|
||||
@SerializedName("transfer_amount")
|
||||
private Integer transferAmount;
|
||||
|
||||
/**
|
||||
* 转账备注
|
||||
* 必须,会在转账成功消息和转账详情页向用户展示
|
||||
*/
|
||||
@SerializedName("transfer_remark")
|
||||
private String transferRemark;
|
||||
|
||||
/**
|
||||
* 用户收款感知
|
||||
* 可选,用于在转账成功消息中向用户展示特定内容
|
||||
*/
|
||||
@SerializedName("user_recv_perception")
|
||||
private String userRecvPerception;
|
||||
|
||||
/**
|
||||
* 异步接收微信支付转账结果通知的回调地址
|
||||
* 可选,通知URL必须为外网可以正常访问的地址,不能携带查询参数
|
||||
*/
|
||||
@SerializedName("notify_url")
|
||||
private String notifyUrl;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.github.binarywang.wxpay.bean.transfer;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 运营工具-商家转账结果
|
||||
*
|
||||
* @author WxJava Team
|
||||
* @see <a href="https://pay.weixin.qq.com/doc/v3/merchant/4012711988">运营工具-商家转账API</a>
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class BusinessOperationTransferResult implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 商户系统内部的商家单号
|
||||
*/
|
||||
@SerializedName("out_bill_no")
|
||||
private String outBillNo;
|
||||
|
||||
/**
|
||||
* 微信转账单号
|
||||
* 微信商家转账系统返回的唯一标识
|
||||
*/
|
||||
@SerializedName("transfer_bill_no")
|
||||
private String transferBillNo;
|
||||
|
||||
/**
|
||||
* 转账状态
|
||||
* WAIT_PAY:等待确认
|
||||
* PROCESSING:转账中
|
||||
* SUCCESS:转账成功
|
||||
* FAIL:转账失败
|
||||
* REFUND:已退款
|
||||
*/
|
||||
@SerializedName("transfer_state")
|
||||
private String transferState;
|
||||
|
||||
/**
|
||||
* 发起转账的时间
|
||||
* 遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE
|
||||
*/
|
||||
@SerializedName("create_time")
|
||||
private String createTime;
|
||||
|
||||
/**
|
||||
* 转账更新时间
|
||||
* 遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE
|
||||
*/
|
||||
@SerializedName("update_time")
|
||||
private String updateTime;
|
||||
|
||||
/**
|
||||
* 失败原因
|
||||
* 当transfer_state为FAIL时返回
|
||||
*/
|
||||
@SerializedName("fail_reason")
|
||||
private String failReason;
|
||||
}
|
||||
@@ -412,6 +412,29 @@ public class WxPayConstants {
|
||||
public static final String CASH_MARKETING = "1001";
|
||||
}
|
||||
|
||||
/**
|
||||
* 【运营工具转账场景ID】 运营工具专用转账场景,用于商户日常运营活动
|
||||
*
|
||||
* @see <a href="https://pay.weixin.qq.com/doc/v3/merchant/4012711988">运营工具-商家转账API</a>
|
||||
*/
|
||||
@UtilityClass
|
||||
public static class OperationSceneId {
|
||||
/**
|
||||
* 运营工具现金营销
|
||||
*/
|
||||
public static final String OPERATION_CASH_MARKETING = "2001";
|
||||
|
||||
/**
|
||||
* 运营工具佣金报酬
|
||||
*/
|
||||
public static final String OPERATION_COMMISSION = "2002";
|
||||
|
||||
/**
|
||||
* 运营工具推广奖励
|
||||
*/
|
||||
public static final String OPERATION_PROMOTION = "2003";
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户收款感知
|
||||
*
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
package com.github.binarywang.wxpay.example;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.transfer.*;
|
||||
import com.github.binarywang.wxpay.config.WxPayConfig;
|
||||
import com.github.binarywang.wxpay.constant.WxPayConstants;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.github.binarywang.wxpay.service.BusinessOperationTransferService;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
|
||||
|
||||
/**
|
||||
* 运营工具-商家转账API使用示例
|
||||
*
|
||||
* 微信支付为商户提供的运营工具转账能力,用于商户的日常运营活动中进行转账操作
|
||||
*
|
||||
* @author WxJava Team
|
||||
* @see <a href="https://pay.weixin.qq.com/doc/v3/merchant/4012711988">运营工具-商家转账API</a>
|
||||
*/
|
||||
public class BusinessOperationTransferExample {
|
||||
|
||||
private WxPayService wxPayService;
|
||||
private BusinessOperationTransferService businessOperationTransferService;
|
||||
|
||||
public void init() {
|
||||
// 初始化配置
|
||||
WxPayConfig config = new WxPayConfig();
|
||||
config.setAppId("your_app_id");
|
||||
config.setMchId("your_mch_id");
|
||||
config.setMchKey("your_mch_key");
|
||||
config.setKeyPath("path_to_your_cert.p12");
|
||||
|
||||
// 初始化服务
|
||||
wxPayService = new WxPayServiceImpl();
|
||||
wxPayService.setConfig(config);
|
||||
businessOperationTransferService = wxPayService.getBusinessOperationTransferService();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发起运营工具转账示例
|
||||
*/
|
||||
public void createOperationTransferExample() {
|
||||
try {
|
||||
// 构建转账请求
|
||||
BusinessOperationTransferRequest request = BusinessOperationTransferRequest.newBuilder()
|
||||
.appid("your_app_id") // 应用ID
|
||||
.outBillNo("OT" + System.currentTimeMillis()) // 商户转账单号
|
||||
.operationSceneId(WxPayConstants.OperationSceneId.OPERATION_CASH_MARKETING) // 运营工具转账场景ID
|
||||
.openid("user_openid") // 用户openid
|
||||
.userName("张三") // 用户姓名(可选)
|
||||
.transferAmount(100) // 转账金额,单位分
|
||||
.transferRemark("运营活动奖励") // 转账备注
|
||||
.userRecvPerception(WxPayConstants.UserRecvPerception.CASH_MARKETING.CASH) // 用户收款感知
|
||||
.notifyUrl("https://your-domain.com/notify") // 回调通知地址
|
||||
.build();
|
||||
|
||||
// 发起转账
|
||||
BusinessOperationTransferResult result = businessOperationTransferService.createOperationTransfer(request);
|
||||
|
||||
System.out.println("转账成功!");
|
||||
System.out.println("商户单号: " + result.getOutBillNo());
|
||||
System.out.println("微信转账单号: " + result.getTransferBillNo());
|
||||
System.out.println("转账状态: " + result.getTransferState());
|
||||
System.out.println("创建时间: " + result.getCreateTime());
|
||||
|
||||
} catch (WxPayException e) {
|
||||
System.err.println("转账失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过商户单号查询转账结果示例
|
||||
*/
|
||||
public void queryByOutBillNoExample() {
|
||||
try {
|
||||
String outBillNo = "OT1640995200000"; // 商户转账单号
|
||||
|
||||
BusinessOperationTransferQueryResult result = businessOperationTransferService
|
||||
.queryOperationTransferByOutBillNo(outBillNo);
|
||||
|
||||
System.out.println("查询成功!");
|
||||
System.out.println("商户单号: " + result.getOutBillNo());
|
||||
System.out.println("微信转账单号: " + result.getTransferBillNo());
|
||||
System.out.println("转账状态: " + result.getTransferState());
|
||||
System.out.println("转账金额: " + result.getTransferAmount() + "分");
|
||||
System.out.println("创建时间: " + result.getCreateTime());
|
||||
System.out.println("更新时间: " + result.getUpdateTime());
|
||||
|
||||
} catch (WxPayException e) {
|
||||
System.err.println("查询失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过微信转账单号查询转账结果示例
|
||||
*/
|
||||
public void queryByTransferBillNoExample() {
|
||||
try {
|
||||
String transferBillNo = "1040000071100999991182020050700019480001"; // 微信转账单号
|
||||
|
||||
BusinessOperationTransferQueryResult result = businessOperationTransferService
|
||||
.queryOperationTransferByTransferBillNo(transferBillNo);
|
||||
|
||||
System.out.println("查询成功!");
|
||||
System.out.println("商户单号: " + result.getOutBillNo());
|
||||
System.out.println("微信转账单号: " + result.getTransferBillNo());
|
||||
System.out.println("运营场景ID: " + result.getOperationSceneId());
|
||||
System.out.println("转账状态: " + result.getTransferState());
|
||||
|
||||
} catch (WxPayException e) {
|
||||
System.err.println("查询失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用配置示例
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
BusinessOperationTransferExample example = new BusinessOperationTransferExample();
|
||||
|
||||
// 初始化配置
|
||||
example.init();
|
||||
|
||||
// 1. 发起运营工具转账
|
||||
example.createOperationTransferExample();
|
||||
|
||||
// 2. 查询转账结果
|
||||
// example.queryByOutBillNoExample();
|
||||
|
||||
// 3. 通过微信转账单号查询
|
||||
// example.queryByTransferBillNoExample();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.github.binarywang.wxpay.service;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.transfer.BusinessOperationTransferRequest;
|
||||
import com.github.binarywang.wxpay.bean.transfer.BusinessOperationTransferResult;
|
||||
import com.github.binarywang.wxpay.bean.transfer.BusinessOperationTransferQueryRequest;
|
||||
import com.github.binarywang.wxpay.bean.transfer.BusinessOperationTransferQueryResult;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
|
||||
/**
|
||||
* 运营工具-商家转账API
|
||||
* <p>
|
||||
* 微信支付为商户提供的运营工具转账能力,用于商户的日常运营活动中进行转账操作
|
||||
*
|
||||
* @author WxJava Team
|
||||
* @see <a href="https://pay.weixin.qq.com/doc/v3/merchant/4012711988">运营工具-商家转账API</a>
|
||||
*/
|
||||
public interface BusinessOperationTransferService {
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 发起运营工具商家转账
|
||||
*
|
||||
* 请求方式:POST(HTTPS)
|
||||
* 请求地址:https://api.mch.weixin.qq.com/v3/fund-app/operation/mch-transfer/transfer-bills
|
||||
*
|
||||
* 文档地址:<a href="https://pay.weixin.qq.com/doc/v3/merchant/4012711988">运营工具-商家转账API</a>
|
||||
* </pre>
|
||||
*
|
||||
* @param request 运营工具转账请求参数
|
||||
* @return BusinessOperationTransferResult 转账结果
|
||||
* @throws WxPayException 微信支付异常
|
||||
*/
|
||||
BusinessOperationTransferResult createOperationTransfer(BusinessOperationTransferRequest request) throws WxPayException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 查询运营工具转账结果
|
||||
*
|
||||
* 请求方式:GET(HTTPS)
|
||||
* 请求地址:https://api.mch.weixin.qq.com/v3/fund-app/operation/mch-transfer/transfer-bills/out-bill-no/{out_bill_no}
|
||||
*
|
||||
* 文档地址:<a href="https://pay.weixin.qq.com/doc/v3/merchant/4012711988">运营工具-商家转账API</a>
|
||||
* </pre>
|
||||
*
|
||||
* @param request 查询请求参数
|
||||
* @return BusinessOperationTransferQueryResult 查询结果
|
||||
* @throws WxPayException 微信支付异常
|
||||
*/
|
||||
BusinessOperationTransferQueryResult queryOperationTransfer(BusinessOperationTransferQueryRequest request) throws WxPayException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 通过商户单号查询运营工具转账结果
|
||||
*
|
||||
* 请求方式:GET(HTTPS)
|
||||
* 请求地址:https://api.mch.weixin.qq.com/v3/fund-app/operation/mch-transfer/transfer-bills/out-bill-no/{out_bill_no}
|
||||
*
|
||||
* 文档地址:<a href="https://pay.weixin.qq.com/doc/v3/merchant/4012711988">运营工具-商家转账API</a>
|
||||
* </pre>
|
||||
*
|
||||
* @param outBillNo 商户单号
|
||||
* @return BusinessOperationTransferQueryResult 查询结果
|
||||
* @throws WxPayException 微信支付异常
|
||||
*/
|
||||
BusinessOperationTransferQueryResult queryOperationTransferByOutBillNo(String outBillNo) throws WxPayException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 通过微信转账单号查询运营工具转账结果
|
||||
*
|
||||
* 请求方式:GET(HTTPS)
|
||||
* 请求地址:https://api.mch.weixin.qq.com/v3/fund-app/operation/mch-transfer/transfer-bills/transfer-bill-no/{transfer_bill_no}
|
||||
*
|
||||
* 文档地址:<a href="https://pay.weixin.qq.com/doc/v3/merchant/4012711988">运营工具-商家转账API</a>
|
||||
* </pre>
|
||||
*
|
||||
* @param transferBillNo 微信转账单号
|
||||
* @return BusinessOperationTransferQueryResult 查询结果
|
||||
* @throws WxPayException 微信支付异常
|
||||
*/
|
||||
BusinessOperationTransferQueryResult queryOperationTransferByTransferBillNo(String transferBillNo) throws WxPayException;
|
||||
}
|
||||
@@ -1646,6 +1646,13 @@ public interface WxPayService {
|
||||
*/
|
||||
TransferService getTransferService();
|
||||
|
||||
/**
|
||||
* 获取运营工具-商家转账服务类
|
||||
*
|
||||
* @return the business operation transfer service
|
||||
*/
|
||||
BusinessOperationTransferService getBusinessOperationTransferService();
|
||||
|
||||
/**
|
||||
* 获取服务商支付分服务类
|
||||
*
|
||||
|
||||
@@ -130,6 +130,9 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
|
||||
@Getter
|
||||
private final BrandMerchantTransferService brandMerchantTransferService = new BrandMerchantTransferServiceImpl(this);
|
||||
|
||||
@Getter
|
||||
private final BusinessOperationTransferService businessOperationTransferService = new BusinessOperationTransferServiceImpl(this);
|
||||
|
||||
protected Map<String, WxPayConfig> configMap = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
@@ -1415,4 +1418,9 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
|
||||
public TransferService getTransferService() {
|
||||
return transferService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BusinessOperationTransferService getBusinessOperationTransferService() {
|
||||
return businessOperationTransferService;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.github.binarywang.wxpay.service.impl;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.transfer.*;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.github.binarywang.wxpay.service.BusinessOperationTransferService;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
/**
|
||||
* 运营工具-商家转账API实现
|
||||
*
|
||||
* @author WxJava Team
|
||||
* @see <a href="https://pay.weixin.qq.com/doc/v3/merchant/4012711988">运营工具-商家转账API</a>
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class BusinessOperationTransferServiceImpl implements BusinessOperationTransferService {
|
||||
|
||||
private static final Gson GSON = new GsonBuilder().create();
|
||||
private final WxPayService wxPayService;
|
||||
|
||||
@Override
|
||||
public BusinessOperationTransferResult createOperationTransfer(BusinessOperationTransferRequest request) throws WxPayException {
|
||||
// 设置默认appid
|
||||
if (StringUtils.isEmpty(request.getAppid())) {
|
||||
request.setAppid(this.wxPayService.getConfig().getAppId());
|
||||
}
|
||||
|
||||
String url = String.format("%s/v3/fund-app/operation/mch-transfer/transfer-bills", this.wxPayService.getPayBaseUrl());
|
||||
|
||||
// 如果传入了用户姓名,需要进行RSA加密
|
||||
if (StringUtils.isNotEmpty(request.getUserName())) {
|
||||
X509Certificate validCertificate = this.wxPayService.getConfig().getVerifier().getValidCertificate();
|
||||
RsaCryptoUtil.encryptFields(request, validCertificate);
|
||||
}
|
||||
|
||||
String response = wxPayService.postV3WithWechatpaySerial(url, GSON.toJson(request));
|
||||
return GSON.fromJson(response, BusinessOperationTransferResult.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BusinessOperationTransferQueryResult queryOperationTransfer(BusinessOperationTransferQueryRequest request) throws WxPayException {
|
||||
if (StringUtils.isNotEmpty(request.getOutBillNo())) {
|
||||
return queryOperationTransferByOutBillNo(request.getOutBillNo());
|
||||
} else if (StringUtils.isNotEmpty(request.getTransferBillNo())) {
|
||||
return queryOperationTransferByTransferBillNo(request.getTransferBillNo());
|
||||
} else {
|
||||
throw new WxPayException("商户单号(out_bill_no)和微信转账单号(transfer_bill_no)必须提供其中一个");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BusinessOperationTransferQueryResult queryOperationTransferByOutBillNo(String outBillNo) throws WxPayException {
|
||||
String url = String.format("%s/v3/fund-app/operation/mch-transfer/transfer-bills/out-bill-no/%s",
|
||||
this.wxPayService.getPayBaseUrl(), outBillNo);
|
||||
String response = wxPayService.getV3(url);
|
||||
return GSON.fromJson(response, BusinessOperationTransferQueryResult.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BusinessOperationTransferQueryResult queryOperationTransferByTransferBillNo(String transferBillNo) throws WxPayException {
|
||||
String url = String.format("%s/v3/fund-app/operation/mch-transfer/transfer-bills/transfer-bill-no/%s",
|
||||
this.wxPayService.getPayBaseUrl(), transferBillNo);
|
||||
String response = wxPayService.getV3(url);
|
||||
return GSON.fromJson(response, BusinessOperationTransferQueryResult.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.github.binarywang.wxpay.service;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.transfer.*;
|
||||
import com.github.binarywang.wxpay.config.WxPayConfig;
|
||||
import com.github.binarywang.wxpay.constant.WxPayConstants;
|
||||
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* 运营工具-商家转账API测试
|
||||
*
|
||||
* @author WxJava Team
|
||||
*/
|
||||
public class BusinessOperationTransferServiceTest {
|
||||
|
||||
private WxPayService wxPayService;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() {
|
||||
WxPayConfig config = new WxPayConfig();
|
||||
config.setAppId("test_app_id");
|
||||
config.setMchId("test_mch_id");
|
||||
|
||||
wxPayService = new WxPayServiceImpl();
|
||||
wxPayService.setConfig(config);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServiceInitialization() {
|
||||
BusinessOperationTransferService service = this.wxPayService.getBusinessOperationTransferService();
|
||||
assertThat(service).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestBuilder() {
|
||||
BusinessOperationTransferRequest request = BusinessOperationTransferRequest.newBuilder()
|
||||
.appid("test_app_id")
|
||||
.outBillNo("OT" + System.currentTimeMillis())
|
||||
.operationSceneId(WxPayConstants.OperationSceneId.OPERATION_CASH_MARKETING)
|
||||
.openid("test_openid")
|
||||
.transferAmount(100)
|
||||
.transferRemark("测试转账")
|
||||
.userRecvPerception(WxPayConstants.UserRecvPerception.CASH_MARKETING.CASH)
|
||||
.build();
|
||||
|
||||
assertThat(request.getAppid()).isEqualTo("test_app_id");
|
||||
assertThat(request.getOperationSceneId()).isEqualTo(WxPayConstants.OperationSceneId.OPERATION_CASH_MARKETING);
|
||||
assertThat(request.getTransferAmount()).isEqualTo(100);
|
||||
assertThat(request.getTransferRemark()).isEqualTo("测试转账");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryRequestBuilder() {
|
||||
BusinessOperationTransferQueryRequest request = BusinessOperationTransferQueryRequest.newBuilder()
|
||||
.outBillNo("OT123456789")
|
||||
.appid("test_app_id")
|
||||
.build();
|
||||
|
||||
assertThat(request.getOutBillNo()).isEqualTo("OT123456789");
|
||||
assertThat(request.getAppid()).isEqualTo("test_app_id");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstants() {
|
||||
// 测试运营工具转账场景ID常量
|
||||
assertThat(WxPayConstants.OperationSceneId.OPERATION_CASH_MARKETING).isEqualTo("2001");
|
||||
assertThat(WxPayConstants.OperationSceneId.OPERATION_COMMISSION).isEqualTo("2002");
|
||||
assertThat(WxPayConstants.OperationSceneId.OPERATION_PROMOTION).isEqualTo("2003");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResultClasses() {
|
||||
// 测试结果类的基本功能
|
||||
BusinessOperationTransferResult result = new BusinessOperationTransferResult();
|
||||
result.setOutBillNo("test_out_bill_no");
|
||||
result.setTransferBillNo("test_transfer_bill_no");
|
||||
result.setTransferState("SUCCESS");
|
||||
|
||||
assertThat(result.getOutBillNo()).isEqualTo("test_out_bill_no");
|
||||
assertThat(result.getTransferBillNo()).isEqualTo("test_transfer_bill_no");
|
||||
assertThat(result.getTransferState()).isEqualTo("SUCCESS");
|
||||
|
||||
BusinessOperationTransferQueryResult queryResult = new BusinessOperationTransferQueryResult();
|
||||
queryResult.setOperationSceneId("2001");
|
||||
queryResult.setTransferAmount(100);
|
||||
|
||||
assertThat(queryResult.getOperationSceneId()).isEqualTo("2001");
|
||||
assertThat(queryResult.getTransferAmount()).isEqualTo(100);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user