mirror of
https://github.com/dromara/payment-spring-boot.git
synced 2026-03-14 05:43:46 +08:00
移除过滤器
This commit is contained in:
@@ -1,29 +0,0 @@
|
|||||||
package com.enongm.dianji.payment.wechat.v3;
|
|
||||||
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Dax
|
|
||||||
* @since 16:16
|
|
||||||
*/
|
|
||||||
public class DefaultPayFilterChain implements PayFilterChain {
|
|
||||||
private int pos = 0;
|
|
||||||
private final List<PayFilter> filters = new ArrayList<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void register(PayFilter filter) {
|
|
||||||
filters.add(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doChain(WechatRequestEntity<?> requestEntity) {
|
|
||||||
int size = filters.size();
|
|
||||||
if (pos < size) {
|
|
||||||
PayFilter payFilter = filters.get(pos++);
|
|
||||||
payFilter.doFilter(requestEntity, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package com.enongm.dianji.payment.wechat.v3;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The interface Pay filter.
|
|
||||||
*
|
|
||||||
* @author Dax
|
|
||||||
* @since 15 :08
|
|
||||||
*/
|
|
||||||
public interface PayFilter {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do filter.
|
|
||||||
* @param requestEntity the request entity
|
|
||||||
* @param chain the chain*/
|
|
||||||
<T> void doFilter(WechatRequestEntity<T> requestEntity, PayFilterChain chain);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
package com.enongm.dianji.payment.wechat.v3;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The interface Pay filter chain.
|
|
||||||
*
|
|
||||||
* @author Dax
|
|
||||||
* @since 16 :11
|
|
||||||
*/
|
|
||||||
public interface PayFilterChain {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do chain.
|
|
||||||
*
|
|
||||||
* @param requestEntity the request entity
|
|
||||||
*/
|
|
||||||
void doChain(WechatRequestEntity<?> requestEntity);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register.
|
|
||||||
*
|
|
||||||
* @param filter the filter
|
|
||||||
*/
|
|
||||||
void register(PayFilter filter);
|
|
||||||
}
|
|
||||||
@@ -1,14 +1,21 @@
|
|||||||
package com.enongm.dianji.payment.wechat.v3;
|
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.enumeration.WechatPayV3Type;
|
||||||
import com.enongm.dianji.payment.wechat.v3.filter.HeaderFilter;
|
|
||||||
import com.enongm.dianji.payment.wechat.v3.filter.HttpRequestFilter;
|
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.springframework.http.RequestEntity;
|
import org.springframework.http.*;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.web.client.DefaultResponseErrorHandler;
|
||||||
|
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.util.Collections;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
@@ -19,7 +26,7 @@ import java.util.function.Consumer;
|
|||||||
* @since 11 :43
|
* @since 11 :43
|
||||||
*/
|
*/
|
||||||
public class WechatPayClient {
|
public class WechatPayClient {
|
||||||
private final PayFilterChain payFilterChain;
|
private final SignatureProvider signatureProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new Wechat pay service.
|
* Instantiates a new Wechat pay service.
|
||||||
@@ -27,12 +34,7 @@ public class WechatPayClient {
|
|||||||
* @param signatureProvider the signature provider
|
* @param signatureProvider the signature provider
|
||||||
*/
|
*/
|
||||||
public WechatPayClient(SignatureProvider signatureProvider) {
|
public WechatPayClient(SignatureProvider signatureProvider) {
|
||||||
DefaultPayFilterChain defaultPayFilterChain = new DefaultPayFilterChain();
|
this.signatureProvider = signatureProvider;
|
||||||
// 构造私钥签名
|
|
||||||
defaultPayFilterChain.register(new HeaderFilter(signatureProvider));
|
|
||||||
// 向微信支付服务器发起请求
|
|
||||||
defaultPayFilterChain.register(new HttpRequestFilter(signatureProvider));
|
|
||||||
this.payFilterChain = defaultPayFilterChain;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -45,7 +47,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.payFilterChain);
|
return new Executor<>(wechatPayV3Type, m, this.signatureProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -59,11 +61,8 @@ public class WechatPayClient {
|
|||||||
* The V 3 pay type.
|
* The V 3 pay type.
|
||||||
*/
|
*/
|
||||||
private final WechatPayV3Type wechatPayV3Type;
|
private final WechatPayV3Type wechatPayV3Type;
|
||||||
|
private final RestOperations restOperations;
|
||||||
/**
|
private final SignatureProvider signatureProvider;
|
||||||
* The Pay filter chain.
|
|
||||||
*/
|
|
||||||
private final PayFilterChain payFilterChain;
|
|
||||||
private final M model;
|
private final M model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,21 +73,25 @@ public class WechatPayClient {
|
|||||||
/**
|
/**
|
||||||
* The Response body consumer.
|
* The Response body consumer.
|
||||||
*/
|
*/
|
||||||
private Consumer<ResponseEntity<ObjectNode>> responseBodyConsumer;
|
private Consumer<ResponseEntity<ObjectNode>> responseBodyConsumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new Executor.
|
* Instantiates a new Executor.
|
||||||
*
|
*
|
||||||
* @param wechatPayV3Type the v 3 pay type
|
* @param wechatPayV3Type the v 3 pay type
|
||||||
* @param model the model
|
* @param model the model
|
||||||
* @param payFilterChain the pay filter chain
|
* @param signatureProvider the signature provider
|
||||||
*/
|
*/
|
||||||
public Executor(WechatPayV3Type wechatPayV3Type,
|
public Executor(WechatPayV3Type wechatPayV3Type,
|
||||||
M model,
|
M model,
|
||||||
PayFilterChain payFilterChain) {
|
SignatureProvider signatureProvider) {
|
||||||
this.wechatPayV3Type = wechatPayV3Type;
|
this.wechatPayV3Type = wechatPayV3Type;
|
||||||
this.model = model;
|
this.model = model;
|
||||||
this.payFilterChain = payFilterChain;
|
this.signatureProvider = signatureProvider;
|
||||||
|
RestTemplate restTemplate = new RestTemplate();
|
||||||
|
DefaultResponseErrorHandler errorHandler = new WechatPayResponseErrorHandler();
|
||||||
|
restTemplate.setErrorHandler(errorHandler);
|
||||||
|
this.restOperations = restTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -120,8 +123,83 @@ public class WechatPayClient {
|
|||||||
@SneakyThrows
|
@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);
|
||||||
payFilterChain.doChain(WechatRequestEntity.of(requestEntity, this.responseBodyConsumer));
|
WechatRequestEntity<?> wechatRequestEntity = WechatRequestEntity.of(requestEntity, this.responseBodyConsumer);
|
||||||
|
this.doExecute(this.header(wechatRequestEntity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造私钥签名.
|
||||||
|
*
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param requestEntity the request entity
|
||||||
|
*/
|
||||||
|
private <T> WechatRequestEntity<T> header(WechatRequestEntity<T> requestEntity) {
|
||||||
|
|
||||||
|
UriComponents uri = UriComponentsBuilder.fromUri(requestEntity.getUrl()).build();
|
||||||
|
String canonicalUrl = uri.getPath();
|
||||||
|
String encodedQuery = uri.getQuery();
|
||||||
|
|
||||||
|
if (encodedQuery != null) {
|
||||||
|
canonicalUrl += "?" + encodedQuery;
|
||||||
|
}
|
||||||
|
// 签名
|
||||||
|
HttpMethod httpMethod = requestEntity.getMethod();
|
||||||
|
Assert.notNull(httpMethod, "httpMethod is required");
|
||||||
|
|
||||||
|
String body = requestEntity.hasBody() ? Objects.requireNonNull(requestEntity.getBody()).toString() : "";
|
||||||
|
String authorization = signatureProvider.requestSign(httpMethod.name(), canonicalUrl, body);
|
||||||
|
|
||||||
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
|
httpHeaders.addAll(requestEntity.getHeaders());
|
||||||
|
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
|
||||||
|
// 兼容图片上传,自定义优先级最高
|
||||||
|
if (Objects.isNull(httpHeaders.getContentType())) {
|
||||||
|
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
}
|
||||||
|
httpHeaders.add("Authorization", authorization);
|
||||||
|
httpHeaders.add("User-Agent", "X-Pay-Service");
|
||||||
|
|
||||||
|
return requestEntity.headers(httpHeaders);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private <T> void doExecute(WechatRequestEntity<T> requestEntity) {
|
||||||
|
|
||||||
|
ResponseEntity<ObjectNode> responseEntity = restOperations.exchange(requestEntity, ObjectNode.class);
|
||||||
|
HttpHeaders headers = responseEntity.getHeaders();
|
||||||
|
ObjectNode body = responseEntity.getBody();
|
||||||
|
|
||||||
|
if (Objects.isNull(body)) {
|
||||||
|
throw new IllegalStateException("cant obtain response body");
|
||||||
|
}
|
||||||
|
// 微信请求回调id
|
||||||
|
// String RequestId = response.header("Request-ID");
|
||||||
|
// 微信平台证书序列号 用来取微信平台证书
|
||||||
|
String wechatpaySerial = headers.getFirst("Wechatpay-Serial");
|
||||||
|
//获取应答签名
|
||||||
|
String wechatpaySignature = headers.getFirst("Wechatpay-Signature");
|
||||||
|
//构造验签名串
|
||||||
|
String wechatpayTimestamp = headers.getFirst("Wechatpay-Timestamp");
|
||||||
|
String wechatpayNonce = headers.getFirst("Wechatpay-Nonce");
|
||||||
|
|
||||||
|
// 验证微信服务器签名
|
||||||
|
if (signatureProvider.responseSignVerify(wechatpaySerial,
|
||||||
|
wechatpaySignature,
|
||||||
|
wechatpayTimestamp,
|
||||||
|
wechatpayNonce,
|
||||||
|
body.toString())) {
|
||||||
|
Consumer<ResponseEntity<ObjectNode>> responseConsumer = requestEntity.getResponseBodyConsumer();
|
||||||
|
if (Objects.nonNull(responseConsumer)) {
|
||||||
|
// 验证通过消费
|
||||||
|
responseConsumer.accept(responseEntity);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new PayException("wechat pay signature failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
package com.enongm.dianji.payment.wechat.v3.filter;
|
|
||||||
|
|
||||||
|
|
||||||
import com.enongm.dianji.payment.wechat.v3.PayFilter;
|
|
||||||
import com.enongm.dianji.payment.wechat.v3.PayFilterChain;
|
|
||||||
import com.enongm.dianji.payment.wechat.v3.SignatureProvider;
|
|
||||||
import com.enongm.dianji.payment.wechat.v3.WechatRequestEntity;
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.web.util.UriComponents;
|
|
||||||
import org.springframework.web.util.UriComponentsBuilder;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 微信支付 给请求添加必要的请求头.
|
|
||||||
* 3
|
|
||||||
*
|
|
||||||
* @author Dax
|
|
||||||
* @since 15 :12
|
|
||||||
*/
|
|
||||||
public class HeaderFilter implements PayFilter {
|
|
||||||
private final SignatureProvider signatureProvider;
|
|
||||||
|
|
||||||
public HeaderFilter(SignatureProvider signatureProvider) {
|
|
||||||
this.signatureProvider = signatureProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> void doFilter(WechatRequestEntity<T> requestEntity, PayFilterChain chain) {
|
|
||||||
|
|
||||||
UriComponents uri = UriComponentsBuilder.fromUri(requestEntity.getUrl()).build();
|
|
||||||
String canonicalUrl = uri.getPath();
|
|
||||||
String encodedQuery = uri.getQuery();
|
|
||||||
|
|
||||||
if (encodedQuery != null) {
|
|
||||||
canonicalUrl += "?" + encodedQuery;
|
|
||||||
}
|
|
||||||
// 签名
|
|
||||||
HttpMethod httpMethod = requestEntity.getMethod();
|
|
||||||
Assert.notNull(httpMethod, "httpMethod is required");
|
|
||||||
|
|
||||||
String body = requestEntity.hasBody() ? Objects.requireNonNull(requestEntity.getBody()).toString() : "";
|
|
||||||
String authorization = signatureProvider.requestSign(httpMethod.name(), canonicalUrl, body);
|
|
||||||
|
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
|
||||||
httpHeaders.addAll(requestEntity.getHeaders());
|
|
||||||
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
|
|
||||||
// 兼容图片上传,自定义优先级最高
|
|
||||||
if (Objects.isNull(httpHeaders.getContentType())) {
|
|
||||||
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|
|
||||||
}
|
|
||||||
httpHeaders.add("Authorization", authorization);
|
|
||||||
httpHeaders.add("User-Agent", "X-Pay-Service");
|
|
||||||
|
|
||||||
chain.doChain(requestEntity.headers(httpHeaders));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
package com.enongm.dianji.payment.wechat.v3.filter;
|
|
||||||
|
|
||||||
|
|
||||||
import com.enongm.dianji.payment.PayException;
|
|
||||||
import com.enongm.dianji.payment.wechat.WechatPayResponseErrorHandler;
|
|
||||||
import com.enongm.dianji.payment.wechat.v3.PayFilter;
|
|
||||||
import com.enongm.dianji.payment.wechat.v3.PayFilterChain;
|
|
||||||
import com.enongm.dianji.payment.wechat.v3.SignatureProvider;
|
|
||||||
import com.enongm.dianji.payment.wechat.v3.WechatRequestEntity;
|
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.client.DefaultResponseErrorHandler;
|
|
||||||
import org.springframework.web.client.RestOperations;
|
|
||||||
import org.springframework.web.client.RestTemplate;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 微信支付用来请求微信支付服务器
|
|
||||||
*
|
|
||||||
* @author Dax
|
|
||||||
* @since 10:42
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class HttpRequestFilter implements PayFilter {
|
|
||||||
private final RestOperations restOperations;
|
|
||||||
private final SignatureProvider signatureProvider;
|
|
||||||
|
|
||||||
|
|
||||||
public HttpRequestFilter(SignatureProvider signatureProvider) {
|
|
||||||
this.signatureProvider = signatureProvider;
|
|
||||||
RestTemplate restTemplate = new RestTemplate();
|
|
||||||
DefaultResponseErrorHandler errorHandler = new WechatPayResponseErrorHandler();
|
|
||||||
restTemplate.setErrorHandler(errorHandler);
|
|
||||||
this.restOperations = restTemplate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> void doFilter(WechatRequestEntity<T> requestEntity, PayFilterChain chain) {
|
|
||||||
|
|
||||||
ResponseEntity<ObjectNode> responseEntity = restOperations.exchange(requestEntity, ObjectNode.class);
|
|
||||||
HttpHeaders headers = responseEntity.getHeaders();
|
|
||||||
ObjectNode body = responseEntity.getBody();
|
|
||||||
|
|
||||||
if (Objects.isNull(body)) {
|
|
||||||
throw new IllegalStateException("cant obtain response body");
|
|
||||||
}
|
|
||||||
// 微信请求回调id
|
|
||||||
// String RequestId = response.header("Request-ID");
|
|
||||||
// 微信平台证书序列号 用来取微信平台证书
|
|
||||||
String wechatpaySerial = headers.getFirst("Wechatpay-Serial");
|
|
||||||
//获取应答签名
|
|
||||||
String wechatpaySignature = headers.getFirst("Wechatpay-Signature");
|
|
||||||
//构造验签名串
|
|
||||||
String wechatpayTimestamp = headers.getFirst("Wechatpay-Timestamp");
|
|
||||||
String wechatpayNonce = headers.getFirst("Wechatpay-Nonce");
|
|
||||||
|
|
||||||
// 验证微信服务器签名
|
|
||||||
if (signatureProvider.responseSignVerify(wechatpaySerial,
|
|
||||||
wechatpaySignature,
|
|
||||||
wechatpayTimestamp,
|
|
||||||
wechatpayNonce,
|
|
||||||
body.toString())) {
|
|
||||||
Consumer<ResponseEntity<ObjectNode>> responseConsumer = requestEntity.getResponseBodyConsumer();
|
|
||||||
if (Objects.nonNull(responseConsumer)) {
|
|
||||||
// 验证通过消费
|
|
||||||
responseConsumer.accept(responseEntity);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new PayException("wechat pay signature failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
2
pom.xml
2
pom.xml
@@ -22,7 +22,7 @@
|
|||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<spring-boot.version>2.3.4.RELEASE</spring-boot.version>
|
<spring-boot.version>2.1.14.RELEASE</spring-boot.version>
|
||||||
<aliy-pay-sdk.version>4.10.167.ALL</aliy-pay-sdk.version>
|
<aliy-pay-sdk.version>4.10.167.ALL</aliy-pay-sdk.version>
|
||||||
<oss-starter.version>1.0.0.RELEASE</oss-starter.version>
|
<oss-starter.version>1.0.0.RELEASE</oss-starter.version>
|
||||||
<lombok.verison>1.18.12</lombok.verison>
|
<lombok.verison>1.18.12</lombok.verison>
|
||||||
|
|||||||
Reference in New Issue
Block a user