diff --git a/README.md b/README.md index 9b7a7b6..a2f228a 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ -# 移动支付 Spring Boot 组件 多租户版 +# 移动支付 Spring Boot 组件 为了满足业务中出现app支付、公众号支付、小程序支付等多appid并存的场景,对原有的进行了增强开发出了多租户版本。 ## 支持类型 -- [x] **微信支付V3** 全量支持。 +- [x] **微信支付V3** 全量支持,并支持多租户。 - [x] **支付宝** 提供所有实现,具体以签约项目为准。 ## 进度 - 微信支付营销-代金券 `WechatMarketingFavorApi` 100% -- 微信支付 支付功能 `WechatPayApi` app预支付 +- 微信支付 支付功能 `WechatPayApi` 100% ## 采用技术 - Spring diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/WechatPayConfiguration.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/WechatPayConfiguration.java index d6c68b4..2a7eb43 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/WechatPayConfiguration.java +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/WechatPayConfiguration.java @@ -73,15 +73,4 @@ public class WechatPayConfiguration { public WechatApiProvider wechatApiProvider(WechatPayClient wechatPayClient){ return new WechatApiProvider(wechatPayClient); } - - /** - * 微信支付回调工具. - * - * @param signatureProvider the signature provider - * @return the wechat pay callback - */ - @Bean - public WechatPayCallback wechatPayCallback(SignatureProvider signatureProvider) { - return new WechatPayCallback(signatureProvider); - } } diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/enumeration/TradeState.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/enumeration/TradeState.java new file mode 100644 index 0000000..fbe97e2 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/enumeration/TradeState.java @@ -0,0 +1,38 @@ +package cn.felord.payment.wechat.enumeration; + +/** + * 微信侧返回交易状态 + * + * @author Dax + * @since 11:37 + */ +public enum TradeState { + /** + * 支付成功 + */ + SUCCESS, + /** + * 转入退款 + */ + REFUND, + /** + * 未支付 + */ + NOTPAY, + /** + * 已关闭 + */ + CLOSED, + /** + * 已撤销(付款码支付) + */ + REVOKED, + /** + * 用户支付中(付款码支付) + */ + USERPAYING, + /** + * 支付失败(其他原因,如银行返回失败) + */ + PAYERROR, +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/enumeration/TradeType.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/enumeration/TradeType.java new file mode 100644 index 0000000..d45cb80 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/enumeration/TradeType.java @@ -0,0 +1,34 @@ +package cn.felord.payment.wechat.enumeration; + +/** + * 微信侧返回交易类型 + * + * @author Dax + * @since 11:34 + */ +public enum TradeType { + /** + * 公众号支付 + */ + JSAPI, + /** + * 扫码支付 + */ + NATIVE, + /** + * APP支付 + */ + APP, + /** + * 付款码支付 + */ + MICROPAY, + /** + * H5支付 + */ + MWEB, + /** + * 刷脸支付 + */ + FACEPAY, +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/enumeration/WechatPayV3Type.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/enumeration/WechatPayV3Type.java index dedb735..449b3ee 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/enumeration/WechatPayV3Type.java +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/enumeration/WechatPayV3Type.java @@ -38,6 +38,10 @@ public enum WechatPayV3Type { * H5支付. */ MWEB(HttpMethod.POST, "%s/v3/pay/transactions/h5"), + /** + * 关闭订单. + */ + CLOSE(HttpMethod.POST, "%s/v3/pay/transactions/out-trade-no/{out_trade_no}/close"), /** * 微信支付订单号查询. */ diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/AbstractApi.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/AbstractApi.java index 2668c81..468e817 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/AbstractApi.java +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/AbstractApi.java @@ -1,17 +1,21 @@ package cn.felord.payment.wechat.v3; import cn.felord.payment.PayException; +import cn.felord.payment.wechat.WechatPayProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategy; import org.springframework.http.RequestEntity; +import org.springframework.util.Assert; import java.net.URI; /** + * The type Abstract api. + * * @author Dax - * @since 18:23 + * @since 18 :23 */ public abstract class AbstractApi { private final ObjectMapper mapper; @@ -19,43 +23,94 @@ public abstract class AbstractApi { private final String tenantId; - - - public AbstractApi(WechatPayClient wechatPayClient,String tenantId) { + /** + * Instantiates a new Abstract api. + * + * @param wechatPayClient the wechat pay client + * @param tenantId the tenant id + */ + public AbstractApi(WechatPayClient wechatPayClient, String tenantId) { this.mapper = new ObjectMapper(); mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); this.wechatPayClient = wechatPayClient; - + Assert.hasText(tenantId, "tenantId is required"); if (!container().getTenantIds().contains(tenantId)) { - throw new PayException("tenantId is not in wechatMetaContainer "); + throw new PayException("tenantId is not in wechatMetaContainer"); } this.tenantId = tenantId; } + /** + * Gets mapper. + * + * @return the mapper + */ public ObjectMapper getMapper() { return mapper; } + /** + * Client wechat pay client. + * + * @return the wechat pay client + */ public WechatPayClient client() { return wechatPayClient; } + /** + * Tenant id string. + * + * @return the string + */ public String tenantId() { return tenantId; } + /** + * Container wechat meta container. + * + * @return the wechat meta container + */ public WechatMetaContainer container() { return wechatPayClient.signatureProvider().wechatMetaContainer(); } - protected RequestEntity post(URI uri, Object params,String tenantId) { + /** + * Wechat meta bean wechat meta bean. + * + * @return the wechat meta bean + */ + public WechatMetaBean wechatMetaBean() { + return container().getWechatMeta(tenantId); + } + + /** + * Post request entity. + * + * @param uri the uri + * @param params the params + * @return the request entity + */ + protected RequestEntity Post(URI uri, Object params) { try { - return RequestEntity.post(uri).header("Pay-TenantId",tenantId) + return RequestEntity.post(uri).header("Pay-TenantId", tenantId) .body(mapper.writeValueAsString(params)); } catch (JsonProcessingException e) { throw new PayException("wechat app pay json failed"); } } + + /** + * Get request entity. + * + * @param uri the uri + * @return the request entity + */ + protected RequestEntity Get(URI uri) { + return RequestEntity.get(uri).header("Pay-TenantId", tenantId) + .build(); + } } diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatApiProvider.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatApiProvider.java index 02a0256..4b256c3 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatApiProvider.java +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatApiProvider.java @@ -1,22 +1,51 @@ package cn.felord.payment.wechat.v3; /** + * The type Wechat api provider. + * * @author Dax - * @since 17:32 + * @since 17 :32 */ public class WechatApiProvider { private final WechatPayClient wechatPayClient; + /** + * Instantiates a new Wechat api provider. + * + * @param wechatPayClient the wechat pay client + */ public WechatApiProvider(WechatPayClient wechatPayClient) { this.wechatPayClient = wechatPayClient; } + /** + * 代金券. + * + * @param tenantId the tenant id + * @return the wechat marketing favor api + */ public WechatMarketingFavorApi favorApi(String tenantId){ return new WechatMarketingFavorApi(this.wechatPayClient,tenantId); } + /** + * 支付. + * + * @param tenantId the tenant id + * @return the wechat pay api + */ public WechatPayApi payApi(String tenantId){ return new WechatPayApi(wechatPayClient,tenantId); } + /** + * 回调. + * + * @param tenantId the tenant id + * @return the wechat pay callback + */ + public WechatPayCallback callback(String tenantId){ + return new WechatPayCallback(wechatPayClient.signatureProvider(),tenantId); + } + } diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatMarketingFavorApi.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatMarketingFavorApi.java index b4a4bf6..427efa2 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatMarketingFavorApi.java +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatMarketingFavorApi.java @@ -1,6 +1,5 @@ package cn.felord.payment.wechat.v3; -import cn.felord.payment.PayException; import cn.felord.payment.wechat.WechatPayProperties; import cn.felord.payment.wechat.enumeration.StockStatus; import cn.felord.payment.wechat.enumeration.WeChatServer; @@ -59,14 +58,14 @@ public class WechatMarketingFavorApi extends AbstractApi { } private RequestEntity createStocksFunction(WechatPayV3Type type, StocksCreateParams params) { - WechatPayProperties.V3 v3 = this.container().getWechatMeta(tenantId()).getV3(); + WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3(); String mchId = v3.getMchId(); URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA)) .build() .toUri(); params.setBelongMerchant(mchId); - return post(uri, params, tenantId()); + return Post(uri, params); } /** @@ -102,7 +101,7 @@ public class WechatMarketingFavorApi extends AbstractApi { private RequestEntity sendStocksFunction(WechatPayV3Type type, StocksSendParams params) { - WechatPayProperties.V3 v3 = this.container().getWechatMeta(tenantId()).getV3(); + WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3(); params.setAppid(v3.getApp().getAppId()); params.setStockCreatorMchid(v3.getMchId()); @@ -111,7 +110,7 @@ public class WechatMarketingFavorApi extends AbstractApi { .expand(params.getOpenid()) .toUri(); params.setOpenid(null); - return post(uri, params, tenantId()); + return Post(uri, params); } /** @@ -145,7 +144,7 @@ public class WechatMarketingFavorApi extends AbstractApi { } private RequestEntity startAndRestartAndPauseStockFunction(WechatPayV3Type type, String stockId) { - WechatPayProperties.V3 v3 = this.container().getWechatMeta(tenantId()).getV3(); + WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3(); String mchId = v3.getMchId(); Map body = new HashMap<>(); body.put("stock_creator_mchid", mchId); @@ -154,7 +153,7 @@ public class WechatMarketingFavorApi extends AbstractApi { .build() .expand(stockId) .toUri(); - return post(uri, body, tenantId()); + return Post(uri, body); } /** @@ -179,7 +178,7 @@ public class WechatMarketingFavorApi extends AbstractApi { MultiValueMap queryParams = new LinkedMultiValueMap<>(); queryParams.add("offset", String.valueOf(params.getOffset())); queryParams.add("limit", String.valueOf(params.getLimit())); - WechatPayProperties.V3 v3 = this.container().getWechatMeta(tenantId()).getV3(); + WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3(); queryParams.add("stock_creator_mchid", v3.getMchId()); LocalDateTime createStartTime = params.getCreateStartTime(); @@ -211,7 +210,7 @@ public class WechatMarketingFavorApi extends AbstractApi { URI uri = uriComponents .toUri(); - return RequestEntity.get(uri).header("Pay-TenantId", tenantId()).build(); + return Get(uri); } /** @@ -231,8 +230,7 @@ public class WechatMarketingFavorApi extends AbstractApi { private RequestEntity stockDetailFunction(WechatPayV3Type type, String stockId) { - WechatPayProperties.V3 v3 = this.container().getWechatMeta(tenantId()).getV3(); - + WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3(); MultiValueMap queryParams = new LinkedMultiValueMap<>(); queryParams.add("stock_creator_mchid", v3.getMchId()); @@ -242,7 +240,7 @@ public class WechatMarketingFavorApi extends AbstractApi { .build() .expand(stockId) .toUri(); - return RequestEntity.get(uri).header("Pay-TenantId", tenantId()).build(); + return Get(uri); } @@ -264,13 +262,11 @@ public class WechatMarketingFavorApi extends AbstractApi { private RequestEntity couponDetailFunction(WechatPayV3Type type, CouponDetailsQueryParams params) { - WechatPayProperties.V3 v3 = this.container().getWechatMeta(tenantId()).getV3(); - + WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3(); MultiValueMap queryParams = new LinkedMultiValueMap<>(); queryParams.add("appid", v3.getApp().getAppId()); - MultiValueMap pathParams = new LinkedMultiValueMap<>(); pathParams.add("openid", params.getOpenId()); pathParams.add("coupon_id", params.getCouponId()); @@ -279,7 +275,7 @@ public class WechatMarketingFavorApi extends AbstractApi { .build() .expand(pathParams) .toUri(); - return RequestEntity.get(uri).header("Pay-TenantId", tenantId()).build(); + return Get(uri); } @@ -332,7 +328,7 @@ public class WechatMarketingFavorApi extends AbstractApi { private RequestEntity queryUserCouponsFunction(WechatPayV3Type type, UserCouponsQueryParams params) { - WechatPayProperties.V3 v3 = this.container().getWechatMeta(tenantId()).getV3(); + WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3(); MultiValueMap queryParams = new LinkedMultiValueMap<>(); queryParams.add("appid", v3.getApp().getAppId()); @@ -363,7 +359,7 @@ public class WechatMarketingFavorApi extends AbstractApi { .build() .expand(params.getOpenId()) .toUri(); - return RequestEntity.get(uri).header("Pay-TenantId", tenantId()).build(); + return Get(uri); } @@ -406,7 +402,7 @@ public class WechatMarketingFavorApi extends AbstractApi { .build() .expand(stockId) .toUri(); - return RequestEntity.get(uri).header("Pay-TenantId", tenantId()).build(); + return Get(uri); } /** @@ -467,7 +463,7 @@ public class WechatMarketingFavorApi extends AbstractApi { } private RequestEntity setMarketingFavorCallbackFunction(WechatPayV3Type type, String notifyUrl) { - WechatPayProperties.V3 v3 = this.container().getWechatMeta(tenantId()).getV3(); + WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3(); Map body = new HashMap<>(3); body.put("mchid", v3.getMchId()); @@ -476,7 +472,7 @@ public class WechatMarketingFavorApi extends AbstractApi { URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA)) .build() .toUri(); - return post(uri, body, tenantId()); + return Post(uri, body); } public String billDownload(String link) { @@ -490,7 +486,7 @@ public class WechatMarketingFavorApi extends AbstractApi { URI uri = UriComponentsBuilder.fromHttpUrl(link) .build() .toUri(); - return RequestEntity.get(uri).header("Pay-TenantId", tenantId()).build(); + return Get(uri); } } diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatPayApi.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatPayApi.java index 3ea9054..6207a3c 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatPayApi.java +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatPayApi.java @@ -92,13 +92,13 @@ public class WechatPayApi extends AbstractApi { } private RequestEntity payFunction(WechatPayV3Type type, PayParams payParams) { - WechatPayProperties.V3 v3 = this.container().getWechatMeta(tenantId()).getV3(); + WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3(); payParams.setAppid(v3.getAppId()); payParams.setMchid(v3.getMchId()); URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA)) .build() .toUri(); - return post(uri, payParams,tenantId()); + return Post(uri, payParams); } /** @@ -132,17 +132,46 @@ public class WechatPayApi extends AbstractApi { } private RequestEntity queryTransactionFunction(WechatPayV3Type type, TransactionQueryParams params) { - WechatPayProperties.V3 v3 = this.container().getWechatMeta(tenantId()).getV3(); + WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3(); MultiValueMap queryParams = new LinkedMultiValueMap<>(); - queryParams.add("mchid", params.getMchId()); + queryParams.add("mchid", v3.getMchId()); URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA)) .queryParams(queryParams) .build() .expand(params.getTransactionIdOrOutTradeNo()) .toUri(); - return RequestEntity.get(uri).header("Pay-TenantId",tenantId()).build(); + return Get(uri); + } + + /** + * 关单API + * + * @param outTradeNo the out trade no + * @return the wechat response entity + */ + public WechatResponseEntity closeByOutTradeNo(String outTradeNo) { + WechatResponseEntity wechatResponseEntity = new WechatResponseEntity<>(); + this.client().withType(WechatPayV3Type.CLOSE, outTradeNo) + .function(this::closeByOutTradeNoFunction) + .consumer(wechatResponseEntity::convert) + .request(); + return wechatResponseEntity; + } + + private RequestEntity closeByOutTradeNoFunction(WechatPayV3Type type, String outTradeNo) { + WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3(); + + MultiValueMap queryParams = new LinkedMultiValueMap<>(); + queryParams.add("mchid", v3.getMchId()); + + URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA)) + .queryParams(queryParams) + .build() + .expand(outTradeNo) + .toUri(); + return Post(uri,queryParams); } } diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatPayCallback.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatPayCallback.java index 804de61..2369a94 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatPayCallback.java +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatPayCallback.java @@ -4,6 +4,7 @@ import cn.felord.payment.wechat.v3.model.CouponConsumeData; import cn.felord.payment.wechat.v3.model.ResponseSignVerifyParams; import cn.felord.payment.PayException; import cn.felord.payment.wechat.v3.model.CallbackParams; +import cn.felord.payment.wechat.v3.model.TransactionConsumeData; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategy; @@ -11,12 +12,14 @@ import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springframework.util.Assert; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.function.Consumer; /** - * The type Wechat pay callback. + * 微信支付回调工具. * * @author Dax * @since 10 :21 @@ -25,6 +28,7 @@ import java.util.function.Consumer; public class WechatPayCallback { private static final ObjectMapper MAPPER = new ObjectMapper(); private final SignatureProvider signatureProvider; + private final String tenantId; static { MAPPER.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); @@ -35,40 +39,91 @@ public class WechatPayCallback { * Instantiates a new Wechat pay callback. * * @param signatureProvider the signature provider + * @param tenantId the tenant id */ - public WechatPayCallback(SignatureProvider signatureProvider) { + public WechatPayCallback(SignatureProvider signatureProvider, String tenantId) { this.signatureProvider = signatureProvider; + Assert.hasText(tenantId, "tenantId is required"); + this.tenantId = tenantId; } /** - * 微信支付代金券核销回调工具. + * 微信支付代金券核销回调. * - * @param tenantId the tenant id * @param params the params * @param couponConsumeDataConsumer the coupon consume data consumer * @return the map */ @SneakyThrows - public Map wechatPayCouponCallback(String tenantId, ResponseSignVerifyParams params, Consumer couponConsumeDataConsumer) { + public Map couponCallback(ResponseSignVerifyParams params, Consumer couponConsumeDataConsumer) { + String data = callback(params, EventType.COUPON); + CouponConsumeData couponConsumeData = MAPPER.readValue(data, CouponConsumeData.class); + couponConsumeDataConsumer.accept(couponConsumeData); + Map responseBody = new HashMap<>(); + responseBody.put("code", 200); + responseBody.put("message", "SUCCESS"); + return responseBody; + } + + /** + * 微信支付成功回调. + *

+ * 无需开发者判断,只有扣款成功微信才会回调此接口 + * + * @param params the params + * @param couponConsumeDataConsumer the coupon consume data consumer + * @return the map + */ + @SneakyThrows + public Map transactionCallback(ResponseSignVerifyParams params, Consumer couponConsumeDataConsumer) { + String data = callback(params, EventType.TRANSACTION); + TransactionConsumeData transactionConsumeData = MAPPER.readValue(data, TransactionConsumeData.class); + couponConsumeDataConsumer.accept(transactionConsumeData); + return Collections.singletonMap("code", "SUCCESS"); + + } + + + @SneakyThrows + private String callback(ResponseSignVerifyParams params, EventType eventType) { if (signatureProvider.responseSignVerify(params)) { CallbackParams callbackParams = MAPPER.readValue(params.getBody(), CallbackParams.class); + if (!Objects.equals(callbackParams.getEventType(), eventType.event)) { + log.error("wechat pay event type is not matched, callbackParams {}", callbackParams); + throw new PayException(" wechat pay event type is not matched"); + } CallbackParams.Resource resource = callbackParams.getResource(); String associatedData = resource.getAssociatedData(); String nonce = resource.getNonce(); String ciphertext = resource.getCiphertext(); - String data = signatureProvider.decryptResponseBody(tenantId,associatedData, nonce, ciphertext); + String data = signatureProvider.decryptResponseBody(tenantId, associatedData, nonce, ciphertext); Assert.hasText(data, "decryptData is required"); - CouponConsumeData couponConsumeData = MAPPER.readValue(data, CouponConsumeData.class); - couponConsumeDataConsumer.accept(couponConsumeData); - Map responseBody = new HashMap<>(); - responseBody.put("code", 200); - responseBody.put("message", "核销成功"); - return responseBody; + return data; + } + throw new PayException("invalid wechat pay callback"); + } + + /** + * 事件类型用于处理回调. + */ + enum EventType { + /** + * 优惠券核销事件. + */ + COUPON("COUPON.USE"), + /** + * 支付成功事件. + */ + TRANSACTION("TRANSACTION.SUCCESS"); + + private final String event; + + EventType(String event) { + this.event = event; } - throw new PayException("invalid wechat pay coupon callback"); } diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/model/PromotionDetail.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/model/PromotionDetail.java new file mode 100644 index 0000000..2cf22a1 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/model/PromotionDetail.java @@ -0,0 +1,32 @@ + +package cn.felord.payment.wechat.v3.model; + +import lombok.Data; + +import java.util.List; + +public class PromotionDetail { + + private Long amount; + private String couponId; + private String currency; + private List goodsDetail; + private Long merchantContribute; + private String name; + private Long otherContribute; + private String scope; + private String stockId; + private String type; + private Long wechatpayContribute; + + @Data + public static class GoodsDetail { + + private String goodsId; + private Long quantity; + private Long unitPrice; + private Long discountAmount; + private String goodsRemark; + + } +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/model/TransactionConsumeData.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/model/TransactionConsumeData.java new file mode 100644 index 0000000..ac5b424 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/model/TransactionConsumeData.java @@ -0,0 +1,46 @@ + +package cn.felord.payment.wechat.v3.model; + +import lombok.Data; + +import java.util.List; + +@Data +public class TransactionConsumeData { + + private Amount amount; + private String appid; + private String attach; + private String bankType; + private String mchid; + private String outTradeNo; + private Payer payer; + private List promotionDetail; + private SceneInfo sceneInfo; + private String successTime; + private String tradeState; + private String tradeStateDesc; + private String tradeType; + private String transactionId; + + + @Data + public static class Payer { + private String openid; + } + + @Data + public static class SceneInfo { + private String deviceId; + } + + @Data + public static class Amount { + private int total; + private int payerTotal; + private String currency; + private String payerCurrency; + } + + +}