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 0583ee4..e0b19f0 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 @@ -92,6 +92,15 @@ public enum WechatPayV3Type { return this.method; } + /** + * Pattern string. + * + * @return the string + */ + public String pattern() { + return this.pattern; + } + /** * 默认支付URI. diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatMarketingApi.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatMarketingApi.java index 5024dc4..be12acd 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatMarketingApi.java +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatMarketingApi.java @@ -8,10 +8,15 @@ import com.enongm.dianji.payment.wechat.v3.model.StocksCreateParams; import com.enongm.dianji.payment.wechat.v3.model.StocksQueryParams; import com.enongm.dianji.payment.wechat.v3.model.StocksSendParams; import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.SneakyThrows; +import org.bouncycastle.jcajce.provider.digest.SHA256; +import org.bouncycastle.util.encoders.Hex; +import org.springframework.http.MediaType; import org.springframework.http.RequestEntity; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; +import org.springframework.web.multipart.MultipartFile; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; @@ -20,14 +25,23 @@ import java.time.LocalDateTime; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; /** + * The type Wechat marketing api. + * * @author Dax - * @since 18:22 + * @since 18 :22 */ public class WechatMarketingApi extends AbstractApi { + /** + * Instantiates a new Wechat marketing api. + * + * @param wechatPayClient the wechat pay client + * @param wechatMetaBean the wechat meta bean + */ public WechatMarketingApi(WechatPayClient wechatPayClient, WechatMetaBean wechatMetaBean) { super(wechatPayClient, wechatMetaBean); } @@ -198,7 +212,6 @@ public class WechatMarketingApi extends AbstractApi { return RequestEntity.get(uri).build(); } - /** * 发放代金券API. * @@ -226,6 +239,40 @@ public class WechatMarketingApi extends AbstractApi { return postRequestEntity(uri, params); } + /** + * 营销图片上传API. + * + * @param file the file + * @return the wechat response entity + */ + public WechatResponseEntity marketingImageUpload(MultipartFile file) { + WechatResponseEntity wechatResponseEntity = new WechatResponseEntity<>(); + this.getWechatPayClient().withType(WechatPayV3Type.MARKETING_IMAGE_UPLOAD, file) + .function(this::marketingImageUploadFunction) + .consumer(wechatResponseEntity::convert) + .request(); + return wechatResponseEntity; + } + + + @SneakyThrows + private RequestEntity marketingImageUploadFunction(WechatPayV3Type type, MultipartFile file) { + + Map meta = new LinkedHashMap<>(2); + meta.put("filename", file.getOriginalFilename()); + + byte[] digest = SHA256.Digest.getInstance("SHA-256").digest(file.getBytes()); + meta.put("sha256", Hex.toHexString(digest)); + String httpUrl = type.uri(WeChatServer.CHINA); + URI uri = UriComponentsBuilder.fromHttpUrl(httpUrl).build().toUri(); + MultiValueMap body = new LinkedMultiValueMap<>(); + body.add("meta", meta); + body.add("file", file.getResource()); + // 签名 + String metaStr = this.getMapper().writeValueAsString(meta); + return RequestEntity.post(uri).header("Content-Type", MediaType.MULTIPART_FORM_DATA_VALUE) + .header("Meta-Info",metaStr).body(body); + } /** * 代金券核销回调通知. 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 945c383..d1a8c72 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 @@ -142,15 +142,21 @@ public class WechatPayClient { UriComponents uri = UriComponentsBuilder.fromUri(requestEntity.getUrl()).build(); String canonicalUrl = uri.getPath(); String encodedQuery = uri.getQuery(); - + Assert.notNull(canonicalUrl,"canonicalUrl is required"); if (encodedQuery != null) { canonicalUrl += "?" + encodedQuery; } + + // 签名 HttpMethod httpMethod = requestEntity.getMethod(); Assert.notNull(httpMethod, "httpMethod is required"); - String body = requestEntity.hasBody() ? Objects.requireNonNull(requestEntity.getBody()).toString() : ""; + T entityBody = requestEntity.getBody(); + String body = requestEntity.hasBody() ? Objects.requireNonNull(entityBody).toString() : ""; + if (WechatPayV3Type.MARKETING_IMAGE_UPLOAD.pattern().contains(canonicalUrl)) { + body = Objects.requireNonNull(requestEntity.getHeaders().get("Meta-Info")).get(0); + } String authorization = signatureProvider.requestSign(httpMethod.name(), canonicalUrl, body); HttpHeaders httpHeaders = new HttpHeaders();