diff --git a/service/src/example/java/com/wechat/pay/java/service/payments/PaymentNotificationParseServiceExample.java b/service/src/example/java/com/wechat/pay/java/service/payments/PaymentNotificationParseServiceExample.java new file mode 100644 index 00000000..3e3a3a93 --- /dev/null +++ b/service/src/example/java/com/wechat/pay/java/service/payments/PaymentNotificationParseServiceExample.java @@ -0,0 +1,63 @@ +package com.wechat.pay.java.service.payments; + +import com.wechat.pay.java.core.RSAAutoCertificateConfig; +import com.wechat.pay.java.core.exception.MalformedMessageException; +import com.wechat.pay.java.core.exception.ValidationException; +import com.wechat.pay.java.core.notification.NotificationConfig; +import com.wechat.pay.java.core.notification.RequestParam; +import com.wechat.pay.java.service.payments.model.Transaction; + +/** PaymentNotificationParseService使用示例 */ +public class PaymentNotificationParseServiceExample { + + /** 商户号 */ + public static String merchantId = "190000****"; + + /** 商户API私钥路径 */ + public static String privateKeyPath = "/Users/yourname/your/path/apiclient_key.pem"; + + /** 商户证书序列号 */ + public static String merchantSerialNumber = "5157F09EFDC096DE15EBE81A47057A72********"; + + /** 商户APIV3密钥 */ + public static String apiV3Key = "..."; + + public static PaymentNotificationParseService service; + + public static void main(String[] args) { + // 初始化商户配置 + NotificationConfig config = + new RSAAutoCertificateConfig.Builder() + .merchantId(merchantId) + // 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名 + .privateKeyFromPath(privateKeyPath) + .merchantSerialNumber(merchantSerialNumber) + .apiV3Key(apiV3Key) + .build(); + + // 初始化服务 + service = new PaymentNotificationParseService.Builder().config(config).build(); + // ... 调用接口 + try { + RequestParam requestParam = + new RequestParam.Builder() + .serialNumber("5157F09EFDC096DE15EBE81A47057A72********") + .signature("mm/2CMGxo5qDKNk1i7Szn0IiwAUPlfrp********") + .timestamp("1723789635") + .nonce("614275b63d789bd3a7a472c63d809552") + .body("") + .signType("WECHATPAY2-SHA256-RSA2048") + .build(); + Transaction transaction = payment(requestParam); + } catch (MalformedMessageException e) { // 回调通知参数不正确、解析通知数据失败 + // 调用e.getMessage()获取信息打印日志或上报监控,更多方法见MalformedMessageException定义 + } catch (ValidationException e) { // 签名验证失败 + // 调用e.getMessage()获取信息打印日志或上报监控,更多方法见ValidationException定义 + } + } + + /** 支付回调 */ + public static Transaction payment(RequestParam requestParam) { + return service.payment(requestParam); + } +} diff --git a/service/src/example/java/com/wechat/pay/java/service/refund/RefundNotificationParseServiceExample.java b/service/src/example/java/com/wechat/pay/java/service/refund/RefundNotificationParseServiceExample.java new file mode 100644 index 00000000..0cd141dd --- /dev/null +++ b/service/src/example/java/com/wechat/pay/java/service/refund/RefundNotificationParseServiceExample.java @@ -0,0 +1,63 @@ +package com.wechat.pay.java.service.refund; + +import com.wechat.pay.java.core.RSAAutoCertificateConfig; +import com.wechat.pay.java.core.exception.MalformedMessageException; +import com.wechat.pay.java.core.exception.ValidationException; +import com.wechat.pay.java.core.notification.NotificationConfig; +import com.wechat.pay.java.core.notification.RequestParam; +import com.wechat.pay.java.service.refund.model.RefundNotification; + +/** RefundNotificationParseService使用示例 */ +public class RefundNotificationParseServiceExample { + + /** 商户号 */ + public static String merchantId = "190000****"; + + /** 商户API私钥路径 */ + public static String privateKeyPath = "/Users/yourname/your/path/apiclient_key.pem"; + + /** 商户证书序列号 */ + public static String merchantSerialNumber = "5157F09EFDC096DE15EBE81A47057A72********"; + + /** 商户APIV3密钥 */ + public static String apiV3Key = "..."; + + public static RefundNotificationParseService service; + + public static void main(String[] args) { + // 初始化商户配置 + NotificationConfig config = + new RSAAutoCertificateConfig.Builder() + .merchantId(merchantId) + // 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名 + .privateKeyFromPath(privateKeyPath) + .merchantSerialNumber(merchantSerialNumber) + .apiV3Key(apiV3Key) + .build(); + + // 初始化服务 + service = new RefundNotificationParseService.Builder().config(config).build(); + // ... 调用接口 + try { + RequestParam requestParam = + new RequestParam.Builder() + .serialNumber("5157F09EFDC096DE15EBE81A47057A72********") + .signature("mm/2CMGxo5qDKNk1i7Szn0IiwAUPlfrp********") + .timestamp("1723789635") + .nonce("614275b63d789bd3a7a472c63d809552") + .body("") + .signType("WECHATPAY2-SHA256-RSA2048") + .build(); + RefundNotification refundNotification = refund(requestParam); + } catch (MalformedMessageException e) { // 回调通知参数不正确、解析通知数据失败 + // 调用e.getMessage()获取信息打印日志或上报监控,更多方法见MalformedMessageException定义 + } catch (ValidationException e) { // 签名验证失败 + // 调用e.getMessage()获取信息打印日志或上报监控,更多方法见ValidationException定义 + } + } + + /** 退款回调 */ + public static RefundNotification refund(RequestParam requestParam) { + return service.refund(requestParam); + } +} diff --git a/service/src/example/java/com/wechat/pay/java/service/transferbatch/TransferBatchNotificationParseServiceExample.java b/service/src/example/java/com/wechat/pay/java/service/transferbatch/TransferBatchNotificationParseServiceExample.java new file mode 100644 index 00000000..c7585134 --- /dev/null +++ b/service/src/example/java/com/wechat/pay/java/service/transferbatch/TransferBatchNotificationParseServiceExample.java @@ -0,0 +1,63 @@ +package com.wechat.pay.java.service.transferbatch; + +import com.wechat.pay.java.core.RSAAutoCertificateConfig; +import com.wechat.pay.java.core.exception.MalformedMessageException; +import com.wechat.pay.java.core.exception.ValidationException; +import com.wechat.pay.java.core.notification.NotificationConfig; +import com.wechat.pay.java.core.notification.RequestParam; +import com.wechat.pay.java.service.transferbatch.model.TransferBatchNotification; + +/** TransferBatchNotificationParseService使用示例 */ +public class TransferBatchNotificationParseServiceExample { + + /** 商户号 */ + public static String merchantId = "190000****"; + + /** 商户API私钥路径 */ + public static String privateKeyPath = "/Users/yourname/your/path/apiclient_key.pem"; + + /** 商户证书序列号 */ + public static String merchantSerialNumber = "5157F09EFDC096DE15EBE81A47057A72********"; + + /** 商户APIV3密钥 */ + public static String apiV3Key = "..."; + + public static TransferBatchNotificationParseService service; + + public static void main(String[] args) { + // 初始化商户配置 + NotificationConfig config = + new RSAAutoCertificateConfig.Builder() + .merchantId(merchantId) + // 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名 + .privateKeyFromPath(privateKeyPath) + .merchantSerialNumber(merchantSerialNumber) + .apiV3Key(apiV3Key) + .build(); + + // 初始化服务 + service = new TransferBatchNotificationParseService.Builder().config(config).build(); + // ... 调用接口 + try { + RequestParam requestParam = + new RequestParam.Builder() + .serialNumber("5157F09EFDC096DE15EBE81A47057A72********") + .signature("mm/2CMGxo5qDKNk1i7Szn0IiwAUPlfrp********") + .timestamp("1723789635") + .nonce("614275b63d789bd3a7a472c63d809552") + .body("") + .signType("WECHATPAY2-SHA256-RSA2048") + .build(); + TransferBatchNotification transferBatchNotification = transferBatch(requestParam); + } catch (MalformedMessageException e) { // 回调通知参数不正确、解析通知数据失败 + // 调用e.getMessage()获取信息打印日志或上报监控,更多方法见MalformedMessageException定义 + } catch (ValidationException e) { // 签名验证失败 + // 调用e.getMessage()获取信息打印日志或上报监控,更多方法见ValidationException定义 + } + } + + /** 商家转账批次回调 */ + public static TransferBatchNotification transferBatch(RequestParam requestParam) { + return service.transferBatch(requestParam); + } +} diff --git a/service/src/main/java/com/wechat/pay/java/service/payments/PaymentNotificationParseService.java b/service/src/main/java/com/wechat/pay/java/service/payments/PaymentNotificationParseService.java new file mode 100644 index 00000000..101f9618 --- /dev/null +++ b/service/src/main/java/com/wechat/pay/java/service/payments/PaymentNotificationParseService.java @@ -0,0 +1,59 @@ +package com.wechat.pay.java.service.payments; + +import static java.util.Objects.requireNonNull; + +import com.wechat.pay.java.core.exception.MalformedMessageException; +import com.wechat.pay.java.core.exception.ValidationException; +import com.wechat.pay.java.core.notification.NotificationConfig; +import com.wechat.pay.java.core.notification.NotificationParser; +import com.wechat.pay.java.core.notification.RequestParam; +import com.wechat.pay.java.service.payments.model.Transaction; + +/** + * 支付回调通知解析服务 + * + *

它用于对 支付回调 进行验签并解析回调报文。 + */ +public class PaymentNotificationParseService { + private final NotificationParser parser; + + private PaymentNotificationParseService(NotificationParser parser) { + this.parser = requireNonNull(parser); + } + + /** PaymentNotificationParseService构造器 */ + public static class Builder { + + private NotificationConfig config; + private NotificationParser parser; + + public PaymentNotificationParseService.Builder config(NotificationConfig config) { + this.config = config; + return this; + } + + public PaymentNotificationParseService.Builder parser(NotificationParser parser) { + this.parser = parser; + return this; + } + + public PaymentNotificationParseService build() { + if (parser == null && config != null) { + return new PaymentNotificationParseService(new NotificationParser(config)); + } + return new PaymentNotificationParseService(parser); + } + } + + /** + * 支付回调通知解析 + * + * @param requestParam 解析通知所需要的请求参数 + * @return 解析后的回调报文 + * @throws MalformedMessageException 回调通知参数不正确、解析通知数据失败 + * @throws ValidationException 签名验证失败 + */ + public Transaction payment(RequestParam requestParam) { + return parser.parse(requestParam, Transaction.class); + } +} diff --git a/service/src/main/java/com/wechat/pay/java/service/refund/RefundNotificationParseService.java b/service/src/main/java/com/wechat/pay/java/service/refund/RefundNotificationParseService.java new file mode 100644 index 00000000..0ae7ad29 --- /dev/null +++ b/service/src/main/java/com/wechat/pay/java/service/refund/RefundNotificationParseService.java @@ -0,0 +1,59 @@ +package com.wechat.pay.java.service.refund; + +import static java.util.Objects.requireNonNull; + +import com.wechat.pay.java.core.exception.MalformedMessageException; +import com.wechat.pay.java.core.exception.ValidationException; +import com.wechat.pay.java.core.notification.NotificationConfig; +import com.wechat.pay.java.core.notification.NotificationParser; +import com.wechat.pay.java.core.notification.RequestParam; +import com.wechat.pay.java.service.refund.model.RefundNotification; + +/** + * 退款回调通知解析服务 + * + *

它用于对 退款回调 进行验签并解析回调报文。 + */ +public class RefundNotificationParseService { + private final NotificationParser parser; + + private RefundNotificationParseService(NotificationParser parser) { + this.parser = requireNonNull(parser); + } + + /** RefundNotificationParseService构造器 */ + public static class Builder { + + private NotificationConfig config; + private NotificationParser parser; + + public RefundNotificationParseService.Builder config(NotificationConfig config) { + this.config = config; + return this; + } + + public RefundNotificationParseService.Builder parser(NotificationParser parser) { + this.parser = parser; + return this; + } + + public RefundNotificationParseService build() { + if (parser == null && config != null) { + return new RefundNotificationParseService(new NotificationParser(config)); + } + return new RefundNotificationParseService(parser); + } + } + + /** + * 退款回调通知解析 + * + * @param requestParam 解析通知所需要的请求参数 + * @return 解析后的回调报文 + * @throws MalformedMessageException 回调通知参数不正确、解析通知数据失败 + * @throws ValidationException 签名验证失败 + */ + public RefundNotification refund(RequestParam requestParam) { + return parser.parse(requestParam, RefundNotification.class); + } +} diff --git a/service/src/main/java/com/wechat/pay/java/service/transferbatch/TransferBatchNotificationParseService.java b/service/src/main/java/com/wechat/pay/java/service/transferbatch/TransferBatchNotificationParseService.java new file mode 100644 index 00000000..69bae9ac --- /dev/null +++ b/service/src/main/java/com/wechat/pay/java/service/transferbatch/TransferBatchNotificationParseService.java @@ -0,0 +1,59 @@ +package com.wechat.pay.java.service.transferbatch; + +import static java.util.Objects.requireNonNull; + +import com.wechat.pay.java.core.exception.MalformedMessageException; +import com.wechat.pay.java.core.exception.ValidationException; +import com.wechat.pay.java.core.notification.NotificationConfig; +import com.wechat.pay.java.core.notification.NotificationParser; +import com.wechat.pay.java.core.notification.RequestParam; +import com.wechat.pay.java.service.transferbatch.model.TransferBatchNotification; + +/** + * 商家转账批次回调通知解析服务 + * + *

它用于对 商家转账批次回调 进行验签并解析回调报文。 + */ +public class TransferBatchNotificationParseService { + private final NotificationParser parser; + + private TransferBatchNotificationParseService(NotificationParser parser) { + this.parser = requireNonNull(parser); + } + + /** TransferBatchNotificationParseService构造器 */ + public static class Builder { + + private NotificationConfig config; + private NotificationParser parser; + + public TransferBatchNotificationParseService.Builder config(NotificationConfig config) { + this.config = config; + return this; + } + + public TransferBatchNotificationParseService.Builder parser(NotificationParser parser) { + this.parser = parser; + return this; + } + + public TransferBatchNotificationParseService build() { + if (parser == null && config != null) { + return new TransferBatchNotificationParseService(new NotificationParser(config)); + } + return new TransferBatchNotificationParseService(parser); + } + } + + /** + * 商家转账批次回调通知解析 + * + * @param requestParam 解析通知所需要的请求参数 + * @return 解析后的回调报文 + * @throws MalformedMessageException 回调通知参数不正确、解析通知数据失败 + * @throws ValidationException 签名验证失败 + */ + public TransferBatchNotification transferBatch(RequestParam requestParam) { + return parser.parse(requestParam, TransferBatchNotification.class); + } +} diff --git a/service/src/main/java/com/wechat/pay/java/service/transferbatch/model/TransferBatchNotification.java b/service/src/main/java/com/wechat/pay/java/service/transferbatch/model/TransferBatchNotification.java new file mode 100644 index 00000000..36b73f32 --- /dev/null +++ b/service/src/main/java/com/wechat/pay/java/service/transferbatch/model/TransferBatchNotification.java @@ -0,0 +1,164 @@ +package com.wechat.pay.java.service.transferbatch.model; + +import com.google.gson.annotations.SerializedName; +import com.wechat.pay.java.core.util.GsonUtil; + +/** TransferBatchNotification */ +public class TransferBatchNotification { + /** 商户号 说明:微信支付分配的商户号 */ + @SerializedName("mchid") + private String mchid; + + /** 商家批次单号 说明:商户系统内部的商家批次单号,在商户系统内部唯一 */ + @SerializedName("out_batch_no") + private String outBatchNo; + + /** 微信批次单号 说明:微信批次单号,微信商家转账系统返回的唯一标识 */ + @SerializedName("batch_id") + private String batchId; + + /** + * 批次状态 说明:WAIT_PAY: 待付款确认。需要付款出资商户在商家助手小程序或服务商助手小程序进行付款确认 + * ACCEPTED:已受理。批次已受理成功,若发起批量转账的30分钟后,转账批次单仍处于该状态,可能原因是商户账户余额不足等。商户可查询账户资金流水,若该笔转账批次单的扣款已经发生,则表示批次已经进入转账中,请再次查单确认 + * PROCESSING:转账中。已开始处理批次内的转账明细单 FINISHED:已完成。批次内的所有转账明细单都已处理完成 CLOSED:已关闭。可查询具体的批次关闭原因确认 + */ + @SerializedName("batch_status") + private String batchStatus; + + /** 批次关闭原因 说明:如果批次单状态为“CLOSED”(已关闭),则有关闭原因 */ + @SerializedName("close_reason") + private CloseReasonType closeReason; + + /** 转账总金额 说明:转账金额单位为“分” */ + @SerializedName("total_amount") + private Long totalAmount; + + /** 转账总笔数 说明:一个转账批次单最多发起三千笔转账 */ + @SerializedName("total_num") + private Integer totalNum; + + /** 转账成功金额 说明:转账成功的金额,单位为“分”。当批次状态为“PROCESSING”(转账中)时,转账成功金额随时可能变化 */ + @SerializedName("success_amount") + private Long successAmount; + + /** 转账成功笔数 说明:转账成功的笔数。当批次状态为“PROCESSING”(转账中)时,转账成功笔数随时可能变化 */ + @SerializedName("success_num") + private Integer successNum; + + /** 转账失败金额 说明:转账失败的金额,单位为“分” */ + @SerializedName("fail_amount") + private Long failAmount; + + /** 转账失败笔数 说明:转账失败的笔数 */ + @SerializedName("fail_num") + private Integer failNum; + + /** + * 批次更新时间 说明:遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE, + * yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC + * 8小时,即北京时间)。 例如:2015-05-20T13:29:35+08:00表示北京时间2015年05月20日13点29分35秒。 + */ + @SerializedName("update_time") + private String updateTime; + + public String getMchid() { + return mchid; + } + + public void setMchid(String mchid) { + this.mchid = mchid; + } + + public String getOutBatchNo() { + return outBatchNo; + } + + public void setOutBatchNo(String outBatchNo) { + this.outBatchNo = outBatchNo; + } + + public String getBatchId() { + return batchId; + } + + public void setBatchId(String batchId) { + this.batchId = batchId; + } + + public String getBatchStatus() { + return batchStatus; + } + + public void setBatchStatus(String batchStatus) { + this.batchStatus = batchStatus; + } + + public CloseReasonType getCloseReason() { + return closeReason; + } + + public void setCloseReason(CloseReasonType closeReason) { + this.closeReason = closeReason; + } + + public Long getTotalAmount() { + return totalAmount; + } + + public void setTotalAmount(Long totalAmount) { + this.totalAmount = totalAmount; + } + + public Integer getTotalNum() { + return totalNum; + } + + public void setTotalNum(Integer totalNum) { + this.totalNum = totalNum; + } + + public Long getSuccessAmount() { + return successAmount; + } + + public void setSuccessAmount(Long successAmount) { + this.successAmount = successAmount; + } + + public Integer getSuccessNum() { + return successNum; + } + + public void setSuccessNum(Integer successNum) { + this.successNum = successNum; + } + + public Long getFailAmount() { + return failAmount; + } + + public void setFailAmount(Long failAmount) { + this.failAmount = failAmount; + } + + public Integer getFailNum() { + return failNum; + } + + public void setFailNum(Integer failNum) { + this.failNum = failNum; + } + + public String getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(String updateTime) { + this.updateTime = updateTime; + } + + @Override + public String toString() { + return GsonUtil.getGson().toJson(this); + } +}