mirror of
https://github.com/dromara/payment-spring-boot.git
synced 2026-03-17 15:33:44 +08:00
对账单下载
This commit is contained in:
@@ -0,0 +1,66 @@
|
|||||||
|
package cn.felord.payment.wechat.v3;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import org.springframework.http.HttpInputMessage;
|
||||||
|
import org.springframework.http.HttpOutputMessage;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.converter.*;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.MimeType;
|
||||||
|
import org.springframework.util.StreamUtils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Dax
|
||||||
|
* @since 12:46
|
||||||
|
*/
|
||||||
|
public class DownloadHttpMessageConverter extends AbstractHttpMessageConverter<ObjectNode> {
|
||||||
|
|
||||||
|
public DownloadHttpMessageConverter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public DownloadHttpMessageConverter(MediaType supportedMediaType) {
|
||||||
|
super(supportedMediaType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean supports(Class<?> clazz) {
|
||||||
|
return clazz.isAssignableFrom(ObjectNode.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ObjectNode readInternal(Class<? extends ObjectNode> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
|
||||||
|
Charset charset = getContentTypeCharset(inputMessage.getHeaders().getContentType());
|
||||||
|
String s = StreamUtils.copyToString(inputMessage.getBody(), charset);
|
||||||
|
return new ObjectNode(JsonNodeFactory.withExactBigDecimals(true)).put("result", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void writeInternal(ObjectNode jsonNodes, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Charset getContentTypeCharset(@Nullable MediaType contentType) {
|
||||||
|
if (contentType != null && contentType.getCharset() != null) {
|
||||||
|
return contentType.getCharset();
|
||||||
|
}
|
||||||
|
else if (contentType != null && contentType.isCompatibleWith(MediaType.APPLICATION_JSON)) {
|
||||||
|
// Matching to AbstractJackson2HttpMessageConverter#DEFAULT_CHARSET
|
||||||
|
return StandardCharsets.UTF_8;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Charset charset = getDefaultCharset();
|
||||||
|
Assert.state(charset != null, "No default charset");
|
||||||
|
return charset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,7 +39,7 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
|||||||
|
|
||||||
|
|
||||||
public WechatMarketingFavorApi(WechatPayClient wechatPayClient, String tenantId) {
|
public WechatMarketingFavorApi(WechatPayClient wechatPayClient, String tenantId) {
|
||||||
super(wechatPayClient,tenantId);
|
super(wechatPayClient, tenantId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
|||||||
.build()
|
.build()
|
||||||
.toUri();
|
.toUri();
|
||||||
params.setBelongMerchant(mchId);
|
params.setBelongMerchant(mchId);
|
||||||
return post(uri, params,tenantId());
|
return post(uri, params, tenantId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -111,7 +111,7 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
|||||||
.expand(params.getOpenid())
|
.expand(params.getOpenid())
|
||||||
.toUri();
|
.toUri();
|
||||||
params.setOpenid(null);
|
params.setOpenid(null);
|
||||||
return post(uri, params,tenantId());
|
return post(uri, params, tenantId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -154,7 +154,7 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
|||||||
.build()
|
.build()
|
||||||
.expand(stockId)
|
.expand(stockId)
|
||||||
.toUri();
|
.toUri();
|
||||||
return post(uri, body,tenantId());
|
return post(uri, body, tenantId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -211,7 +211,7 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
|||||||
|
|
||||||
URI uri = uriComponents
|
URI uri = uriComponents
|
||||||
.toUri();
|
.toUri();
|
||||||
return RequestEntity.get(uri).header("Pay-TenantId",tenantId()).build();
|
return RequestEntity.get(uri).header("Pay-TenantId", tenantId()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -242,7 +242,7 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
|||||||
.build()
|
.build()
|
||||||
.expand(stockId)
|
.expand(stockId)
|
||||||
.toUri();
|
.toUri();
|
||||||
return RequestEntity.get(uri).header("Pay-TenantId",tenantId()).build();
|
return RequestEntity.get(uri).header("Pay-TenantId", tenantId()).build();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,7 +279,7 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
|||||||
.build()
|
.build()
|
||||||
.expand(pathParams)
|
.expand(pathParams)
|
||||||
.toUri();
|
.toUri();
|
||||||
return RequestEntity.get(uri).header("Pay-TenantId",tenantId()).build();
|
return RequestEntity.get(uri).header("Pay-TenantId", tenantId()).build();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,7 +364,7 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
|||||||
.build()
|
.build()
|
||||||
.expand(params.getOpenId())
|
.expand(params.getOpenId())
|
||||||
.toUri();
|
.toUri();
|
||||||
return RequestEntity.get(uri).header("Pay-TenantId",tenantId()).build();
|
return RequestEntity.get(uri).header("Pay-TenantId", tenantId()).build();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,7 +380,8 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
|||||||
.function(this::downloadFlowFunction)
|
.function(this::downloadFlowFunction)
|
||||||
.consumer(wechatResponseEntity::convert)
|
.consumer(wechatResponseEntity::convert)
|
||||||
.request();
|
.request();
|
||||||
|
String csv = billDownload(wechatResponseEntity.getBody().get("url").asText());
|
||||||
|
wechatResponseEntity.getBody().put("csv", csv);
|
||||||
return wechatResponseEntity;
|
return wechatResponseEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,6 +397,8 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
|||||||
.function(this::downloadFlowFunction)
|
.function(this::downloadFlowFunction)
|
||||||
.consumer(wechatResponseEntity::convert)
|
.consumer(wechatResponseEntity::convert)
|
||||||
.request();
|
.request();
|
||||||
|
String csv = billDownload(wechatResponseEntity.getBody().get("url").asText());
|
||||||
|
wechatResponseEntity.getBody().put("csv", csv);
|
||||||
return wechatResponseEntity;
|
return wechatResponseEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,7 +407,7 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
|||||||
.build()
|
.build()
|
||||||
.expand(stockId)
|
.expand(stockId)
|
||||||
.toUri();
|
.toUri();
|
||||||
return RequestEntity.get(uri).header("Pay-TenantId",tenantId()).build();
|
return RequestEntity.get(uri).header("Pay-TenantId", tenantId()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -444,7 +447,7 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
|||||||
return RequestEntity.post(uri)
|
return RequestEntity.post(uri)
|
||||||
.header("Content-Type", MediaType.MULTIPART_FORM_DATA_VALUE)
|
.header("Content-Type", MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||||
.header("Meta-Info", metaStr)
|
.header("Meta-Info", metaStr)
|
||||||
.header("Pay-TenantId",tenantId())
|
.header("Pay-TenantId", tenantId())
|
||||||
.body(body);
|
.body(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,9 +477,22 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
|||||||
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||||
.build()
|
.build()
|
||||||
.toUri();
|
.toUri();
|
||||||
return post(uri, body,tenantId());
|
return post(uri, body, tenantId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String billDownload(String link) {
|
||||||
|
return this.client().withType(WechatPayV3Type.FILE_DOWNLOAD, link)
|
||||||
|
.function(this::billDownloadFunction)
|
||||||
|
.download();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private RequestEntity<?> billDownloadFunction(WechatPayV3Type type, String link) {
|
||||||
|
URI uri = UriComponentsBuilder.fromHttpUrl(link)
|
||||||
|
.build()
|
||||||
|
.toUri();
|
||||||
|
return RequestEntity.get(uri).header("Pay-TenantId", tenantId()).build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import org.springframework.http.*;
|
|||||||
import org.springframework.http.converter.HttpMessageConverter;
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
|
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.MimeType;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.web.client.DefaultResponseErrorHandler;
|
import org.springframework.web.client.DefaultResponseErrorHandler;
|
||||||
import org.springframework.web.client.RestOperations;
|
import org.springframework.web.client.RestOperations;
|
||||||
@@ -54,7 +55,7 @@ public class WechatPayClient {
|
|||||||
* @return the executor
|
* @return the executor
|
||||||
*/
|
*/
|
||||||
public <M> Executor<M> withType(WechatPayV3Type wechatPayV3Type, M m) {
|
public <M> Executor<M> withType(WechatPayV3Type wechatPayV3Type, M m) {
|
||||||
return new Executor<>(wechatPayV3Type, m, this.signatureProvider,this.restOperations);
|
return new Executor<>(wechatPayV3Type, m, this.signatureProvider, this.restOperations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -88,10 +89,11 @@ public class WechatPayClient {
|
|||||||
* @param wechatPayV3Type the v 3 pay type
|
* @param wechatPayV3Type the v 3 pay type
|
||||||
* @param model the model
|
* @param model the model
|
||||||
* @param signatureProvider the signature provider
|
* @param signatureProvider the signature provider
|
||||||
|
* @param restOperations the rest operations
|
||||||
*/
|
*/
|
||||||
Executor(WechatPayV3Type wechatPayV3Type,
|
Executor(WechatPayV3Type wechatPayV3Type,
|
||||||
M model,
|
M model,
|
||||||
SignatureProvider signatureProvider, RestOperations restOperations) {
|
SignatureProvider signatureProvider, RestOperations restOperations) {
|
||||||
this.wechatPayV3Type = wechatPayV3Type;
|
this.wechatPayV3Type = wechatPayV3Type;
|
||||||
this.model = model;
|
this.model = model;
|
||||||
this.signatureProvider = signatureProvider;
|
this.signatureProvider = signatureProvider;
|
||||||
@@ -124,7 +126,6 @@ public class WechatPayClient {
|
|||||||
/**
|
/**
|
||||||
* Request.
|
* Request.
|
||||||
*/
|
*/
|
||||||
@SneakyThrows
|
|
||||||
public void request() {
|
public void request() {
|
||||||
RequestEntity<?> requestEntity = this.requestEntityBiFunction.apply(this.wechatPayV3Type, this.model);
|
RequestEntity<?> requestEntity = this.requestEntityBiFunction.apply(this.wechatPayV3Type, this.model);
|
||||||
WechatRequestEntity<?> wechatRequestEntity = WechatRequestEntity.of(requestEntity, this.responseBodyConsumer);
|
WechatRequestEntity<?> wechatRequestEntity = WechatRequestEntity.of(requestEntity, this.responseBodyConsumer);
|
||||||
@@ -132,6 +133,18 @@ public class WechatPayClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download string.
|
||||||
|
*
|
||||||
|
* @return the string
|
||||||
|
*/
|
||||||
|
public String download() {
|
||||||
|
RequestEntity<?> requestEntity = this.requestEntityBiFunction.apply(this.wechatPayV3Type, this.model);
|
||||||
|
WechatRequestEntity<?> wechatRequestEntity = WechatRequestEntity.of(requestEntity, this.responseBodyConsumer);
|
||||||
|
return this.doDownload(this.header(wechatRequestEntity));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造私钥签名.
|
* 构造私钥签名.
|
||||||
*
|
*
|
||||||
@@ -143,7 +156,7 @@ public class WechatPayClient {
|
|||||||
UriComponents uri = UriComponentsBuilder.fromUri(requestEntity.getUrl()).build();
|
UriComponents uri = UriComponentsBuilder.fromUri(requestEntity.getUrl()).build();
|
||||||
String canonicalUrl = uri.getPath();
|
String canonicalUrl = uri.getPath();
|
||||||
String encodedQuery = uri.getQuery();
|
String encodedQuery = uri.getQuery();
|
||||||
Assert.notNull(canonicalUrl,"canonicalUrl is required");
|
Assert.notNull(canonicalUrl, "canonicalUrl is required");
|
||||||
if (encodedQuery != null) {
|
if (encodedQuery != null) {
|
||||||
canonicalUrl += "?" + encodedQuery;
|
canonicalUrl += "?" + encodedQuery;
|
||||||
}
|
}
|
||||||
@@ -156,11 +169,11 @@ public class WechatPayClient {
|
|||||||
T entityBody = requestEntity.getBody();
|
T entityBody = requestEntity.getBody();
|
||||||
String body = requestEntity.hasBody() ? Objects.requireNonNull(entityBody).toString() : "";
|
String body = requestEntity.hasBody() ? Objects.requireNonNull(entityBody).toString() : "";
|
||||||
if (WechatPayV3Type.MARKETING_IMAGE_UPLOAD.pattern().contains(canonicalUrl)) {
|
if (WechatPayV3Type.MARKETING_IMAGE_UPLOAD.pattern().contains(canonicalUrl)) {
|
||||||
body = Objects.requireNonNull(headers.get("Meta-Info")).get(0);
|
body = Objects.requireNonNull(headers.get("Meta-Info")).get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
String tenantId = Objects.requireNonNull(headers.get("Pay-TenantId")).get(0);
|
String tenantId = Objects.requireNonNull(headers.get("Pay-TenantId")).get(0);
|
||||||
String authorization = signatureProvider.requestSign(tenantId,httpMethod.name(), canonicalUrl, body);
|
String authorization = signatureProvider.requestSign(tenantId, httpMethod.name(), canonicalUrl, body);
|
||||||
|
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
httpHeaders.addAll(headers);
|
httpHeaders.addAll(headers);
|
||||||
@@ -215,8 +228,27 @@ public class WechatPayClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private <T> String doDownload(WechatRequestEntity<T> requestEntity) {
|
||||||
|
|
||||||
|
ResponseEntity<String> responseEntity = restOperations.exchange(requestEntity, String.class);
|
||||||
|
|
||||||
|
String body = responseEntity.getBody();
|
||||||
|
if (!responseEntity.getStatusCode().is2xxSuccessful()) {
|
||||||
|
throw new PayException("wechat pay server error,result : " + body);
|
||||||
|
}
|
||||||
|
if (Objects.isNull(body)) {
|
||||||
|
throw new PayException("cant obtain wechat response body");
|
||||||
|
}
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signature provider signature provider.
|
||||||
|
*
|
||||||
|
* @return the signature provider
|
||||||
|
*/
|
||||||
public SignatureProvider signatureProvider() {
|
public SignatureProvider signatureProvider() {
|
||||||
return signatureProvider;
|
return signatureProvider;
|
||||||
}
|
}
|
||||||
@@ -229,6 +261,7 @@ public class WechatPayClient {
|
|||||||
|
|
||||||
messageConverters.removeIf(httpMessageConverter -> httpMessageConverter instanceof AllEncompassingFormHttpMessageConverter);
|
messageConverters.removeIf(httpMessageConverter -> httpMessageConverter instanceof AllEncompassingFormHttpMessageConverter);
|
||||||
messageConverters.add(new ExtensionFormHttpMessageConverter());
|
messageConverters.add(new ExtensionFormHttpMessageConverter());
|
||||||
|
// messageConverters.add(new DownloadHttpMessageConverter(MediaType.asMediaType(MimeType.valueOf("text/plain;charset=utf-8"))));
|
||||||
restTemplate.setMessageConverters(messageConverters);
|
restTemplate.setMessageConverters(messageConverters);
|
||||||
this.restOperations = restTemplate;
|
this.restOperations = restTemplate;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user