diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/WechatPayConfiguration.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/WechatPayConfiguration.java index 32a70ad..c49b0b3 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/WechatPayConfiguration.java +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/WechatPayConfiguration.java @@ -60,14 +60,26 @@ public class WechatPayConfiguration { * Wechat pay v3 api. * * @param wechatPayClient the wechat pay v 3 client - * @param wechatMetaBean the wechat meta bean + * @param wechatMetaBean the wechat meta bean * @return the wechat pay v 3 api */ @Bean public WechatPayApi wechatPayApi(WechatPayClient wechatPayClient, WechatMetaBean wechatMetaBean) { - return new WechatPayApi(wechatPayClient,wechatMetaBean); + return new WechatPayApi(wechatPayClient, wechatMetaBean); } + /** + * Wechat pay callback. + * + * @param signatureProvider the signature provider + * @return the wechat pay callback + */ + @Bean + public WechatPayCallback wechatPayCallback(SignatureProvider signatureProvider) { + return new WechatPayCallback(signatureProvider); + } + + /** * 公众号授权工具用于获取用户openId,需要配置{@link WechatPayProperties.Mp}. * @@ -76,7 +88,7 @@ public class WechatPayConfiguration { */ @Bean @ConditionalOnProperty(prefix = "wechat.pay", name = "v3.mp.app-id") - public OAuth2AuthorizationRequestRedirectProvider oAuth2Provider(WechatPayProperties wechatPayProperties){ + public OAuth2AuthorizationRequestRedirectProvider oAuth2Provider(WechatPayProperties wechatPayProperties) { WechatPayProperties.Mp mp = wechatPayProperties.getV3().getMp(); return new OAuth2AuthorizationRequestRedirectProvider(mp.getAppId(), mp.getAppSecret()); } diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/enumeration/CouponStatus.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/enumeration/CouponStatus.java new file mode 100644 index 0000000..a6a049f --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/enumeration/CouponStatus.java @@ -0,0 +1,22 @@ +package com.enongm.dianji.payment.wechat.enumeration; + +/** + * The enum Coupon status. + * + * @author Dax + * @since 10 :57 + */ +public enum CouponStatus { + /** + * 可用. + */ + SENDED, + /** + * 已实扣. + */ + USED, + /** + * 已过期. + */ + EXPIRED +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/enumeration/WechatPayV3Type.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/enumeration/WechatPayV3Type.java index 491f54a..0583ee4 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/enumeration/WechatPayV3Type.java +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/enumeration/WechatPayV3Type.java @@ -43,6 +43,10 @@ public enum WechatPayV3Type { * 激活代金券批次API. */ MARKETING_FAVOR_STOCKS_START(HttpMethod.POST,"%s/v3/marketing/favor/stocks/{stock_id}/start"), + /** + * 重启代金券 + */ + MARKETING_FAVOR_STOCKS_RESTART(HttpMethod.POST,"%s/v3/marketing/favor/stocks/{stock_id}/restart"), /** * 发放代金券API & 根据商户号查用户的券. */ @@ -62,7 +66,11 @@ public enum WechatPayV3Type { /** * 营销图片上传API. */ - MARKETING_IMAGE_UPLOAD(HttpMethod.POST, "%s/v3/marketing/favor/media/image-upload"); + MARKETING_IMAGE_UPLOAD(HttpMethod.POST, "%s/v3/marketing/favor/media/image-upload"), + /** + * 设置核销回调通知API. + */ + MARKETING_FAVOR_CALLBACKS(HttpMethod.POST, "%s/v3/marketing/favor/callbacks"); diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/oauth2/OAuth2AuthorizationRequestRedirectProvider.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/oauth2/OAuth2AuthorizationRequestRedirectProvider.java index c2fcdd3..ee015f6 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/oauth2/OAuth2AuthorizationRequestRedirectProvider.java +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/oauth2/OAuth2AuthorizationRequestRedirectProvider.java @@ -4,6 +4,7 @@ package com.enongm.dianji.payment.wechat.oauth2; import com.enongm.dianji.payment.PayException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.SneakyThrows; import org.springframework.http.RequestEntity; import org.springframework.http.ResponseEntity; import org.springframework.util.Assert; @@ -11,10 +12,11 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestOperations; import org.springframework.web.client.RestTemplate; -import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; import java.net.URI; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.Objects; /** @@ -48,14 +50,17 @@ public class OAuth2AuthorizationRequestRedirectProvider { * @param redirectUri the redirect uri * @return uri components */ - public UriComponents redirect(String phoneNumber, String redirectUri) { + @SneakyThrows + public String redirect(String phoneNumber, String redirectUri) { + Assert.hasText(redirectUri, "redirectUri is required"); + String encode = URLEncoder.encode(redirectUri, StandardCharsets.UTF_8.name()); MultiValueMap queryParams = new LinkedMultiValueMap<>(); queryParams.add("appid", appId); - queryParams.add("redirect_uri", redirectUri); + queryParams.add("redirect_uri", encode); queryParams.add("response_type", "code"); queryParams.add("scope", "snsapi_base"); queryParams.add("state", phoneNumber); - return UriComponentsBuilder.fromHttpUrl(AUTHORIZATION_URI).queryParams(queryParams).build(); + return UriComponentsBuilder.fromHttpUrl(AUTHORIZATION_URI).queryParams(queryParams).build().toUriString() + "#wechat_redirect"; } diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/SignatureProvider.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/SignatureProvider.java index 6aa4403..5fd9b8c 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/SignatureProvider.java +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/SignatureProvider.java @@ -2,8 +2,9 @@ package com.enongm.dianji.payment.wechat.v3; import com.enongm.dianji.payment.PayException; -import com.enongm.dianji.payment.wechat.enumeration.WechatPayV3Type; import com.enongm.dianji.payment.wechat.enumeration.WeChatServer; +import com.enongm.dianji.payment.wechat.enumeration.WechatPayV3Type; +import com.enongm.dianji.payment.wechat.v3.model.ResponseSignVerifyParams; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -107,27 +108,24 @@ public class SignatureProvider { /** * 我方对响应验签,和应答签名做比较,使用微信平台证书. * - * @param wechatpaySerial response.headers['Wechatpay-Serial'] 当前使用的微信平台证书序列号 - * @param wechatpaySignature response.headers['Wechatpay-Signature'] 微信平台签名 - * @param wechatpayTimestamp response.headers['Wechatpay-Timestamp'] 微信服务器的时间戳 - * @param wechatpayNonce response.headers['Wechatpay-Nonce'] 微信服务器提供的随机串 - * @param body response.body 微信服务器的响应体 + * @param params the params * @return the boolean */ @SneakyThrows - public boolean responseSignVerify(String wechatpaySerial, String wechatpaySignature, String wechatpayTimestamp, String wechatpayNonce, String body) { + public boolean responseSignVerify(ResponseSignVerifyParams params) { + String wechatpaySerial = params.getWechatpaySerial(); if (CERTIFICATE_MAP.isEmpty() || !CERTIFICATE_MAP.containsKey(wechatpaySerial)) { refreshCertificate(); } Certificate certificate = CERTIFICATE_MAP.get(wechatpaySerial); - final String signatureStr = createSign(wechatpayTimestamp, wechatpayNonce, body); + final String signatureStr = createSign(params.getWechatpayTimestamp(), params.getWechatpayNonce(), params.getBody()); Signature signer = Signature.getInstance("SHA256withRSA"); signer.initVerify(certificate); signer.update(signatureStr.getBytes(StandardCharsets.UTF_8)); - return signer.verify(Base64Utils.decodeFromString(wechatpaySignature)); + return signer.verify(Base64Utils.decodeFromString(params.getWechatpaySignature())); } @@ -207,7 +205,6 @@ public class SignatureProvider { cipher.init(Cipher.DECRYPT_MODE, key, spec); cipher.updateAAD(associatedData.getBytes(StandardCharsets.UTF_8)); - byte[] bytes; try { bytes = cipher.doFinal(Base64Utils.decodeFromString(ciphertext)); @@ -221,6 +218,11 @@ public class SignatureProvider { } } + /** + * Gets wechat meta bean. + * + * @return the wechat meta bean + */ public WechatMetaBean getWechatMetaBean() { return wechatMetaBean; } diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatPayApi.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatPayApi.java index 4a39c89..c4729e7 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatPayApi.java +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatPayApi.java @@ -79,13 +79,7 @@ public class WechatPayApi { String httpUrl = type.uri(WeChatServer.CHINA); URI uri = UriComponentsBuilder.fromHttpUrl(httpUrl).build().toUri(); params.setBelongMerchant(mchId); - try { - return RequestEntity.post(uri) - .body(MAPPER.writeValueAsString(params)); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - throw new PayException("wechat app pay json failed"); + return postRequestEntity(uri, params); } /** @@ -97,27 +91,35 @@ public class WechatPayApi { public WechatResponseEntity startStock(String stockId) { WechatResponseEntity wechatResponseEntity = new WechatResponseEntity<>(); wechatPayClient.withType(WechatPayV3Type.MARKETING_FAVOR_STOCKS_START, stockId) - .function(this::startStockFunction) + .function(this::startAndRestartStockFunction) .consumer(wechatResponseEntity::convert) .request(); return wechatResponseEntity; } - private RequestEntity startStockFunction(WechatPayV3Type type, String stockId) { + /** + * 重启代金券批次API. + * + * @param stockId the stock id + * @return the wechat response entity + */ + public WechatResponseEntity restartStock(String stockId) { + WechatResponseEntity wechatResponseEntity = new WechatResponseEntity<>(); + wechatPayClient.withType(WechatPayV3Type.MARKETING_FAVOR_STOCKS_RESTART, stockId) + .function(this::startAndRestartStockFunction) + .consumer(wechatResponseEntity::convert) + .request(); + return wechatResponseEntity; + } + + private RequestEntity startAndRestartStockFunction(WechatPayV3Type type, String stockId) { WechatPayProperties.V3 v3 = wechatMetaBean.getWechatPayProperties().getV3(); String mchId = v3.getMchId(); + Map body = new HashMap<>(); + body.put("stock_creator_mchid", mchId); String httpUrl = type.uri(WeChatServer.CHINA); URI uri = UriComponentsBuilder.fromHttpUrl(httpUrl).build().expand(stockId).toUri(); - - Map map = new HashMap<>(); - map.put("stock_creator_mchid", mchId); - try { - return RequestEntity.post(uri) - .body(MAPPER.writeValueAsString(map)); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - throw new PayException("wechat app pay json failed"); + return postRequestEntity(uri, body); } /** @@ -247,13 +249,34 @@ public class WechatPayApi { String httpUrl = type.uri(WeChatServer.CHINA); URI uri = UriComponentsBuilder.fromHttpUrl(httpUrl).build().expand(params.getOpenid()).toUri(); params.setOpenid(null); - try { - return RequestEntity.post(uri) - .body(MAPPER.writeValueAsString(params)); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - throw new PayException("wechat app pay json failed"); + return postRequestEntity(uri, params); + } + + + /** + * 代金券核销回调通知. + * + * @param notifyUrl the notify url + * @return the wechat response entity + */ + public WechatResponseEntity marketingFavorCallback(String notifyUrl) { + WechatResponseEntity wechatResponseEntity = new WechatResponseEntity<>(); + wechatPayClient.withType(WechatPayV3Type.MARKETING_FAVOR_CALLBACKS, notifyUrl) + .function(this::marketingFavorCallbackFunction) + .consumer(wechatResponseEntity::convert) + .request(); + return wechatResponseEntity; + } + + private RequestEntity marketingFavorCallbackFunction(WechatPayV3Type type, String notifyUrl) { + WechatPayProperties.V3 v3 = wechatMetaBean.getWechatPayProperties().getV3(); + Map body = new HashMap<>(3); + body.put("mchid", v3.getMchId()); + body.put("notify_url", notifyUrl); + body.put("switch", true); + String httpUrl = type.uri(WeChatServer.CHINA); + URI uri = UriComponentsBuilder.fromHttpUrl(httpUrl).build().toUri(); + return postRequestEntity(uri, body); } /** @@ -277,13 +300,19 @@ public class WechatPayApi { payParams.setMchid(v3.getMchId()); String httpUrl = type.uri(WeChatServer.CHINA); URI uri = UriComponentsBuilder.fromHttpUrl(httpUrl).build().toUri(); + return postRequestEntity(uri, payParams); + } + + + private static RequestEntity postRequestEntity(URI uri, Object params) { try { return RequestEntity.post(uri) - .body(MAPPER.writeValueAsString(payParams)); + .body(MAPPER.writeValueAsString(params)); } catch (JsonProcessingException e) { e.printStackTrace(); } throw new PayException("wechat app pay json failed"); } + } diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatPayCallback.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatPayCallback.java new file mode 100644 index 0000000..1f74dc6 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatPayCallback.java @@ -0,0 +1,49 @@ +package com.enongm.dianji.payment.wechat.v3; + +import com.enongm.dianji.payment.PayException; +import com.enongm.dianji.payment.wechat.v3.model.CallbackParams; +import com.enongm.dianji.payment.wechat.v3.model.CouponConsumeData; +import com.enongm.dianji.payment.wechat.v3.model.ResponseSignVerifyParams; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import lombok.SneakyThrows; +import org.springframework.util.Assert; + +/** + * @author Dax + * @since 10:21 + */ +public class WechatPayCallback { + private static final ObjectMapper MAPPER = new ObjectMapper(); + private final SignatureProvider signatureProvider; + + static { + MAPPER.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); + MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL); + } + + public WechatPayCallback(SignatureProvider signatureProvider) { + this.signatureProvider = signatureProvider; + } + + + @SneakyThrows + public CouponConsumeData wechatPayCouponCallback(ResponseSignVerifyParams params) { + + if (signatureProvider.responseSignVerify(params)) { + CallbackParams callbackParams = MAPPER.readValue(params.getBody(), CallbackParams.class); + + CallbackParams.Resource resource = callbackParams.getResource(); + String associatedData = resource.getAssociatedData(); + String nonce = resource.getNonce(); + String ciphertext = resource.getCiphertext(); + String data = signatureProvider.decryptResponseBody(associatedData, nonce, ciphertext); + Assert.hasText(data, "decryptData is required"); + return MAPPER.readValue(data, CouponConsumeData.class); + } + throw new PayException("invalid wechat pay coupon callback"); + } + + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatPayClient.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatPayClient.java index 104bc03..86c4b2e 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatPayClient.java +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatPayClient.java @@ -4,6 +4,7 @@ package com.enongm.dianji.payment.wechat.v3; import com.enongm.dianji.payment.PayException; import com.enongm.dianji.payment.wechat.WechatPayResponseErrorHandler; import com.enongm.dianji.payment.wechat.enumeration.WechatPayV3Type; +import com.enongm.dianji.payment.wechat.v3.model.ResponseSignVerifyParams; import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.SneakyThrows; import org.springframework.http.*; @@ -97,7 +98,7 @@ public class WechatPayClient { /** * Function executor. * - * @param requestEntityBiFunction the request entity bi function + * @param requestEntityBiFunction the request entity bifunction * @return the executor */ public Executor function(BiFunction> requestEntityBiFunction) { @@ -170,26 +171,28 @@ public class WechatPayClient { ResponseEntity responseEntity = restOperations.exchange(requestEntity, ObjectNode.class); HttpHeaders headers = responseEntity.getHeaders(); ObjectNode body = responseEntity.getBody(); - + if (!responseEntity.getStatusCode().is2xxSuccessful()) { + throw new PayException("wechat pay server error,result : " + body); + } if (Objects.isNull(body)) { throw new IllegalStateException("cant obtain response body"); } + + + ResponseSignVerifyParams params = new ResponseSignVerifyParams(); // 微信请求回调id // String RequestId = response.header("Request-ID"); // 微信平台证书序列号 用来取微信平台证书 - String wechatpaySerial = headers.getFirst("Wechatpay-Serial"); + params.setWechatpaySerial(headers.getFirst("Wechatpay-Serial")); //获取应答签名 - String wechatpaySignature = headers.getFirst("Wechatpay-Signature"); + params.setWechatpaySignature(headers.getFirst("Wechatpay-Signature")); //构造验签名串 - String wechatpayTimestamp = headers.getFirst("Wechatpay-Timestamp"); - String wechatpayNonce = headers.getFirst("Wechatpay-Nonce"); + params.setWechatpayTimestamp(headers.getFirst("Wechatpay-Timestamp")); + params.setWechatpayNonce(headers.getFirst("Wechatpay-Nonce")); + params.setBody(body.toString()); // 验证微信服务器签名 - if (signatureProvider.responseSignVerify(wechatpaySerial, - wechatpaySignature, - wechatpayTimestamp, - wechatpayNonce, - body.toString())) { + if (signatureProvider.responseSignVerify(params)) { Consumer> responseConsumer = requestEntity.getResponseBodyConsumer(); if (Objects.nonNull(responseConsumer)) { // 验证通过消费 diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatResponseEntity.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatResponseEntity.java index 687bc92..c06989f 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatResponseEntity.java +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatResponseEntity.java @@ -31,7 +31,10 @@ public class WechatResponseEntity { } } - public boolean successful() { - return this.httpStatus == HttpStatus.OK.value(); + public boolean is2xxSuccessful() { + if (log.isDebugEnabled()) { + log.debug("wechat httpStatus {}", this.httpStatus); + } + return HttpStatus.valueOf(this.httpStatus).is2xxSuccessful(); } } diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/CallbackParams.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/CallbackParams.java new file mode 100644 index 0000000..0fb18b9 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/CallbackParams.java @@ -0,0 +1,28 @@ +package com.enongm.dianji.payment.wechat.v3.model; + +import lombok.Data; + +/** + * @author Dax + * @since 10:13 + */ +@Data +public class CallbackParams { + private String id; + private String createTime; + private String eventType; + private String resourceType; + private String summary; + private Resource resource; + + + @Data + public static class Resource { + private String algorithm; + private String ciphertext; + private String associatedData; + private String nonce; + private String originalType; + } + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/ConsumeInformation.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/ConsumeInformation.java new file mode 100644 index 0000000..935f3ce --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/ConsumeInformation.java @@ -0,0 +1,22 @@ + +package com.enongm.dianji.payment.wechat.v3.model; + +import lombok.Data; + +import java.util.List; + +/** + * 已实扣代金券信息 + */ +@Data +public class ConsumeInformation { + + private String consumeMchid; + + private String consumeTime; + + private List goodsDetail; + + private String transactionId; + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/CouponConsumeData.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/CouponConsumeData.java new file mode 100644 index 0000000..0b92ee0 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/CouponConsumeData.java @@ -0,0 +1,31 @@ + +package com.enongm.dianji.payment.wechat.v3.model; + +import lombok.Data; + +/** + * 微信代金券核销通知参数 + */ +@Data +public class CouponConsumeData { + + + private String availableBeginTime; + private String availableEndTime; + private ConsumeInformation consumeInformation; + private String couponId; + private String couponName; + private String couponType; + private String createTime; + private String description; + private DiscountTo discountTo; + private boolean noCash; + private NormalCouponInformation normalCouponInformation; + private boolean singleitem; + private SingleitemDiscountOff singleitemDiscountOff; + private String status; + private String stockCreatorMchid; + private String stockId; + + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/DiscountTo.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/DiscountTo.java new file mode 100644 index 0000000..f48c7eb --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/DiscountTo.java @@ -0,0 +1,15 @@ + +package com.enongm.dianji.payment.wechat.v3.model; + +import lombok.Data; + +/** + * 减至优惠限定字段,仅减至优惠场景有返回 + */ +@Data +public class DiscountTo { + + private Long cutToPrice; + private Long maxPrice; + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/GoodsDetail.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/GoodsDetail.java new file mode 100644 index 0000000..15162a4 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/GoodsDetail.java @@ -0,0 +1,17 @@ + +package com.enongm.dianji.payment.wechat.v3.model; + +import lombok.Data; + +/** + * 商户下单接口传的单品信息 + */ +@Data +public class GoodsDetail { + + private Long discountAmount; + private String goodsId; + private Long price; + private Long quantity; + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/NormalCouponInformation.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/NormalCouponInformation.java new file mode 100644 index 0000000..10af9da --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/NormalCouponInformation.java @@ -0,0 +1,15 @@ + +package com.enongm.dianji.payment.wechat.v3.model; + +import lombok.Data; + +/** + * 普通满减券面额、门槛信息 + */ +@Data +public class NormalCouponInformation { + + private Long couponAmount; + private Long transactionMinimum; + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/ResponseSignVerifyParams.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/ResponseSignVerifyParams.java new file mode 100644 index 0000000..b828927 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/ResponseSignVerifyParams.java @@ -0,0 +1,34 @@ +package com.enongm.dianji.payment.wechat.v3.model; + +import lombok.Data; + +/** + * 微信的响应签名校验参数 + * + * @author Dax + * @see com.enongm.dianji.payment.wechat.v3.SignatureProvider#responseSignVerify(String, String, String, String, String) + * @since 16:32 + */ +@Data +public class ResponseSignVerifyParams { + /** + * response.headers['Wechatpay-Serial'] 当前使用的微信平台证书序列号 + */ + private String wechatpaySerial; + /** + * response.headers['Wechatpay-Signature'] 微信平台签名 + */ + private String wechatpaySignature; + /** + * response.headers['Wechatpay-Timestamp'] 微信服务器的时间戳 + */ + private String wechatpayTimestamp; + /** + * response.headers['Wechatpay-Nonce'] 微信服务器提供的随机串 + */ + private String wechatpayNonce; + /** + * response.body 微信服务器的响应体 + */ + private String body; +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/SingleitemDiscountOff.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/SingleitemDiscountOff.java new file mode 100644 index 0000000..001d37a --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/model/SingleitemDiscountOff.java @@ -0,0 +1,14 @@ + +package com.enongm.dianji.payment.wechat.v3.model; + +import lombok.Data; + +/** + * 单品优惠特定信息 + */ +@Data +public class SingleitemDiscountOff { + + private Long singlePriceMax; + +}