更新了商品管理模块
This commit is contained in:
parent
37c501ebfd
commit
534d5714b3
|
@ -1,43 +1,43 @@
|
||||||
package com.cultural.heritage.controller.wxPayDemo;
|
//package com.cultural.heritage.controller.wxPayDemo;
|
||||||
|
//
|
||||||
|
//
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
//import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
//
|
||||||
import java.io.BufferedReader;
|
//import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
//import java.io.IOException;
|
||||||
|
//
|
||||||
/**
|
///**
|
||||||
* @author weikai
|
// * @author weikai
|
||||||
*/
|
// */
|
||||||
public class HttpUtils {
|
//public class HttpUtils {
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 将通知参数转化为字符串
|
// * 将通知参数转化为字符串
|
||||||
* @param request
|
// * @param request
|
||||||
* @return
|
// * @return
|
||||||
*/
|
// */
|
||||||
public static String readData(HttpServletRequest request) {
|
// public static String readData(HttpServletRequest request) {
|
||||||
BufferedReader br = null;
|
// BufferedReader br = null;
|
||||||
try {
|
// try {
|
||||||
StringBuilder result = new StringBuilder();
|
// StringBuilder result = new StringBuilder();
|
||||||
br = request.getReader();
|
// br = request.getReader();
|
||||||
for (String line; (line = br.readLine()) != null; ) {
|
// for (String line; (line = br.readLine()) != null; ) {
|
||||||
if (result.length() > 0) {
|
// if (result.length() > 0) {
|
||||||
result.append("\n");
|
// result.append("\n");
|
||||||
}
|
// }
|
||||||
result.append(line);
|
// result.append(line);
|
||||||
}
|
// }
|
||||||
return result.toString();
|
// return result.toString();
|
||||||
} catch (IOException e) {
|
// } catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
// throw new RuntimeException(e);
|
||||||
} finally {
|
// } finally {
|
||||||
if (br != null) {
|
// if (br != null) {
|
||||||
try {
|
// try {
|
||||||
br.close();
|
// br.close();
|
||||||
} catch (IOException e) {
|
// } catch (IOException e) {
|
||||||
e.printStackTrace();
|
// e.printStackTrace();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
|
@ -1,110 +1,110 @@
|
||||||
package com.cultural.heritage.controller.wxPayDemo;
|
//package com.cultural.heritage.controller.wxPayDemo;
|
||||||
|
//
|
||||||
|
//
|
||||||
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
|
//import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
//import jakarta.servlet.http.HttpServletRequest;
|
||||||
import org.apache.http.HttpEntity;
|
//import org.apache.http.HttpEntity;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
//import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.util.EntityUtils;
|
//import org.apache.http.util.EntityUtils;
|
||||||
import org.slf4j.Logger;
|
//import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
//import org.slf4j.LoggerFactory;
|
||||||
|
//
|
||||||
import java.io.IOException;
|
//import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
//import java.nio.charset.StandardCharsets;
|
||||||
import java.time.DateTimeException;
|
//import java.time.DateTimeException;
|
||||||
import java.time.Duration;
|
//import java.time.Duration;
|
||||||
import java.time.Instant;
|
//import java.time.Instant;
|
||||||
|
//
|
||||||
import static com.wechat.pay.contrib.apache.httpclient.constant.WechatPayHttpHeaders.*;
|
//import static com.wechat.pay.contrib.apache.httpclient.constant.WechatPayHttpHeaders.*;
|
||||||
|
//
|
||||||
public class WechatPay2ValidatorForRequest {
|
//public class WechatPay2ValidatorForRequest {
|
||||||
|
//
|
||||||
protected static final Logger log = LoggerFactory.getLogger(WechatPay2ValidatorForRequest.class);
|
// protected static final Logger log = LoggerFactory.getLogger(WechatPay2ValidatorForRequest.class);
|
||||||
/**
|
// /**
|
||||||
* 应答超时时间,单位为分钟
|
// * 应答超时时间,单位为分钟
|
||||||
*/
|
// */
|
||||||
protected static final long RESPONSE_EXPIRED_MINUTES = 5;
|
// protected static final long RESPONSE_EXPIRED_MINUTES = 5;
|
||||||
protected final Verifier verifier;
|
// protected final Verifier verifier;
|
||||||
protected final String requestId;
|
// protected final String requestId;
|
||||||
protected final String body;
|
// protected final String body;
|
||||||
|
//
|
||||||
|
//
|
||||||
public WechatPay2ValidatorForRequest(Verifier verifier, String requestId, String body) {
|
// public WechatPay2ValidatorForRequest(Verifier verifier, String requestId, String body) {
|
||||||
this.verifier = verifier;
|
// this.verifier = verifier;
|
||||||
this.requestId = requestId;
|
// this.requestId = requestId;
|
||||||
this.body = body;
|
// this.body = body;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
protected static IllegalArgumentException parameterError(String message, Object... args) {
|
// protected static IllegalArgumentException parameterError(String message, Object... args) {
|
||||||
message = String.format(message, args);
|
// message = String.format(message, args);
|
||||||
return new IllegalArgumentException("parameter error: " + message);
|
// return new IllegalArgumentException("parameter error: " + message);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
protected static IllegalArgumentException verifyFail(String message, Object... args) {
|
// protected static IllegalArgumentException verifyFail(String message, Object... args) {
|
||||||
message = String.format(message, args);
|
// message = String.format(message, args);
|
||||||
return new IllegalArgumentException("signature verify fail: " + message);
|
// return new IllegalArgumentException("signature verify fail: " + message);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
public final boolean validate(HttpServletRequest request) throws IOException {
|
// public final boolean validate(HttpServletRequest request) throws IOException {
|
||||||
try {
|
// try {
|
||||||
//处理请求参数
|
// //处理请求参数
|
||||||
validateParameters(request);
|
// validateParameters(request);
|
||||||
|
//
|
||||||
//构造验签名串
|
// //构造验签名串
|
||||||
String message = buildMessage(request);
|
// String message = buildMessage(request);
|
||||||
|
//
|
||||||
String serial = request.getHeader(WECHAT_PAY_SERIAL);
|
// String serial = request.getHeader(WECHAT_PAY_SERIAL);
|
||||||
String signature = request.getHeader(WECHAT_PAY_SIGNATURE);
|
// String signature = request.getHeader(WECHAT_PAY_SIGNATURE);
|
||||||
|
//
|
||||||
//验签
|
// //验签
|
||||||
if (!verifier.verify(serial, message.getBytes(StandardCharsets.UTF_8), signature)) {
|
// if (!verifier.verify(serial, message.getBytes(StandardCharsets.UTF_8), signature)) {
|
||||||
throw verifyFail("serial=[%s] message=[%s] sign=[%s], request-id=[%s]",
|
// throw verifyFail("serial=[%s] message=[%s] sign=[%s], request-id=[%s]",
|
||||||
serial, message, signature, requestId);
|
// serial, message, signature, requestId);
|
||||||
}
|
// }
|
||||||
} catch (IllegalArgumentException e) {
|
// } catch (IllegalArgumentException e) {
|
||||||
log.warn(e.getMessage());
|
// log.warn(e.getMessage());
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
protected final void validateParameters(HttpServletRequest request) {
|
// protected final void validateParameters(HttpServletRequest request) {
|
||||||
|
//
|
||||||
// NOTE: ensure HEADER_WECHAT_PAY_TIMESTAMP at last
|
// // NOTE: ensure HEADER_WECHAT_PAY_TIMESTAMP at last
|
||||||
String[] headers = {WECHAT_PAY_SERIAL, WECHAT_PAY_SIGNATURE, WECHAT_PAY_NONCE, WECHAT_PAY_TIMESTAMP};
|
// String[] headers = {WECHAT_PAY_SERIAL, WECHAT_PAY_SIGNATURE, WECHAT_PAY_NONCE, WECHAT_PAY_TIMESTAMP};
|
||||||
|
//
|
||||||
String header = null;
|
// String header = null;
|
||||||
for (String headerName : headers) {
|
// for (String headerName : headers) {
|
||||||
header = request.getHeader(headerName);
|
// header = request.getHeader(headerName);
|
||||||
if (header == null) {
|
// if (header == null) {
|
||||||
throw parameterError("empty [%s], request-id=[%s]", headerName, requestId);
|
// throw parameterError("empty [%s], request-id=[%s]", headerName, requestId);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
//判断请求是否过期
|
// //判断请求是否过期
|
||||||
String timestampStr = header;
|
// String timestampStr = header;
|
||||||
try {
|
// try {
|
||||||
Instant responseTime = Instant.ofEpochSecond(Long.parseLong(timestampStr));
|
// Instant responseTime = Instant.ofEpochSecond(Long.parseLong(timestampStr));
|
||||||
// 拒绝过期请求
|
// // 拒绝过期请求
|
||||||
if (Duration.between(responseTime, Instant.now()).abs().toMinutes() >= RESPONSE_EXPIRED_MINUTES) {
|
// if (Duration.between(responseTime, Instant.now()).abs().toMinutes() >= RESPONSE_EXPIRED_MINUTES) {
|
||||||
throw parameterError("timestamp=[%s] expires, request-id=[%s]", timestampStr, requestId);
|
// throw parameterError("timestamp=[%s] expires, request-id=[%s]", timestampStr, requestId);
|
||||||
}
|
// }
|
||||||
} catch (DateTimeException | NumberFormatException e) {
|
// } catch (DateTimeException | NumberFormatException e) {
|
||||||
throw parameterError("invalid timestamp=[%s], request-id=[%s]", timestampStr, requestId);
|
// throw parameterError("invalid timestamp=[%s], request-id=[%s]", timestampStr, requestId);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
protected final String buildMessage(HttpServletRequest request) throws IOException {
|
// protected final String buildMessage(HttpServletRequest request) throws IOException {
|
||||||
String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
|
// String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
|
||||||
String nonce = request.getHeader(WECHAT_PAY_NONCE);
|
// String nonce = request.getHeader(WECHAT_PAY_NONCE);
|
||||||
return timestamp + "\n"
|
// return timestamp + "\n"
|
||||||
+ nonce + "\n"
|
// + nonce + "\n"
|
||||||
+ body + "\n";
|
// + body + "\n";
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
protected final String getResponseBody(CloseableHttpResponse response) throws IOException {
|
// protected final String getResponseBody(CloseableHttpResponse response) throws IOException {
|
||||||
HttpEntity entity = response.getEntity();
|
// HttpEntity entity = response.getEntity();
|
||||||
return (entity != null && entity.isRepeatable()) ? EntityUtils.toString(entity) : "";
|
// return (entity != null && entity.isRepeatable()) ? EntityUtils.toString(entity) : "";
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
|
@ -1,55 +1,55 @@
|
||||||
package com.cultural.heritage.controller.wxPayDemo;
|
//package com.cultural.heritage.controller.wxPayDemo;
|
||||||
|
//
|
||||||
|
//
|
||||||
import lombok.AllArgsConstructor;
|
//import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
//import lombok.Getter;
|
||||||
|
//
|
||||||
@AllArgsConstructor
|
//@AllArgsConstructor
|
||||||
@Getter
|
//@Getter
|
||||||
public enum WxApiType {
|
//public enum WxApiType {
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
*
|
// *
|
||||||
*/
|
// */
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* Native下单
|
// * Native下单
|
||||||
*/
|
// */
|
||||||
NATIVE_PAY("/v3/pay/transactions/native"),
|
// NATIVE_PAY("/v3/pay/transactions/native"),
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 查询订单
|
// * 查询订单
|
||||||
*/
|
// */
|
||||||
ORDER_QUERY_BY_NO("/v3/pay/transactions/out-trade-no/%s"),
|
// ORDER_QUERY_BY_NO("/v3/pay/transactions/out-trade-no/%s"),
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 关闭订单
|
// * 关闭订单
|
||||||
*/
|
// */
|
||||||
CLOSE_ORDER_BY_NO("/v3/pay/transactions/out-trade-no/%s/close"),
|
// CLOSE_ORDER_BY_NO("/v3/pay/transactions/out-trade-no/%s/close"),
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 申请退款
|
// * 申请退款
|
||||||
*/
|
// */
|
||||||
DOMESTIC_REFUNDS("/v3/refund/domestic/refunds"),
|
// DOMESTIC_REFUNDS("/v3/refund/domestic/refunds"),
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 查询单笔退款
|
// * 查询单笔退款
|
||||||
*/
|
// */
|
||||||
DOMESTIC_REFUNDS_QUERY("/v3/refund/domestic/refunds/%s"),
|
// DOMESTIC_REFUNDS_QUERY("/v3/refund/domestic/refunds/%s"),
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 申请交易账单
|
// * 申请交易账单
|
||||||
*/
|
// */
|
||||||
TRADE_BILLS("/v3/bill/tradebill"),
|
// TRADE_BILLS("/v3/bill/tradebill"),
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 申请资金账单
|
// * 申请资金账单
|
||||||
*/
|
// */
|
||||||
FUND_FLOW_BILLS("/v3/bill/fundflowbill");
|
// FUND_FLOW_BILLS("/v3/bill/fundflowbill");
|
||||||
|
//
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 类型
|
// * 类型
|
||||||
*/
|
// */
|
||||||
private final String type;
|
// private final String type;
|
||||||
}
|
//}
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
package com.cultural.heritage.controller.wxPayDemo;
|
//package com.cultural.heritage.controller.wxPayDemo;
|
||||||
|
//
|
||||||
|
//
|
||||||
import lombok.AllArgsConstructor;
|
//import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
//import lombok.Getter;
|
||||||
|
//
|
||||||
@AllArgsConstructor
|
//@AllArgsConstructor
|
||||||
@Getter
|
//@Getter
|
||||||
public enum WxNotifyType {
|
//public enum WxNotifyType {
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 支付通知
|
// * 支付通知
|
||||||
*/
|
// */
|
||||||
NATIVE_NOTIFY("/api/wx-pay/notify/native"),
|
// NATIVE_NOTIFY("/api/wx-pay/notify/native"),
|
||||||
|
//
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 退款结果通知
|
// * 退款结果通知
|
||||||
*/
|
// */
|
||||||
REFUND_NOTIFY("/api/wx-pay/notify/refunds");
|
// REFUND_NOTIFY("/api/wx-pay/notify/refunds");
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 类型
|
// * 类型
|
||||||
*/
|
// */
|
||||||
private final String type;
|
// private final String type;
|
||||||
}
|
//}
|
||||||
|
|
|
@ -1,142 +1,142 @@
|
||||||
package com.cultural.heritage.controller.wxPayDemo;
|
//package com.cultural.heritage.controller.wxPayDemo;
|
||||||
|
//
|
||||||
|
//
|
||||||
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
|
//import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
|
||||||
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
|
//import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
|
||||||
import com.wechat.pay.contrib.apache.httpclient.auth.ScheduledUpdateCertificatesVerifier;
|
//import com.wechat.pay.contrib.apache.httpclient.auth.ScheduledUpdateCertificatesVerifier;
|
||||||
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
|
//import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
|
||||||
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
|
//import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
|
||||||
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
|
//import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
|
||||||
import lombok.Data;
|
//import lombok.Data;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
//import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
//import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
//import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
//import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
//import org.springframework.context.annotation.Configuration;
|
||||||
|
//
|
||||||
import java.io.FileInputStream;
|
//import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
//import java.io.FileNotFoundException;
|
||||||
import java.nio.charset.StandardCharsets;
|
//import java.nio.charset.StandardCharsets;
|
||||||
import java.security.PrivateKey;
|
//import java.security.PrivateKey;
|
||||||
|
//
|
||||||
@Configuration
|
//@Configuration
|
||||||
@ConfigurationProperties(prefix = "wx.pay") //读取wxpay节点
|
//@ConfigurationProperties(prefix = "wx.pay") //读取wxpay节点
|
||||||
@Data //使用set方法将wxpay节点中的值填充到当前类的属性中
|
//@Data //使用set方法将wxpay节点中的值填充到当前类的属性中
|
||||||
@Slf4j
|
//@Slf4j
|
||||||
public class WxPayConfig {
|
//public class WxPayConfig {
|
||||||
|
//
|
||||||
// 商户号
|
// // 商户号
|
||||||
private String mchId;
|
// private String mchId;
|
||||||
|
//
|
||||||
// 商户API证书序列号
|
// // 商户API证书序列号
|
||||||
private String mchSerialNo;
|
// private String mchSerialNo;
|
||||||
|
//
|
||||||
// 商户私钥文件
|
// // 商户私钥文件
|
||||||
private String privateKeyPath;
|
// private String privateKeyPath;
|
||||||
|
//
|
||||||
// APIv3密钥
|
// // APIv3密钥
|
||||||
private String apiV3Key;
|
// private String apiV3Key;
|
||||||
|
//
|
||||||
// APPID
|
// // APPID
|
||||||
private String appid;
|
// private String appid;
|
||||||
|
//
|
||||||
// 微信服务器地址
|
// // 微信服务器地址
|
||||||
private String domain;
|
// private String domain;
|
||||||
|
//
|
||||||
// 接收结果通知地址
|
// // 接收结果通知地址
|
||||||
private String notifyDomain;
|
// private String notifyDomain;
|
||||||
|
//
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 获取商户的私钥文件
|
// * 获取商户的私钥文件
|
||||||
*
|
// *
|
||||||
* @param filename
|
// * @param filename
|
||||||
* @return
|
// * @return
|
||||||
*/
|
// */
|
||||||
private PrivateKey getPrivateKey(String filename) {
|
// private PrivateKey getPrivateKey(String filename) {
|
||||||
|
//
|
||||||
try {
|
// try {
|
||||||
return PemUtil.loadPrivateKey(new FileInputStream(filename));
|
// return PemUtil.loadPrivateKey(new FileInputStream(filename));
|
||||||
} catch (FileNotFoundException e) {
|
// } catch (FileNotFoundException e) {
|
||||||
throw new RuntimeException("私钥文件不存在", e);
|
// throw new RuntimeException("私钥文件不存在", e);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 获取签名验证器
|
// * 获取签名验证器
|
||||||
*
|
// *
|
||||||
* @return
|
// * @return
|
||||||
*/
|
// */
|
||||||
@Bean
|
// @Bean
|
||||||
public ScheduledUpdateCertificatesVerifier getVerifier() {
|
// public ScheduledUpdateCertificatesVerifier getVerifier() {
|
||||||
|
//
|
||||||
log.info("获取签名验证器");
|
// log.info("获取签名验证器");
|
||||||
|
//
|
||||||
//获取商户私钥
|
// //获取商户私钥
|
||||||
PrivateKey privateKey = getPrivateKey(privateKeyPath);
|
// PrivateKey privateKey = getPrivateKey(privateKeyPath);
|
||||||
|
//
|
||||||
//私钥签名对象
|
// //私钥签名对象
|
||||||
PrivateKeySigner privateKeySigner = new PrivateKeySigner(mchSerialNo, privateKey);
|
// PrivateKeySigner privateKeySigner = new PrivateKeySigner(mchSerialNo, privateKey);
|
||||||
|
//
|
||||||
//身份认证对象
|
// //身份认证对象
|
||||||
WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(mchId, privateKeySigner);
|
// WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(mchId, privateKeySigner);
|
||||||
|
//
|
||||||
// 使用定时更新的签名验证器,不需要传入证书
|
// // 使用定时更新的签名验证器,不需要传入证书
|
||||||
ScheduledUpdateCertificatesVerifier verifier = new ScheduledUpdateCertificatesVerifier(
|
// ScheduledUpdateCertificatesVerifier verifier = new ScheduledUpdateCertificatesVerifier(
|
||||||
wechatPay2Credentials,
|
// wechatPay2Credentials,
|
||||||
apiV3Key.getBytes(StandardCharsets.UTF_8));
|
// apiV3Key.getBytes(StandardCharsets.UTF_8));
|
||||||
|
//
|
||||||
return verifier;
|
// return verifier;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 获取http请求对象
|
// * 获取http请求对象
|
||||||
*
|
// *
|
||||||
* @param verifier
|
// * @param verifier
|
||||||
* @return
|
// * @return
|
||||||
*/
|
// */
|
||||||
@Bean(name = "wxPayClient")
|
// @Bean(name = "wxPayClient")
|
||||||
public CloseableHttpClient getWxPayClient(ScheduledUpdateCertificatesVerifier verifier) {
|
// public CloseableHttpClient getWxPayClient(ScheduledUpdateCertificatesVerifier verifier) {
|
||||||
|
//
|
||||||
log.info("获取httpClient");
|
// log.info("获取httpClient");
|
||||||
|
//
|
||||||
//获取商户私钥
|
// //获取商户私钥
|
||||||
PrivateKey privateKey = getPrivateKey(privateKeyPath);
|
// PrivateKey privateKey = getPrivateKey(privateKeyPath);
|
||||||
|
//
|
||||||
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
|
// WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
|
||||||
.withMerchant(mchId, mchSerialNo, privateKey)
|
// .withMerchant(mchId, mchSerialNo, privateKey)
|
||||||
.withValidator(new WechatPay2Validator(verifier));
|
// .withValidator(new WechatPay2Validator(verifier));
|
||||||
// ... 接下来,你仍然可以通过builder设置各种参数,来配置你的HttpClient
|
// // ... 接下来,你仍然可以通过builder设置各种参数,来配置你的HttpClient
|
||||||
|
//
|
||||||
// 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
|
// // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
|
||||||
CloseableHttpClient httpClient = builder.build();
|
// CloseableHttpClient httpClient = builder.build();
|
||||||
|
//
|
||||||
return httpClient;
|
// return httpClient;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 获取HttpClient,无需进行应答签名验证,跳过验签的流程
|
// * 获取HttpClient,无需进行应答签名验证,跳过验签的流程
|
||||||
*/
|
// */
|
||||||
@Bean(name = "wxPayNoSignClient")
|
// @Bean(name = "wxPayNoSignClient")
|
||||||
public CloseableHttpClient getWxPayNoSignClient() {
|
// public CloseableHttpClient getWxPayNoSignClient() {
|
||||||
|
//
|
||||||
log.info("无需进行应答签名验证,获取httpClient");
|
// log.info("无需进行应答签名验证,获取httpClient");
|
||||||
|
//
|
||||||
|
//
|
||||||
//获取商户私钥
|
// //获取商户私钥
|
||||||
PrivateKey privateKey = getPrivateKey(privateKeyPath);
|
// PrivateKey privateKey = getPrivateKey(privateKeyPath);
|
||||||
|
//
|
||||||
//用于构造HttpClient
|
// //用于构造HttpClient
|
||||||
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
|
// WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
|
||||||
//设置商户信息
|
// //设置商户信息
|
||||||
.withMerchant(mchId, mchSerialNo, privateKey)
|
// .withMerchant(mchId, mchSerialNo, privateKey)
|
||||||
//无需进行签名验证、通过withValidator((response) -> true)实现
|
// //无需进行签名验证、通过withValidator((response) -> true)实现
|
||||||
.withValidator((response) -> true);
|
// .withValidator((response) -> true);
|
||||||
|
//
|
||||||
// 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
|
// // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
|
||||||
CloseableHttpClient httpClient = builder.build();
|
// CloseableHttpClient httpClient = builder.build();
|
||||||
|
//
|
||||||
return httpClient;
|
// return httpClient;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
}
|
//}
|
||||||
|
|
|
@ -1,361 +1,361 @@
|
||||||
package com.cultural.heritage.controller.wxPayDemo;
|
//package com.cultural.heritage.controller.wxPayDemo;
|
||||||
|
//
|
||||||
|
//
|
||||||
import com.google.gson.Gson;
|
//import com.google.gson.Gson;
|
||||||
import jakarta.annotation.Resource;
|
//import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
//import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
//import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
//import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.client.methods.HttpPost;
|
//import org.apache.http.client.methods.HttpPost;
|
||||||
import org.apache.http.entity.StringEntity;
|
//import org.apache.http.entity.StringEntity;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
//import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.util.EntityUtils;
|
//import org.apache.http.util.EntityUtils;
|
||||||
import org.springframework.web.bind.annotation.*;
|
//import org.springframework.web.bind.annotation.*;
|
||||||
|
//
|
||||||
import java.io.IOException;
|
//import java.io.IOException;
|
||||||
import java.util.HashMap;
|
//import java.util.HashMap;
|
||||||
import java.util.Map;
|
//import java.util.Map;
|
||||||
|
//
|
||||||
@RestController
|
//@RestController
|
||||||
@RequestMapping("/api/wx-pay")
|
//@RequestMapping("/api/wx-pay")
|
||||||
@Slf4j
|
//@Slf4j
|
||||||
public class WxPayController {
|
//public class WxPayController {
|
||||||
|
//
|
||||||
@Resource
|
// @Resource
|
||||||
private CloseableHttpClient wxPayClient;
|
// private CloseableHttpClient wxPayClient;
|
||||||
|
//
|
||||||
@Resource
|
// @Resource
|
||||||
//无需应答签名
|
// //无需应答签名
|
||||||
private CloseableHttpClient wxPayNoSignClient;
|
// private CloseableHttpClient wxPayNoSignClient;
|
||||||
|
//
|
||||||
@Resource
|
// @Resource
|
||||||
private WxPayConfig wxPayConfig;
|
// private WxPayConfig wxPayConfig;
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* Native下单
|
// * Native下单
|
||||||
*/
|
// */
|
||||||
@PostMapping("/native")
|
// @PostMapping("/native")
|
||||||
public void nativePay() throws Exception {
|
// public void nativePay() throws Exception {
|
||||||
|
//
|
||||||
log.info("发起支付请求 v3");
|
// log.info("发起支付请求 v3");
|
||||||
|
//
|
||||||
log.info("调用统一下单API");
|
// log.info("调用统一下单API");
|
||||||
|
//
|
||||||
//调用统一下单API
|
// //调用统一下单API
|
||||||
HttpPost httpPost = new HttpPost(wxPayConfig.getDomain().concat(WxApiType.NATIVE_PAY.getType()));
|
// HttpPost httpPost = new HttpPost(wxPayConfig.getDomain().concat(WxApiType.NATIVE_PAY.getType()));
|
||||||
|
//
|
||||||
// 请求body参数
|
// // 请求body参数
|
||||||
Gson gson = new Gson();
|
// Gson gson = new Gson();
|
||||||
HashMap<String, Object> paramsMap = new HashMap<>();
|
// HashMap<String, Object> paramsMap = new HashMap<>();
|
||||||
paramsMap.put("appid", wxPayConfig.getAppid());// APPID
|
// paramsMap.put("appid", wxPayConfig.getAppid());// APPID
|
||||||
paramsMap.put("mchid", wxPayConfig.getMchId());// 商户id
|
// paramsMap.put("mchid", wxPayConfig.getMchId());// 商户id
|
||||||
paramsMap.put("description", "魏凯的小商铺"); // 订单描述
|
// paramsMap.put("description", "魏凯的小商铺"); // 订单描述
|
||||||
paramsMap.put("out_trade_no", "123456789987"); // 订单号
|
// paramsMap.put("out_trade_no", "123456789987"); // 订单号
|
||||||
paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.NATIVE_NOTIFY.getType()));// 二维码扫描支付成功后进行回调
|
// paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.NATIVE_NOTIFY.getType()));// 二维码扫描支付成功后进行回调
|
||||||
|
//
|
||||||
Map<String, Object> amountMap = new HashMap<>();
|
// Map<String, Object> amountMap = new HashMap<>();
|
||||||
amountMap.put("total", 1); // 金额 以分为单位 这里写1分钱 订单号123456789987对应的金额为1分
|
// amountMap.put("total", 1); // 金额 以分为单位 这里写1分钱 订单号123456789987对应的金额为1分
|
||||||
amountMap.put("currency", "CNY");
|
// amountMap.put("currency", "CNY");
|
||||||
|
//
|
||||||
paramsMap.put("amount", amountMap);
|
// paramsMap.put("amount", amountMap);
|
||||||
|
//
|
||||||
//将参数转换成json字符串
|
// //将参数转换成json字符串
|
||||||
String jsonParams = gson.toJson(paramsMap);
|
// String jsonParams = gson.toJson(paramsMap);
|
||||||
log.info("请求参数 ===> {}" + jsonParams);
|
// log.info("请求参数 ===> {}" + jsonParams);
|
||||||
|
//
|
||||||
StringEntity entity = new StringEntity(jsonParams, "utf-8");
|
// StringEntity entity = new StringEntity(jsonParams, "utf-8");
|
||||||
entity.setContentType("application/json");
|
// entity.setContentType("application/json");
|
||||||
httpPost.setEntity(entity);
|
// httpPost.setEntity(entity);
|
||||||
httpPost.setHeader("Accept", "application/json");
|
// httpPost.setHeader("Accept", "application/json");
|
||||||
|
//
|
||||||
//完成签名并执行请求(这个地方就是mchId与商户证书密钥进行校验)
|
// //完成签名并执行请求(这个地方就是mchId与商户证书密钥进行校验)
|
||||||
try (CloseableHttpResponse response = wxPayClient.execute(httpPost)) {
|
// try (CloseableHttpResponse response = wxPayClient.execute(httpPost)) {
|
||||||
String bodyAsString = EntityUtils.toString(response.getEntity());//响应体
|
// String bodyAsString = EntityUtils.toString(response.getEntity());//响应体
|
||||||
int statusCode = response.getStatusLine().getStatusCode();//响应状态码
|
// int statusCode = response.getStatusLine().getStatusCode();//响应状态码
|
||||||
if (statusCode == 200) { //处理成功
|
// if (statusCode == 200) { //处理成功
|
||||||
log.info("成功, 返回结果 = " + bodyAsString);
|
// log.info("成功, 返回结果 = " + bodyAsString);
|
||||||
} else if (statusCode == 204) { //处理成功,无返回Body
|
// } else if (statusCode == 204) { //处理成功,无返回Body
|
||||||
log.info("成功");
|
// log.info("成功");
|
||||||
} else {
|
// } else {
|
||||||
log.info("Native下单失败,响应码 = " + statusCode + ",返回结果 = " + bodyAsString);
|
// log.info("Native下单失败,响应码 = " + statusCode + ",返回结果 = " + bodyAsString);
|
||||||
throw new IOException("request failed");
|
// throw new IOException("request failed");
|
||||||
}
|
// }
|
||||||
//响应结果
|
// //响应结果
|
||||||
HashMap resultMap = gson.fromJson(bodyAsString, HashMap.class);
|
// HashMap resultMap = gson.fromJson(bodyAsString, HashMap.class);
|
||||||
//二维码
|
// //二维码
|
||||||
String codeUrl = (String) resultMap.get("code_url");
|
// String codeUrl = (String) resultMap.get("code_url");
|
||||||
|
//
|
||||||
log.info("二维码为: " + codeUrl);
|
// log.info("二维码为: " + codeUrl);
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 查询订单
|
// * 查询订单
|
||||||
*/
|
// */
|
||||||
@GetMapping("/query/{orderNo}")
|
// @GetMapping("/query/{orderNo}")
|
||||||
public void queryOrder(@PathVariable String orderNo) throws Exception {
|
// public void queryOrder(@PathVariable String orderNo) throws Exception {
|
||||||
|
//
|
||||||
log.info("查询订单");
|
// log.info("查询订单");
|
||||||
|
//
|
||||||
log.info("查单接口调用 ===> {}", orderNo);
|
// log.info("查单接口调用 ===> {}", orderNo);
|
||||||
|
//
|
||||||
// 拼接url
|
// // 拼接url
|
||||||
String url = String.format(WxApiType.ORDER_QUERY_BY_NO.getType(), orderNo);
|
// String url = String.format(WxApiType.ORDER_QUERY_BY_NO.getType(), orderNo);
|
||||||
url = wxPayConfig.getDomain().concat(url).concat("?mchid=").concat(wxPayConfig.getMchId());
|
// url = wxPayConfig.getDomain().concat(url).concat("?mchid=").concat(wxPayConfig.getMchId());
|
||||||
|
//
|
||||||
HttpGet httpGet = new HttpGet(url);
|
// HttpGet httpGet = new HttpGet(url);
|
||||||
httpGet.setHeader("Accept", "application/json");
|
// httpGet.setHeader("Accept", "application/json");
|
||||||
|
//
|
||||||
//完成签名并执行请求
|
// //完成签名并执行请求
|
||||||
try (CloseableHttpResponse response = wxPayClient.execute(httpGet)) {
|
// try (CloseableHttpResponse response = wxPayClient.execute(httpGet)) {
|
||||||
String bodyAsString = EntityUtils.toString(response.getEntity());//响应体
|
// String bodyAsString = EntityUtils.toString(response.getEntity());//响应体
|
||||||
int statusCode = response.getStatusLine().getStatusCode();//响应状态码
|
// int statusCode = response.getStatusLine().getStatusCode();//响应状态码
|
||||||
if (statusCode == 200) { //处理成功
|
// if (statusCode == 200) { //处理成功
|
||||||
log.info("成功, 返回结果 = " + bodyAsString);
|
// log.info("成功, 返回结果 = " + bodyAsString);
|
||||||
} else if (statusCode == 204) { //处理成功,无返回Body
|
// } else if (statusCode == 204) { //处理成功,无返回Body
|
||||||
log.info("成功");
|
// log.info("成功");
|
||||||
} else {
|
// } else {
|
||||||
log.info("查单接口调用,响应码 = " + statusCode + ",返回结果 = " + bodyAsString);
|
// log.info("查单接口调用,响应码 = " + statusCode + ",返回结果 = " + bodyAsString);
|
||||||
throw new IOException("request failed");
|
// throw new IOException("request failed");
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 用户取消订单
|
// * 用户取消订单
|
||||||
*/
|
// */
|
||||||
@PostMapping("/cancel/{orderNo}")
|
// @PostMapping("/cancel/{orderNo}")
|
||||||
public void cancel(@PathVariable String orderNo) throws Exception {
|
// public void cancel(@PathVariable String orderNo) throws Exception {
|
||||||
|
//
|
||||||
log.info("关单接口的调用,订单号 ===> {}", orderNo);
|
// log.info("关单接口的调用,订单号 ===> {}", orderNo);
|
||||||
|
//
|
||||||
//创建远程请求对象
|
// //创建远程请求对象
|
||||||
String url = String.format(WxApiType.CLOSE_ORDER_BY_NO.getType(), orderNo);
|
// String url = String.format(WxApiType.CLOSE_ORDER_BY_NO.getType(), orderNo);
|
||||||
url = wxPayConfig.getDomain().concat(url);
|
// url = wxPayConfig.getDomain().concat(url);
|
||||||
HttpPost httpPost = new HttpPost(url);
|
// HttpPost httpPost = new HttpPost(url);
|
||||||
|
//
|
||||||
//组装json请求体
|
// //组装json请求体
|
||||||
Gson gson = new Gson();
|
// Gson gson = new Gson();
|
||||||
Map<String, String> paramsMap = new HashMap<>();
|
// Map<String, String> paramsMap = new HashMap<>();
|
||||||
paramsMap.put("mchid", wxPayConfig.getMchId());
|
// paramsMap.put("mchid", wxPayConfig.getMchId());
|
||||||
String jsonParams = gson.toJson(paramsMap);
|
// String jsonParams = gson.toJson(paramsMap);
|
||||||
log.info("请求参数 ===> {}", jsonParams);
|
// log.info("请求参数 ===> {}", jsonParams);
|
||||||
|
//
|
||||||
//将请求参数设置到请求对象中
|
// //将请求参数设置到请求对象中
|
||||||
StringEntity entity = new StringEntity(jsonParams, "utf-8");
|
// StringEntity entity = new StringEntity(jsonParams, "utf-8");
|
||||||
entity.setContentType("application/json");
|
// entity.setContentType("application/json");
|
||||||
httpPost.setEntity(entity);
|
// httpPost.setEntity(entity);
|
||||||
httpPost.setHeader("Accept", "application/json");
|
// httpPost.setHeader("Accept", "application/json");
|
||||||
|
//
|
||||||
//完成签名并执行请求
|
// //完成签名并执行请求
|
||||||
try (CloseableHttpResponse response = wxPayClient.execute(httpPost)) {
|
// try (CloseableHttpResponse response = wxPayClient.execute(httpPost)) {
|
||||||
int statusCode = response.getStatusLine().getStatusCode();//响应状态码
|
// int statusCode = response.getStatusLine().getStatusCode();//响应状态码
|
||||||
if (statusCode == 200) { //处理成功
|
// if (statusCode == 200) { //处理成功
|
||||||
log.info("成功200");
|
// log.info("成功200");
|
||||||
} else if (statusCode == 204) { //处理成功,无返回Body
|
// } else if (statusCode == 204) { //处理成功,无返回Body
|
||||||
log.info("成功204");
|
// log.info("成功204");
|
||||||
} else {
|
// } else {
|
||||||
log.info("Native下单失败,响应码 = " + statusCode);
|
// log.info("Native下单失败,响应码 = " + statusCode);
|
||||||
throw new IOException("request failed");
|
// throw new IOException("request failed");
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 用户申请退款
|
// * 用户申请退款
|
||||||
*/
|
// */
|
||||||
@PostMapping("/refunds/{orderNo}")
|
// @PostMapping("/refunds/{orderNo}")
|
||||||
public void refunds(@PathVariable String orderNo) throws Exception {
|
// public void refunds(@PathVariable String orderNo) throws Exception {
|
||||||
|
//
|
||||||
log.info("申请退款");
|
// log.info("申请退款");
|
||||||
log.info("调用退款API");
|
// log.info("调用退款API");
|
||||||
//调用统一下单API
|
// //调用统一下单API
|
||||||
String url = wxPayConfig.getDomain().concat(WxApiType.DOMESTIC_REFUNDS.getType());
|
// String url = wxPayConfig.getDomain().concat(WxApiType.DOMESTIC_REFUNDS.getType());
|
||||||
HttpPost httpPost = new HttpPost(url);
|
// HttpPost httpPost = new HttpPost(url);
|
||||||
|
//
|
||||||
// 请求body参数
|
// // 请求body参数
|
||||||
Gson gson = new Gson();
|
// Gson gson = new Gson();
|
||||||
Map<String, Object> paramsMap = new HashMap<>();
|
// Map<String, Object> paramsMap = new HashMap<>();
|
||||||
paramsMap.put("out_trade_no", orderNo);//订单编号
|
// paramsMap.put("out_trade_no", orderNo);//订单编号
|
||||||
paramsMap.put("out_refund_no", "123456");//退款单编号 随便填
|
// paramsMap.put("out_refund_no", "123456");//退款单编号 随便填
|
||||||
paramsMap.put("reason", "随便填一个");//退款原因
|
// paramsMap.put("reason", "随便填一个");//退款原因
|
||||||
paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.REFUND_NOTIFY.getType()));//退款成功通知地址
|
// paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.REFUND_NOTIFY.getType()));//退款成功通知地址
|
||||||
|
//
|
||||||
Map<String, java.io.Serializable> amountMap = new HashMap<String, java.io.Serializable>();
|
// Map<String, java.io.Serializable> amountMap = new HashMap<String, java.io.Serializable>();
|
||||||
amountMap.put("refund", 1);//退款金额 这里的金额应该根据订单id查询出来
|
// amountMap.put("refund", 1);//退款金额 这里的金额应该根据订单id查询出来
|
||||||
amountMap.put("total", 1);//原订单金额 这里的金额应该根据订单id查询出来
|
// amountMap.put("total", 1);//原订单金额 这里的金额应该根据订单id查询出来
|
||||||
amountMap.put("currency", "CNY");//退款币种
|
// amountMap.put("currency", "CNY");//退款币种
|
||||||
paramsMap.put("amount", amountMap);
|
// paramsMap.put("amount", amountMap);
|
||||||
|
//
|
||||||
//将参数转换成json字符串
|
// //将参数转换成json字符串
|
||||||
String jsonParams = gson.toJson(paramsMap);
|
// String jsonParams = gson.toJson(paramsMap);
|
||||||
log.info("请求参数 ===> {}" + jsonParams);
|
// log.info("请求参数 ===> {}" + jsonParams);
|
||||||
|
//
|
||||||
StringEntity entity = new StringEntity(jsonParams, "utf-8");
|
// StringEntity entity = new StringEntity(jsonParams, "utf-8");
|
||||||
entity.setContentType("application/json");//设置请求报文格式
|
// entity.setContentType("application/json");//设置请求报文格式
|
||||||
httpPost.setEntity(entity);//将请求报文放入请求对象
|
// httpPost.setEntity(entity);//将请求报文放入请求对象
|
||||||
httpPost.setHeader("Accept", "application/json");//设置响应报文格式
|
// httpPost.setHeader("Accept", "application/json");//设置响应报文格式
|
||||||
|
//
|
||||||
//完成签名并执行请求,并完成验签
|
// //完成签名并执行请求,并完成验签
|
||||||
try (CloseableHttpResponse response = wxPayClient.execute(httpPost)) {
|
// try (CloseableHttpResponse response = wxPayClient.execute(httpPost)) {
|
||||||
//解析响应结果
|
// //解析响应结果
|
||||||
String bodyAsString = EntityUtils.toString(response.getEntity());
|
// String bodyAsString = EntityUtils.toString(response.getEntity());
|
||||||
int statusCode = response.getStatusLine().getStatusCode();
|
// int statusCode = response.getStatusLine().getStatusCode();
|
||||||
if (statusCode == 200) {
|
// if (statusCode == 200) {
|
||||||
log.info("成功, 退款返回结果 = " + bodyAsString);
|
// log.info("成功, 退款返回结果 = " + bodyAsString);
|
||||||
} else if (statusCode == 204) {
|
// } else if (statusCode == 204) {
|
||||||
log.info("成功");
|
// log.info("成功");
|
||||||
} else {
|
// } else {
|
||||||
throw new RuntimeException("退款异常, 响应码 = " + statusCode + ", 退款返回结果 = " + bodyAsString);
|
// throw new RuntimeException("退款异常, 响应码 = " + statusCode + ", 退款返回结果 = " + bodyAsString);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 查询退款
|
// * 查询退款
|
||||||
*/
|
// */
|
||||||
@GetMapping("/query-refund/{refundNo}")
|
// @GetMapping("/query-refund/{refundNo}")
|
||||||
public void queryRefund(@PathVariable String refundNo) throws Exception {
|
// public void queryRefund(@PathVariable String refundNo) throws Exception {
|
||||||
|
//
|
||||||
log.info("查询退款");
|
// log.info("查询退款");
|
||||||
log.info("查询退款接口调用 ===> {}", refundNo);
|
// log.info("查询退款接口调用 ===> {}", refundNo);
|
||||||
|
//
|
||||||
String url = String.format(WxApiType.DOMESTIC_REFUNDS_QUERY.getType(), refundNo);
|
// String url = String.format(WxApiType.DOMESTIC_REFUNDS_QUERY.getType(), refundNo);
|
||||||
url = wxPayConfig.getDomain().concat(url);
|
// url = wxPayConfig.getDomain().concat(url);
|
||||||
|
//
|
||||||
//创建远程Get 请求对象
|
// //创建远程Get 请求对象
|
||||||
HttpGet httpGet = new HttpGet(url);
|
// HttpGet httpGet = new HttpGet(url);
|
||||||
httpGet.setHeader("Accept", "application/json");
|
// httpGet.setHeader("Accept", "application/json");
|
||||||
|
//
|
||||||
//完成签名并执行请求
|
// //完成签名并执行请求
|
||||||
try (CloseableHttpResponse response = wxPayClient.execute(httpGet)) {
|
// try (CloseableHttpResponse response = wxPayClient.execute(httpGet)) {
|
||||||
String bodyAsString = EntityUtils.toString(response.getEntity());
|
// String bodyAsString = EntityUtils.toString(response.getEntity());
|
||||||
int statusCode = response.getStatusLine().getStatusCode();
|
// int statusCode = response.getStatusLine().getStatusCode();
|
||||||
if (statusCode == 200) {
|
// if (statusCode == 200) {
|
||||||
log.info("成功, 查询退款返回结果 = " + bodyAsString);
|
// log.info("成功, 查询退款返回结果 = " + bodyAsString);
|
||||||
} else if (statusCode == 204) {
|
// } else if (statusCode == 204) {
|
||||||
log.info("成功");
|
// log.info("成功");
|
||||||
} else {
|
// } else {
|
||||||
throw new RuntimeException("查询退款异常, 响应码 = " + statusCode + ", 查询退款返回结果 = " + bodyAsString);
|
// throw new RuntimeException("查询退款异常, 响应码 = " + statusCode + ", 查询退款返回结果 = " + bodyAsString);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 获取账单url 这个url无法在浏览器打开
|
// * 获取账单url 这个url无法在浏览器打开
|
||||||
*/
|
// */
|
||||||
@GetMapping("/querybill/{billDate}/{type}")
|
// @GetMapping("/querybill/{billDate}/{type}")
|
||||||
public void queryTradeBill(@PathVariable String billDate, @PathVariable String type) throws Exception {
|
// public void queryTradeBill(@PathVariable String billDate, @PathVariable String type) throws Exception {
|
||||||
|
//
|
||||||
log.info("获取账单url");
|
// log.info("获取账单url");
|
||||||
|
//
|
||||||
log.warn("申请账单接口调用 {}", billDate);
|
// log.warn("申请账单接口调用 {}", billDate);
|
||||||
|
//
|
||||||
String url = "";
|
// String url = "";
|
||||||
if ("tradebill".equals(type)) {
|
// if ("tradebill".equals(type)) {
|
||||||
url = WxApiType.TRADE_BILLS.getType();
|
// url = WxApiType.TRADE_BILLS.getType();
|
||||||
} else if ("fundflowbill".equals(type)) {
|
// } else if ("fundflowbill".equals(type)) {
|
||||||
url = WxApiType.FUND_FLOW_BILLS.getType();
|
// url = WxApiType.FUND_FLOW_BILLS.getType();
|
||||||
} else {
|
// } else {
|
||||||
throw new RuntimeException("不支持的账单类型");
|
// throw new RuntimeException("不支持的账单类型");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
url = wxPayConfig.getDomain().concat(url).concat("?bill_date=").concat(billDate);
|
// url = wxPayConfig.getDomain().concat(url).concat("?bill_date=").concat(billDate);
|
||||||
|
//
|
||||||
//创建远程Get 请求对象
|
// //创建远程Get 请求对象
|
||||||
HttpGet httpGet = new HttpGet(url);
|
// HttpGet httpGet = new HttpGet(url);
|
||||||
httpGet.addHeader("Accept", "application/json");
|
// httpGet.addHeader("Accept", "application/json");
|
||||||
|
//
|
||||||
//使用wxPayClient发送请求得到响应
|
// //使用wxPayClient发送请求得到响应
|
||||||
try (CloseableHttpResponse response = wxPayClient.execute(httpGet)) {
|
// try (CloseableHttpResponse response = wxPayClient.execute(httpGet)) {
|
||||||
String bodyAsString = EntityUtils.toString(response.getEntity());
|
// String bodyAsString = EntityUtils.toString(response.getEntity());
|
||||||
|
//
|
||||||
int statusCode = response.getStatusLine().getStatusCode();
|
// int statusCode = response.getStatusLine().getStatusCode();
|
||||||
if (statusCode == 200) {
|
// if (statusCode == 200) {
|
||||||
log.info("成功, 申请账单返回结果 = " + bodyAsString);
|
// log.info("成功, 申请账单返回结果 = " + bodyAsString);
|
||||||
} else if (statusCode == 204) {
|
// } else if (statusCode == 204) {
|
||||||
log.info("成功");
|
// log.info("成功");
|
||||||
} else {
|
// } else {
|
||||||
throw new RuntimeException("申请账单异常, 响应码 = " + statusCode + ", 申请账单返回结果 = " + bodyAsString);
|
// throw new RuntimeException("申请账单异常, 响应码 = " + statusCode + ", 申请账单返回结果 = " + bodyAsString);
|
||||||
}
|
// }
|
||||||
//获取账单下载地址
|
// //获取账单下载地址
|
||||||
Gson gson = new Gson();
|
// Gson gson = new Gson();
|
||||||
Map<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class);
|
// Map<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class);
|
||||||
log.info("账单链接;" + resultMap.get("download_url"));
|
// log.info("账单链接;" + resultMap.get("download_url"));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 下载账单
|
// * 下载账单
|
||||||
*/
|
// */
|
||||||
@GetMapping("/downloadbill/{billDate}/{type}")
|
// @GetMapping("/downloadbill/{billDate}/{type}")
|
||||||
public void downloadBill(@PathVariable String billDate, @PathVariable String type) throws Exception {
|
// public void downloadBill(@PathVariable String billDate, @PathVariable String type) throws Exception {
|
||||||
|
//
|
||||||
log.info("下载账单");
|
// log.info("下载账单");
|
||||||
log.warn("下载账单接口调用 {}, {}", billDate, type);
|
// log.warn("下载账单接口调用 {}, {}", billDate, type);
|
||||||
|
//
|
||||||
//获取账单url地址
|
// //获取账单url地址
|
||||||
String downloadUrl = this.queryBill(billDate, type);
|
// String downloadUrl = this.queryBill(billDate, type);
|
||||||
//创建远程Get 请求对象
|
// //创建远程Get 请求对象
|
||||||
HttpGet httpGet = new HttpGet(downloadUrl);
|
// HttpGet httpGet = new HttpGet(downloadUrl);
|
||||||
httpGet.addHeader("Accept", "application/json");
|
// httpGet.addHeader("Accept", "application/json");
|
||||||
|
//
|
||||||
//使用wxPayClient发送请求得到响应
|
// //使用wxPayClient发送请求得到响应
|
||||||
try (CloseableHttpResponse response = wxPayNoSignClient.execute(httpGet)) {
|
// try (CloseableHttpResponse response = wxPayNoSignClient.execute(httpGet)) {
|
||||||
String bodyAsString = EntityUtils.toString(response.getEntity());
|
// String bodyAsString = EntityUtils.toString(response.getEntity());
|
||||||
int statusCode = response.getStatusLine().getStatusCode();
|
// int statusCode = response.getStatusLine().getStatusCode();
|
||||||
if (statusCode == 200) {
|
// if (statusCode == 200) {
|
||||||
log.info("成功, 下载账单返回结果 = " + bodyAsString);
|
// log.info("成功, 下载账单返回结果 = " + bodyAsString);
|
||||||
} else if (statusCode == 204) {
|
// } else if (statusCode == 204) {
|
||||||
log.info("成功");
|
// log.info("成功");
|
||||||
} else {
|
// } else {
|
||||||
throw new RuntimeException("下载账单异常, 响应码 = " + statusCode + ", 下载账单返回结果 = " + bodyAsString);
|
// throw new RuntimeException("下载账单异常, 响应码 = " + statusCode + ", 下载账单返回结果 = " + bodyAsString);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 申请账单
|
// * 申请账单
|
||||||
*/
|
// */
|
||||||
public String queryBill(String billDate, String type) throws Exception {
|
// public String queryBill(String billDate, String type) throws Exception {
|
||||||
log.warn("申请账单接口调用 {}", billDate);
|
// log.warn("申请账单接口调用 {}", billDate);
|
||||||
|
//
|
||||||
String url = "";
|
// String url = "";
|
||||||
if ("tradebill".equals(type)) {
|
// if ("tradebill".equals(type)) {
|
||||||
url = WxApiType.TRADE_BILLS.getType();
|
// url = WxApiType.TRADE_BILLS.getType();
|
||||||
} else if ("fundflowbill".equals(type)) {
|
// } else if ("fundflowbill".equals(type)) {
|
||||||
url = WxApiType.FUND_FLOW_BILLS.getType();
|
// url = WxApiType.FUND_FLOW_BILLS.getType();
|
||||||
} else {
|
// } else {
|
||||||
throw new RuntimeException("不支持的账单类型");
|
// throw new RuntimeException("不支持的账单类型");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
url = wxPayConfig.getDomain().concat(url).concat("?bill_date=").concat(billDate);
|
// url = wxPayConfig.getDomain().concat(url).concat("?bill_date=").concat(billDate);
|
||||||
|
//
|
||||||
//创建远程Get 请求对象
|
// //创建远程Get 请求对象
|
||||||
HttpGet httpGet = new HttpGet(url);
|
// HttpGet httpGet = new HttpGet(url);
|
||||||
httpGet.addHeader("Accept", "application/json");
|
// httpGet.addHeader("Accept", "application/json");
|
||||||
|
//
|
||||||
//使用wxPayClient发送请求得到响应
|
// //使用wxPayClient发送请求得到响应
|
||||||
try (CloseableHttpResponse response = wxPayClient.execute(httpGet)) {
|
// try (CloseableHttpResponse response = wxPayClient.execute(httpGet)) {
|
||||||
String bodyAsString = EntityUtils.toString(response.getEntity());
|
// String bodyAsString = EntityUtils.toString(response.getEntity());
|
||||||
|
//
|
||||||
int statusCode = response.getStatusLine().getStatusCode();
|
// int statusCode = response.getStatusLine().getStatusCode();
|
||||||
if (statusCode == 200) {
|
// if (statusCode == 200) {
|
||||||
log.info("成功, 申请账单返回结果 = " + bodyAsString);
|
// log.info("成功, 申请账单返回结果 = " + bodyAsString);
|
||||||
} else if (statusCode == 204) {
|
// } else if (statusCode == 204) {
|
||||||
log.info("成功");
|
// log.info("成功");
|
||||||
} else {
|
// } else {
|
||||||
throw new RuntimeException("申请账单异常, 响应码 = " + statusCode + ", 申请账单返回结果 = " + bodyAsString);
|
// throw new RuntimeException("申请账单异常, 响应码 = " + statusCode + ", 申请账单返回结果 = " + bodyAsString);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
//获取账单下载地址
|
// //获取账单下载地址
|
||||||
Gson gson = new Gson();
|
// Gson gson = new Gson();
|
||||||
Map<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class);
|
// Map<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class);
|
||||||
return resultMap.get("download_url");
|
// return resultMap.get("download_url");
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
}
|
//}
|
||||||
|
|
|
@ -1,124 +1,124 @@
|
||||||
package com.cultural.heritage.controller.wxPayDemo;
|
//package com.cultural.heritage.controller.wxPayDemo;
|
||||||
|
//
|
||||||
|
//
|
||||||
import com.google.gson.Gson;
|
//import com.google.gson.Gson;
|
||||||
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
|
//import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
|
||||||
import jakarta.annotation.Resource;
|
//import jakarta.annotation.Resource;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
//import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
//import jakarta.servlet.http.HttpServletResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
//import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
//import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
//import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
//import org.springframework.web.bind.annotation.RestController;
|
||||||
|
//
|
||||||
import java.util.HashMap;
|
//import java.util.HashMap;
|
||||||
import java.util.Map;
|
//import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
//import java.util.concurrent.TimeUnit;
|
||||||
|
//
|
||||||
@RestController
|
//@RestController
|
||||||
@RequestMapping("/api/wx-pay/notify")
|
//@RequestMapping("/api/wx-pay/notify")
|
||||||
@Slf4j
|
//@Slf4j
|
||||||
public class WxPayNotifyController {
|
//public class WxPayNotifyController {
|
||||||
@Resource
|
// @Resource
|
||||||
private Verifier verifier;
|
// private Verifier verifier;
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 订单支付成功回调
|
// * 订单支付成功回调
|
||||||
*/
|
// */
|
||||||
@PostMapping("/native")
|
// @PostMapping("/native")
|
||||||
public String nativeNotify(HttpServletRequest request, HttpServletResponse response) {
|
// public String nativeNotify(HttpServletRequest request, HttpServletResponse response) {
|
||||||
|
//
|
||||||
Gson gson = new Gson();
|
// Gson gson = new Gson();
|
||||||
Map<String, String> map = new HashMap<>();//应答对象
|
// Map<String, String> map = new HashMap<>();//应答对象
|
||||||
|
//
|
||||||
try {
|
// try {
|
||||||
//处理通知参数
|
// //处理通知参数
|
||||||
String body = HttpUtils.readData(request);
|
// String body = HttpUtils.readData(request);
|
||||||
Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
|
// Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
|
||||||
String requestId = (String) bodyMap.get("id");
|
// String requestId = (String) bodyMap.get("id");
|
||||||
log.info("支付通知的id ===> {}", requestId);
|
// log.info("支付通知的id ===> {}", requestId);
|
||||||
|
//
|
||||||
//签名的验证
|
// //签名的验证
|
||||||
WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest
|
// WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest
|
||||||
= new WechatPay2ValidatorForRequest(verifier, requestId, body);
|
// = new WechatPay2ValidatorForRequest(verifier, requestId, body);
|
||||||
if (!wechatPay2ValidatorForRequest.validate(request)) {
|
// if (!wechatPay2ValidatorForRequest.validate(request)) {
|
||||||
|
//
|
||||||
log.error("通知验签失败");
|
// log.error("通知验签失败");
|
||||||
//失败应答
|
// //失败应答
|
||||||
response.setStatus(500);
|
// response.setStatus(500);
|
||||||
map.put("code", "ERROR");
|
// map.put("code", "ERROR");
|
||||||
map.put("message", "通知验签失败");
|
// map.put("message", "通知验签失败");
|
||||||
return gson.toJson(map);
|
// return gson.toJson(map);
|
||||||
}
|
// }
|
||||||
log.info("通知验签成功");
|
// log.info("通知验签成功");
|
||||||
|
//
|
||||||
//处理订单 这里可以对订单进行处理 比如订单支付成功 修改数据库订单表订单状态为已支付
|
// //处理订单 这里可以对订单进行处理 比如订单支付成功 修改数据库订单表订单状态为已支付
|
||||||
// processOrder(bodyMap);
|
//// processOrder(bodyMap);
|
||||||
|
//
|
||||||
//应答超时
|
// //应答超时
|
||||||
//模拟接收微信端的重复通知
|
// //模拟接收微信端的重复通知
|
||||||
TimeUnit.SECONDS.sleep(5);
|
// TimeUnit.SECONDS.sleep(5);
|
||||||
|
//
|
||||||
//成功应答
|
// //成功应答
|
||||||
response.setStatus(200);
|
// response.setStatus(200);
|
||||||
map.put("code", "SUCCESS");
|
// map.put("code", "SUCCESS");
|
||||||
map.put("message", "成功");
|
// map.put("message", "成功");
|
||||||
return gson.toJson(map);
|
// return gson.toJson(map);
|
||||||
|
//
|
||||||
} catch (Exception e) {
|
// } catch (Exception e) {
|
||||||
e.printStackTrace();
|
// e.printStackTrace();
|
||||||
//失败应答
|
// //失败应答
|
||||||
response.setStatus(500);
|
// response.setStatus(500);
|
||||||
map.put("code", "ERROR");
|
// map.put("code", "ERROR");
|
||||||
map.put("message", "失败");
|
// map.put("message", "失败");
|
||||||
return gson.toJson(map);
|
// return gson.toJson(map);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@PostMapping("/refunds")
|
// @PostMapping("/refunds")
|
||||||
public String refundsNotify(HttpServletRequest request, HttpServletResponse response){
|
// public String refundsNotify(HttpServletRequest request, HttpServletResponse response){
|
||||||
|
//
|
||||||
log.info("退款通知执行");
|
// log.info("退款通知执行");
|
||||||
Gson gson = new Gson();
|
// Gson gson = new Gson();
|
||||||
Map<String, String> map = new HashMap<>();//应答对象
|
// Map<String, String> map = new HashMap<>();//应答对象
|
||||||
|
//
|
||||||
try {
|
// try {
|
||||||
//处理通知参数
|
// //处理通知参数
|
||||||
String body = HttpUtils.readData(request);
|
// String body = HttpUtils.readData(request);
|
||||||
Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
|
// Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
|
||||||
String requestId = (String)bodyMap.get("id");
|
// String requestId = (String)bodyMap.get("id");
|
||||||
log.info("支付通知的id ===> {}", requestId);
|
// log.info("支付通知的id ===> {}", requestId);
|
||||||
|
//
|
||||||
//签名的验证
|
// //签名的验证
|
||||||
WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest
|
// WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest
|
||||||
= new WechatPay2ValidatorForRequest(verifier, requestId, body);
|
// = new WechatPay2ValidatorForRequest(verifier, requestId, body);
|
||||||
if(!wechatPay2ValidatorForRequest.validate(request)){
|
// if(!wechatPay2ValidatorForRequest.validate(request)){
|
||||||
|
//
|
||||||
log.error("通知验签失败");
|
// log.error("通知验签失败");
|
||||||
//失败应答
|
// //失败应答
|
||||||
response.setStatus(500);
|
// response.setStatus(500);
|
||||||
map.put("code", "ERROR");
|
// map.put("code", "ERROR");
|
||||||
map.put("message", "通知验签失败");
|
// map.put("message", "通知验签失败");
|
||||||
return gson.toJson(map);
|
// return gson.toJson(map);
|
||||||
}
|
// }
|
||||||
log.info("通知验签成功");
|
// log.info("通知验签成功");
|
||||||
|
//
|
||||||
//处理退款单 订单退款成功 修改订单表中订单状态为已退款
|
// //处理退款单 订单退款成功 修改订单表中订单状态为已退款
|
||||||
// processRefund(bodyMap);
|
//// processRefund(bodyMap);
|
||||||
|
//
|
||||||
//成功应答
|
// //成功应答
|
||||||
response.setStatus(200);
|
// response.setStatus(200);
|
||||||
map.put("code", "SUCCESS");
|
// map.put("code", "SUCCESS");
|
||||||
map.put("message", "成功");
|
// map.put("message", "成功");
|
||||||
return gson.toJson(map);
|
// return gson.toJson(map);
|
||||||
|
//
|
||||||
} catch (Exception e) {
|
// } catch (Exception e) {
|
||||||
e.printStackTrace();
|
// e.printStackTrace();
|
||||||
//失败应答
|
// //失败应答
|
||||||
response.setStatus(500);
|
// response.setStatus(500);
|
||||||
map.put("code", "ERROR");
|
// map.put("code", "ERROR");
|
||||||
map.put("message", "失败");
|
// map.put("message", "失败");
|
||||||
return gson.toJson(map);
|
// return gson.toJson(map);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user