diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/BusinessOperationTransferQueryRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/BusinessOperationTransferQueryRequest.java new file mode 100644 index 0000000000..f1323655a1 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/BusinessOperationTransferQueryRequest.java @@ -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 运营工具-商家转账API + */ +@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; +} \ No newline at end of file diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/BusinessOperationTransferQueryResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/BusinessOperationTransferQueryResult.java new file mode 100644 index 0000000000..0cfd8f8570 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/BusinessOperationTransferQueryResult.java @@ -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 运营工具-商家转账API + */ +@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; +} \ No newline at end of file diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/BusinessOperationTransferRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/BusinessOperationTransferRequest.java new file mode 100644 index 0000000000..91d9438833 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/BusinessOperationTransferRequest.java @@ -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 运营工具-商家转账API + */ +@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; +} \ No newline at end of file diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/BusinessOperationTransferResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/BusinessOperationTransferResult.java new file mode 100644 index 0000000000..a380d6133e --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/BusinessOperationTransferResult.java @@ -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 运营工具-商家转账API + */ +@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; +} \ No newline at end of file diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java index e8a6b6acb3..b1a57ccc0f 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java @@ -412,6 +412,29 @@ public static class TransformSceneId { public static final String CASH_MARKETING = "1001"; } + /** + * 【运营工具转账场景ID】 运营工具专用转账场景,用于商户日常运营活动 + * + * @see 运营工具-商家转账API + */ + @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"; + } + /** * 用户收款感知 * diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/example/BusinessOperationTransferExample.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/example/BusinessOperationTransferExample.java new file mode 100644 index 0000000000..d11738816b --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/example/BusinessOperationTransferExample.java @@ -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 运营工具-商家转账API + */ +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(); + } +} \ No newline at end of file diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/BusinessOperationTransferService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/BusinessOperationTransferService.java new file mode 100644 index 0000000000..740c2af83f --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/BusinessOperationTransferService.java @@ -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 + *
+ * 微信支付为商户提供的运营工具转账能力,用于商户的日常运营活动中进行转账操作 + * + * @author WxJava Team + * @see 运营工具-商家转账API + */ +public interface BusinessOperationTransferService { + + /** + *
+ * 发起运营工具商家转账 + * + * 请求方式:POST(HTTPS) + * 请求地址:https://api.mch.weixin.qq.com/v3/fund-app/operation/mch-transfer/transfer-bills + * + * 文档地址:运营工具-商家转账API + *+ * + * @param request 运营工具转账请求参数 + * @return BusinessOperationTransferResult 转账结果 + * @throws WxPayException 微信支付异常 + */ + BusinessOperationTransferResult createOperationTransfer(BusinessOperationTransferRequest request) throws WxPayException; + + /** + *
+ * 查询运营工具转账结果 + * + * 请求方式:GET(HTTPS) + * 请求地址:https://api.mch.weixin.qq.com/v3/fund-app/operation/mch-transfer/transfer-bills/out-bill-no/{out_bill_no} + * + * 文档地址:运营工具-商家转账API + *+ * + * @param request 查询请求参数 + * @return BusinessOperationTransferQueryResult 查询结果 + * @throws WxPayException 微信支付异常 + */ + BusinessOperationTransferQueryResult queryOperationTransfer(BusinessOperationTransferQueryRequest request) throws WxPayException; + + /** + *
+ * 通过商户单号查询运营工具转账结果 + * + * 请求方式:GET(HTTPS) + * 请求地址:https://api.mch.weixin.qq.com/v3/fund-app/operation/mch-transfer/transfer-bills/out-bill-no/{out_bill_no} + * + * 文档地址:运营工具-商家转账API + *+ * + * @param outBillNo 商户单号 + * @return BusinessOperationTransferQueryResult 查询结果 + * @throws WxPayException 微信支付异常 + */ + BusinessOperationTransferQueryResult queryOperationTransferByOutBillNo(String outBillNo) throws WxPayException; + + /** + *
+ * 通过微信转账单号查询运营工具转账结果 + * + * 请求方式:GET(HTTPS) + * 请求地址:https://api.mch.weixin.qq.com/v3/fund-app/operation/mch-transfer/transfer-bills/transfer-bill-no/{transfer_bill_no} + * + * 文档地址:运营工具-商家转账API + *+ * + * @param transferBillNo 微信转账单号 + * @return BusinessOperationTransferQueryResult 查询结果 + * @throws WxPayException 微信支付异常 + */ + BusinessOperationTransferQueryResult queryOperationTransferByTransferBillNo(String transferBillNo) throws WxPayException; +} \ No newline at end of file diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java index 8ceac2b6ba..39062c82e4 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java @@ -1610,6 +1610,13 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri */ TransferService getTransferService(); + /** + * 获取运营工具-商家转账服务类 + * + * @return the business operation transfer service + */ + BusinessOperationTransferService getBusinessOperationTransferService(); + /** * 获取服务商支付分服务类 * diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java index 5057ef2b6b..acf39196b3 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java @@ -128,6 +128,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