diff --git a/pom.xml b/pom.xml
index 327420a..c523c8b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -178,12 +178,20 @@
+
+
+
+
+
+
+
com.github.wechatpay-apiv3
- wechatpay-java
- 0.2.10
+ wechatpay-apache-httpclient
+ 0.3.0
+
diff --git a/src/main/java/com/cultural/heritage/config/WxPayConfig.java b/src/main/java/com/cultural/heritage/config/WxPayConfig.java
index 338b774..87306ad 100644
--- a/src/main/java/com/cultural/heritage/config/WxPayConfig.java
+++ b/src/main/java/com/cultural/heritage/config/WxPayConfig.java
@@ -1,78 +1,78 @@
-package com.cultural.heritage.config;
-
-import com.wechat.pay.java.core.RSAAutoCertificateConfig;
-import com.wechat.pay.java.core.util.IOUtil;
-import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
-import com.wechat.pay.java.service.refund.RefundService;
-import lombok.Data;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.stereotype.Component;
-
-import java.io.IOException;
-
-@Data
-@Slf4j
-@Configuration
-@Component("WxPayConfig")
-@ConfigurationProperties(prefix = "wx.pay")
-public class WxPayConfig {
-
- private String appId;
-
- private String apiV3Key;
-
- private String notifyUrl;
-
- private String merchantId;
-
- private String privateKeyPath;
-
- private String merchantSerialNumber;
-
- // RSA配置
- private RSAAutoCertificateConfig RSAConfig;
-
- // JSAPI支付
- private JsapiServiceExtension jsapiServiceExtension;
-
- // 退款
- private RefundService refundService;
-
- /**
- * 初始化配置
- */
- @Bean
- public boolean initWxPayConfig() throws IOException {
- this.RSAConfig = buildRSAAutoCertificateConfig();
- this.jsapiServiceExtension = buildJsapiServiceExtension(RSAConfig);
- this.refundService = buildRefundService(RSAConfig);
- return true;
- }
-
- // 构建并使用自动更新平台证书的RSA配置,一个商户号只能初始化一个配置,否则会因为重复的下载任务报错
- private RSAAutoCertificateConfig buildRSAAutoCertificateConfig() throws IOException {
- // 将 resource 目录下的文件转为 InputStream,然后利用 IOUtil.toString(inputStream) 转化为密钥
- String privateKey = IOUtil.toString(new ClassPathResource(privateKeyPath).getInputStream());
- return new RSAAutoCertificateConfig.Builder()
- .merchantId(merchantId)
- .privateKey(privateKey)
- .merchantSerialNumber(merchantSerialNumber)
- .apiV3Key(apiV3Key)
- .build();
- }
-
- // 构建JSAPI支付
- private JsapiServiceExtension buildJsapiServiceExtension(RSAAutoCertificateConfig config) {
- return new JsapiServiceExtension.Builder().config(config).build();
- }
-
- // 构建退款
- private RefundService buildRefundService(RSAAutoCertificateConfig config) {
- return new RefundService.Builder().config(config).build();
- }
-
-}
+//package com.cultural.heritage.config;
+//
+//import com.wechat.pay.java.core.RSAAutoCertificateConfig;
+//import com.wechat.pay.java.core.util.IOUtil;
+//import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
+//import com.wechat.pay.java.service.refund.RefundService;
+//import lombok.Data;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.boot.context.properties.ConfigurationProperties;
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.core.io.ClassPathResource;
+//import org.springframework.stereotype.Component;
+//
+//import java.io.IOException;
+//
+//@Data
+//@Slf4j
+//@Configuration
+//@Component("WxPayConfig")
+//@ConfigurationProperties(prefix = "wx.pay")
+//public class WxPayConfig {
+//
+// private String appId;
+//
+// private String apiV3Key;
+//
+// private String notifyUrl;
+//
+// private String merchantId;
+//
+// private String privateKeyPath;
+//
+// private String merchantSerialNumber;
+//
+// // RSA配置
+// private RSAAutoCertificateConfig RSAConfig;
+//
+// // JSAPI支付
+// private JsapiServiceExtension jsapiServiceExtension;
+//
+// // 退款
+// private RefundService refundService;
+//
+// /**
+// * 初始化配置
+// */
+// @Bean
+// public boolean initWxPayConfig() throws IOException {
+// this.RSAConfig = buildRSAAutoCertificateConfig();
+// this.jsapiServiceExtension = buildJsapiServiceExtension(RSAConfig);
+// this.refundService = buildRefundService(RSAConfig);
+// return true;
+// }
+//
+// // 构建并使用自动更新平台证书的RSA配置,一个商户号只能初始化一个配置,否则会因为重复的下载任务报错
+// private RSAAutoCertificateConfig buildRSAAutoCertificateConfig() throws IOException {
+// // 将 resource 目录下的文件转为 InputStream,然后利用 IOUtil.toString(inputStream) 转化为密钥
+// String privateKey = IOUtil.toString(new ClassPathResource(privateKeyPath).getInputStream());
+// return new RSAAutoCertificateConfig.Builder()
+// .merchantId(merchantId)
+// .privateKey(privateKey)
+// .merchantSerialNumber(merchantSerialNumber)
+// .apiV3Key(apiV3Key)
+// .build();
+// }
+//
+// // 构建JSAPI支付
+// private JsapiServiceExtension buildJsapiServiceExtension(RSAAutoCertificateConfig config) {
+// return new JsapiServiceExtension.Builder().config(config).build();
+// }
+//
+// // 构建退款
+// private RefundService buildRefundService(RSAAutoCertificateConfig config) {
+// return new RefundService.Builder().config(config).build();
+// }
+//
+//}
diff --git a/src/main/java/com/cultural/heritage/controller/good/AppointmentDateController.java b/src/main/java/com/cultural/heritage/controller/good/AppointmentDateController.java
index 54eb20f..6ed598e 100644
--- a/src/main/java/com/cultural/heritage/controller/good/AppointmentDateController.java
+++ b/src/main/java/com/cultural/heritage/controller/good/AppointmentDateController.java
@@ -160,7 +160,7 @@ public class AppointmentDateController {
@Operation(summary = "Web端管理员添加预约时间段", description = "参数:预约时间段添加请求体,权限:管理员(admin, boss),方法名:addAppointmentDate")
@Transactional(rollbackFor = Exception.class)
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
- public BaseResponse addTimePeriod(@RequestBody TimePeriodSingleAddRequest timePeriodSingleAddRequest) {
+ public BaseResponse addTimePeriod(@RequestBody TimePeriodSingleAddRequest timePeriodSingleAddRequest) {
if (timePeriodSingleAddRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
@@ -168,7 +168,7 @@ public class AppointmentDateController {
BeanUtils.copyProperties(timePeriodSingleAddRequest, timePeriod);
boolean save = timePeriodService.save(timePeriod);
ThrowUtils.throwIf(!save, ErrorCode.OPERATION_ERROR, "预约时间段添加失败");
- return ResultUtils.success(true);
+ return ResultUtils.success(timePeriod.getId());
}
diff --git a/src/main/java/com/cultural/heritage/controller/wx/WeChatPayController.java b/src/main/java/com/cultural/heritage/controller/wx/WeChatPayController.java
index f80ff1d..35fa36e 100644
--- a/src/main/java/com/cultural/heritage/controller/wx/WeChatPayController.java
+++ b/src/main/java/com/cultural/heritage/controller/wx/WeChatPayController.java
@@ -1,120 +1,120 @@
-package com.cultural.heritage.controller.wx;
-
-
-import com.cultural.heritage.annotation.AuthCheck;
-import com.cultural.heritage.common.BaseResponse;
-import com.cultural.heritage.common.ErrorCode;
-import com.cultural.heritage.common.ResultUtils;
-import com.cultural.heritage.constant.UserConstant;
-import com.cultural.heritage.exception.BusinessException;
-import com.cultural.heritage.exception.ThrowUtils;
-import com.cultural.heritage.model.dto.CommonRequest;
-import com.cultural.heritage.model.entity.Order;
-import com.cultural.heritage.model.entity.User;
-import com.cultural.heritage.service.order.OrderService;
-import com.cultural.heritage.service.user.UserService;
-import com.cultural.heritage.service.wxpay.WeChatService;
-import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
-import com.wechat.pay.java.service.payments.model.Transaction;
-import com.wechat.pay.java.service.refund.model.Refund;
-import com.wechat.pay.java.service.refund.model.RefundNotification;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import jakarta.annotation.Resource;
-import jakarta.servlet.http.HttpServletRequest;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.bind.annotation.*;
-
-import java.io.IOException;
-
-/**
- * 微信小程序相关接口
- **/
-@Slf4j
-@RestController
-@Tag(name = "微信支付接口")
-@RequestMapping("/wechat")
-public class WeChatPayController {
-
- @Resource
- private UserService userService;
-
- @Resource
- private OrderService ordersService;
-
- @Resource
- private WeChatService weChatService;
-
-
- /**
- * JSAPI 下单
- */
- @PostMapping("/payment/create")
- public BaseResponse createPayment(@RequestBody CommonRequest commonRequest, HttpServletRequest request) {
- User loginUser = userService.getLoginUser(request);
- String miniOpenId = loginUser.getMiniOpenId();
- ThrowUtils.throwIf(miniOpenId == null, ErrorCode.NOT_FOUND_ERROR, "不是小程序用户");
- Long orderId = commonRequest.getId();
- Order order = ordersService.getById(orderId);
- ThrowUtils.throwIf(order == null, ErrorCode.NOT_FOUND_ERROR, "订单不存在");
-// ThrowUtils.throwIf(order.getState() != 0, ErrorCode.OPERATION_ERROR, "订单状态错误");
- if (!loginUser.getId().equals(order.getUserId())) {
- throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "你不是该订单用户!");
- }
- PrepayWithRequestPaymentResponse response = weChatService.createPayment(String.valueOf(orderId), miniOpenId, order.getTotalAmount());
- return ResultUtils.success(response);
- }
-
- /**
- * JSAPI 下单回调
- */
- @PostMapping("/payment/callback")
- @Transactional(rollbackFor = Exception.class)
- public synchronized BaseResponse callbackPayment(HttpServletRequest request) throws IOException {
- // 获取下单信息
- Transaction transaction = weChatService.getTransactionInfo(request);
- System.out.println("下单信息:" + transaction);
- // 支付回调
- boolean result = weChatService.paymentCallback(transaction);
- ThrowUtils.throwIf(!result, ErrorCode.SYSTEM_ERROR, "微信支付回调失败");
- return ResultUtils.success(true);
- }
-
- /**
- * 退款(仅管理员和商家)
- */
- @PostMapping("/refund/create")
- @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
- public BaseResponse createRefund(@RequestBody CommonRequest commonRequest) {
- Long orderId = commonRequest.getId();
- Order order = ordersService.getById(orderId);
- ThrowUtils.throwIf(order == null, ErrorCode.NOT_FOUND_ERROR, "订单不存在");
- Refund refund = weChatService.refundPayment(String.valueOf(orderId), order.getTotalAmount());
- return ResultUtils.success(refund);
- }
-
- /**
- * 退款回调
- */
- @PostMapping("/refund/callback")
- public BaseResponse callbackRefund(HttpServletRequest request) {
- // 获取退款信息
- RefundNotification refundNotification = weChatService.getRefundInfo(request);
- // 退款回调
- boolean result = weChatService.refundCallback(refundNotification);
- ThrowUtils.throwIf(!result, ErrorCode.SYSTEM_ERROR, "退款回调失败");
- return ResultUtils.success(true);
- }
-
- /**
- * 发送订阅消息
- */
- @GetMapping("/refund/callback")
- public BaseResponse testSendMessage() {
- String miniOpenId = "o0o_B5CMLFiOs96dJZwtkyHcJzcM";
- String templateId = "MK13FfX0XxsPV6m1vi6J8_8Bf7JT8rsayFs9q3f4FW4";
- boolean subscribeMessage = weChatService.sendSubscribeMessage(miniOpenId, templateId);
- return ResultUtils.success(subscribeMessage);
- }
-
-}
+//package com.cultural.heritage.controller.wx;
+//
+//
+//import com.cultural.heritage.annotation.AuthCheck;
+//import com.cultural.heritage.common.BaseResponse;
+//import com.cultural.heritage.common.ErrorCode;
+//import com.cultural.heritage.common.ResultUtils;
+//import com.cultural.heritage.constant.UserConstant;
+//import com.cultural.heritage.exception.BusinessException;
+//import com.cultural.heritage.exception.ThrowUtils;
+//import com.cultural.heritage.model.dto.CommonRequest;
+//import com.cultural.heritage.model.entity.Order;
+//import com.cultural.heritage.model.entity.User;
+//import com.cultural.heritage.service.order.OrderService;
+//import com.cultural.heritage.service.user.UserService;
+//import com.cultural.heritage.service.wxpay.WeChatService;
+//import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
+//import com.wechat.pay.java.service.payments.model.Transaction;
+//import com.wechat.pay.java.service.refund.model.Refund;
+//import com.wechat.pay.java.service.refund.model.RefundNotification;
+//import io.swagger.v3.oas.annotations.tags.Tag;
+//import jakarta.annotation.Resource;
+//import jakarta.servlet.http.HttpServletRequest;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.transaction.annotation.Transactional;
+//import org.springframework.web.bind.annotation.*;
+//
+//import java.io.IOException;
+//
+///**
+// * 微信小程序相关接口
+// **/
+//@Slf4j
+//@RestController
+//@Tag(name = "微信支付接口")
+//@RequestMapping("/wechat")
+//public class WeChatPayController {
+//
+// @Resource
+// private UserService userService;
+//
+// @Resource
+// private OrderService ordersService;
+//
+// @Resource
+// private WeChatService weChatService;
+//
+//
+// /**
+// * JSAPI 下单
+// */
+// @PostMapping("/payment/create")
+// public BaseResponse createPayment(@RequestBody CommonRequest commonRequest, HttpServletRequest request) {
+// User loginUser = userService.getLoginUser(request);
+// String miniOpenId = loginUser.getMiniOpenId();
+// ThrowUtils.throwIf(miniOpenId == null, ErrorCode.NOT_FOUND_ERROR, "不是小程序用户");
+// Long orderId = commonRequest.getId();
+// Order order = ordersService.getById(orderId);
+// ThrowUtils.throwIf(order == null, ErrorCode.NOT_FOUND_ERROR, "订单不存在");
+//// ThrowUtils.throwIf(order.getState() != 0, ErrorCode.OPERATION_ERROR, "订单状态错误");
+// if (!loginUser.getId().equals(order.getUserId())) {
+// throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "你不是该订单用户!");
+// }
+// PrepayWithRequestPaymentResponse response = weChatService.createPayment(String.valueOf(orderId), miniOpenId, order.getTotalAmount());
+// return ResultUtils.success(response);
+// }
+//
+// /**
+// * JSAPI 下单回调
+// */
+// @PostMapping("/payment/callback")
+// @Transactional(rollbackFor = Exception.class)
+// public synchronized BaseResponse callbackPayment(HttpServletRequest request) throws IOException {
+// // 获取下单信息
+// Transaction transaction = weChatService.getTransactionInfo(request);
+// System.out.println("下单信息:" + transaction);
+// // 支付回调
+// boolean result = weChatService.paymentCallback(transaction);
+// ThrowUtils.throwIf(!result, ErrorCode.SYSTEM_ERROR, "微信支付回调失败");
+// return ResultUtils.success(true);
+// }
+//
+// /**
+// * 退款(仅管理员和商家)
+// */
+// @PostMapping("/refund/create")
+// @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
+// public BaseResponse createRefund(@RequestBody CommonRequest commonRequest) {
+// Long orderId = commonRequest.getId();
+// Order order = ordersService.getById(orderId);
+// ThrowUtils.throwIf(order == null, ErrorCode.NOT_FOUND_ERROR, "订单不存在");
+// Refund refund = weChatService.refundPayment(String.valueOf(orderId), order.getTotalAmount());
+// return ResultUtils.success(refund);
+// }
+//
+// /**
+// * 退款回调
+// */
+// @PostMapping("/refund/callback")
+// public BaseResponse callbackRefund(HttpServletRequest request) {
+// // 获取退款信息
+// RefundNotification refundNotification = weChatService.getRefundInfo(request);
+// // 退款回调
+// boolean result = weChatService.refundCallback(refundNotification);
+// ThrowUtils.throwIf(!result, ErrorCode.SYSTEM_ERROR, "退款回调失败");
+// return ResultUtils.success(true);
+// }
+//
+// /**
+// * 发送订阅消息
+// */
+// @GetMapping("/refund/callback")
+// public BaseResponse testSendMessage() {
+// String miniOpenId = "o0o_B5CMLFiOs96dJZwtkyHcJzcM";
+// String templateId = "MK13FfX0XxsPV6m1vi6J8_8Bf7JT8rsayFs9q3f4FW4";
+// boolean subscribeMessage = weChatService.sendSubscribeMessage(miniOpenId, templateId);
+// return ResultUtils.success(subscribeMessage);
+// }
+//
+//}
diff --git a/src/main/java/com/cultural/heritage/controller/wxPayDemo/HttpUtils.java b/src/main/java/com/cultural/heritage/controller/wxPayDemo/HttpUtils.java
new file mode 100644
index 0000000..d9e3bf7
--- /dev/null
+++ b/src/main/java/com/cultural/heritage/controller/wxPayDemo/HttpUtils.java
@@ -0,0 +1,43 @@
+package com.cultural.heritage.controller.wxPayDemo;
+
+
+import jakarta.servlet.http.HttpServletRequest;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+
+/**
+ * @author weikai
+ */
+public class HttpUtils {
+
+ /**
+ * 将通知参数转化为字符串
+ * @param request
+ * @return
+ */
+ public static String readData(HttpServletRequest request) {
+ BufferedReader br = null;
+ try {
+ StringBuilder result = new StringBuilder();
+ br = request.getReader();
+ for (String line; (line = br.readLine()) != null; ) {
+ if (result.length() > 0) {
+ result.append("\n");
+ }
+ result.append(line);
+ }
+ return result.toString();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (br != null) {
+ try {
+ br.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/cultural/heritage/controller/wxPayDemo/WechatPay2ValidatorForRequest.java b/src/main/java/com/cultural/heritage/controller/wxPayDemo/WechatPay2ValidatorForRequest.java
new file mode 100644
index 0000000..fc57693
--- /dev/null
+++ b/src/main/java/com/cultural/heritage/controller/wxPayDemo/WechatPay2ValidatorForRequest.java
@@ -0,0 +1,110 @@
+package com.cultural.heritage.controller.wxPayDemo;
+
+
+import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
+import jakarta.servlet.http.HttpServletRequest;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.time.DateTimeException;
+import java.time.Duration;
+import java.time.Instant;
+
+import static com.wechat.pay.contrib.apache.httpclient.constant.WechatPayHttpHeaders.*;
+
+public class WechatPay2ValidatorForRequest {
+
+ protected static final Logger log = LoggerFactory.getLogger(WechatPay2ValidatorForRequest.class);
+ /**
+ * 应答超时时间,单位为分钟
+ */
+ protected static final long RESPONSE_EXPIRED_MINUTES = 5;
+ protected final Verifier verifier;
+ protected final String requestId;
+ protected final String body;
+
+
+ public WechatPay2ValidatorForRequest(Verifier verifier, String requestId, String body) {
+ this.verifier = verifier;
+ this.requestId = requestId;
+ this.body = body;
+ }
+
+ protected static IllegalArgumentException parameterError(String message, Object... args) {
+ message = String.format(message, args);
+ return new IllegalArgumentException("parameter error: " + message);
+ }
+
+ protected static IllegalArgumentException verifyFail(String message, Object... args) {
+ message = String.format(message, args);
+ return new IllegalArgumentException("signature verify fail: " + message);
+ }
+
+ public final boolean validate(HttpServletRequest request) throws IOException {
+ try {
+ //处理请求参数
+ validateParameters(request);
+
+ //构造验签名串
+ String message = buildMessage(request);
+
+ String serial = request.getHeader(WECHAT_PAY_SERIAL);
+ String signature = request.getHeader(WECHAT_PAY_SIGNATURE);
+
+ //验签
+ if (!verifier.verify(serial, message.getBytes(StandardCharsets.UTF_8), signature)) {
+ throw verifyFail("serial=[%s] message=[%s] sign=[%s], request-id=[%s]",
+ serial, message, signature, requestId);
+ }
+ } catch (IllegalArgumentException e) {
+ log.warn(e.getMessage());
+ return false;
+ }
+
+ return true;
+ }
+
+ protected final void validateParameters(HttpServletRequest request) {
+
+ // NOTE: ensure HEADER_WECHAT_PAY_TIMESTAMP at last
+ String[] headers = {WECHAT_PAY_SERIAL, WECHAT_PAY_SIGNATURE, WECHAT_PAY_NONCE, WECHAT_PAY_TIMESTAMP};
+
+ String header = null;
+ for (String headerName : headers) {
+ header = request.getHeader(headerName);
+ if (header == null) {
+ throw parameterError("empty [%s], request-id=[%s]", headerName, requestId);
+ }
+ }
+
+ //判断请求是否过期
+ String timestampStr = header;
+ try {
+ Instant responseTime = Instant.ofEpochSecond(Long.parseLong(timestampStr));
+ // 拒绝过期请求
+ if (Duration.between(responseTime, Instant.now()).abs().toMinutes() >= RESPONSE_EXPIRED_MINUTES) {
+ throw parameterError("timestamp=[%s] expires, request-id=[%s]", timestampStr, requestId);
+ }
+ } catch (DateTimeException | NumberFormatException e) {
+ throw parameterError("invalid timestamp=[%s], request-id=[%s]", timestampStr, requestId);
+ }
+ }
+
+ protected final String buildMessage(HttpServletRequest request) throws IOException {
+ String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
+ String nonce = request.getHeader(WECHAT_PAY_NONCE);
+ return timestamp + "\n"
+ + nonce + "\n"
+ + body + "\n";
+ }
+
+ protected final String getResponseBody(CloseableHttpResponse response) throws IOException {
+ HttpEntity entity = response.getEntity();
+ return (entity != null && entity.isRepeatable()) ? EntityUtils.toString(entity) : "";
+ }
+}
diff --git a/src/main/java/com/cultural/heritage/controller/wxPayDemo/WxApiType.java b/src/main/java/com/cultural/heritage/controller/wxPayDemo/WxApiType.java
new file mode 100644
index 0000000..314aeec
--- /dev/null
+++ b/src/main/java/com/cultural/heritage/controller/wxPayDemo/WxApiType.java
@@ -0,0 +1,55 @@
+package com.cultural.heritage.controller.wxPayDemo;
+
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+@Getter
+public enum WxApiType {
+
+ /**
+ *
+ */
+
+ /**
+ * Native下单
+ */
+ NATIVE_PAY("/v3/pay/transactions/native"),
+
+ /**
+ * 查询订单
+ */
+ ORDER_QUERY_BY_NO("/v3/pay/transactions/out-trade-no/%s"),
+
+ /**
+ * 关闭订单
+ */
+ CLOSE_ORDER_BY_NO("/v3/pay/transactions/out-trade-no/%s/close"),
+
+ /**
+ * 申请退款
+ */
+ DOMESTIC_REFUNDS("/v3/refund/domestic/refunds"),
+
+ /**
+ * 查询单笔退款
+ */
+ DOMESTIC_REFUNDS_QUERY("/v3/refund/domestic/refunds/%s"),
+
+ /**
+ * 申请交易账单
+ */
+ TRADE_BILLS("/v3/bill/tradebill"),
+
+ /**
+ * 申请资金账单
+ */
+ FUND_FLOW_BILLS("/v3/bill/fundflowbill");
+
+
+ /**
+ * 类型
+ */
+ private final String type;
+}
diff --git a/src/main/java/com/cultural/heritage/controller/wxPayDemo/WxNotifyType.java b/src/main/java/com/cultural/heritage/controller/wxPayDemo/WxNotifyType.java
new file mode 100644
index 0000000..44dfa26
--- /dev/null
+++ b/src/main/java/com/cultural/heritage/controller/wxPayDemo/WxNotifyType.java
@@ -0,0 +1,26 @@
+package com.cultural.heritage.controller.wxPayDemo;
+
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+@Getter
+public enum WxNotifyType {
+
+ /**
+ * 支付通知
+ */
+ NATIVE_NOTIFY("/api/wx-pay/notify/native"),
+
+
+ /**
+ * 退款结果通知
+ */
+ REFUND_NOTIFY("/api/wx-pay/notify/refunds");
+
+ /**
+ * 类型
+ */
+ private final String type;
+}
diff --git a/src/main/java/com/cultural/heritage/controller/wxPayDemo/WxPayConfig.java b/src/main/java/com/cultural/heritage/controller/wxPayDemo/WxPayConfig.java
new file mode 100644
index 0000000..ca711a3
--- /dev/null
+++ b/src/main/java/com/cultural/heritage/controller/wxPayDemo/WxPayConfig.java
@@ -0,0 +1,142 @@
+package com.cultural.heritage.controller.wxPayDemo;
+
+
+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.ScheduledUpdateCertificatesVerifier;
+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.util.PemUtil;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.nio.charset.StandardCharsets;
+import java.security.PrivateKey;
+
+@Configuration
+@ConfigurationProperties(prefix = "wx.pay") //读取wxpay节点
+@Data //使用set方法将wxpay节点中的值填充到当前类的属性中
+@Slf4j
+public class WxPayConfig {
+
+ // 商户号
+ private String mchId;
+
+ // 商户API证书序列号
+ private String mchSerialNo;
+
+ // 商户私钥文件
+ private String privateKeyPath;
+
+ // APIv3密钥
+ private String apiV3Key;
+
+ // APPID
+ private String appid;
+
+ // 微信服务器地址
+ private String domain;
+
+ // 接收结果通知地址
+ private String notifyDomain;
+
+
+ /**
+ * 获取商户的私钥文件
+ *
+ * @param filename
+ * @return
+ */
+ private PrivateKey getPrivateKey(String filename) {
+
+ try {
+ return PemUtil.loadPrivateKey(new FileInputStream(filename));
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException("私钥文件不存在", e);
+ }
+ }
+
+ /**
+ * 获取签名验证器
+ *
+ * @return
+ */
+ @Bean
+ public ScheduledUpdateCertificatesVerifier getVerifier() {
+
+ log.info("获取签名验证器");
+
+ //获取商户私钥
+ PrivateKey privateKey = getPrivateKey(privateKeyPath);
+
+ //私钥签名对象
+ PrivateKeySigner privateKeySigner = new PrivateKeySigner(mchSerialNo, privateKey);
+
+ //身份认证对象
+ WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(mchId, privateKeySigner);
+
+ // 使用定时更新的签名验证器,不需要传入证书
+ ScheduledUpdateCertificatesVerifier verifier = new ScheduledUpdateCertificatesVerifier(
+ wechatPay2Credentials,
+ apiV3Key.getBytes(StandardCharsets.UTF_8));
+
+ return verifier;
+ }
+
+ /**
+ * 获取http请求对象
+ *
+ * @param verifier
+ * @return
+ */
+ @Bean(name = "wxPayClient")
+ public CloseableHttpClient getWxPayClient(ScheduledUpdateCertificatesVerifier verifier) {
+
+ log.info("获取httpClient");
+
+ //获取商户私钥
+ PrivateKey privateKey = getPrivateKey(privateKeyPath);
+
+ WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
+ .withMerchant(mchId, mchSerialNo, privateKey)
+ .withValidator(new WechatPay2Validator(verifier));
+ // ... 接下来,你仍然可以通过builder设置各种参数,来配置你的HttpClient
+
+ // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
+ CloseableHttpClient httpClient = builder.build();
+
+ return httpClient;
+ }
+
+ /**
+ * 获取HttpClient,无需进行应答签名验证,跳过验签的流程
+ */
+ @Bean(name = "wxPayNoSignClient")
+ public CloseableHttpClient getWxPayNoSignClient() {
+
+ log.info("无需进行应答签名验证,获取httpClient");
+
+
+ //获取商户私钥
+ PrivateKey privateKey = getPrivateKey(privateKeyPath);
+
+ //用于构造HttpClient
+ WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
+ //设置商户信息
+ .withMerchant(mchId, mchSerialNo, privateKey)
+ //无需进行签名验证、通过withValidator((response) -> true)实现
+ .withValidator((response) -> true);
+
+ // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
+ CloseableHttpClient httpClient = builder.build();
+
+ return httpClient;
+ }
+
+}
diff --git a/src/main/java/com/cultural/heritage/controller/wxPayDemo/WxPayController.java b/src/main/java/com/cultural/heritage/controller/wxPayDemo/WxPayController.java
new file mode 100644
index 0000000..95f470b
--- /dev/null
+++ b/src/main/java/com/cultural/heritage/controller/wxPayDemo/WxPayController.java
@@ -0,0 +1,361 @@
+package com.cultural.heritage.controller.wxPayDemo;
+
+
+import com.google.gson.Gson;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.util.EntityUtils;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/api/wx-pay")
+@Slf4j
+public class WxPayController {
+
+ @Resource
+ private CloseableHttpClient wxPayClient;
+
+ @Resource
+ //无需应答签名
+ private CloseableHttpClient wxPayNoSignClient;
+
+ @Resource
+ private WxPayConfig wxPayConfig;
+
+ /**
+ * Native下单
+ */
+ @PostMapping("/native")
+ public void nativePay() throws Exception {
+
+ log.info("发起支付请求 v3");
+
+ log.info("调用统一下单API");
+
+ //调用统一下单API
+ HttpPost httpPost = new HttpPost(wxPayConfig.getDomain().concat(WxApiType.NATIVE_PAY.getType()));
+
+ // 请求body参数
+ Gson gson = new Gson();
+ HashMap paramsMap = new HashMap<>();
+ paramsMap.put("appid", wxPayConfig.getAppid());// APPID
+ paramsMap.put("mchid", wxPayConfig.getMchId());// 商户id
+ paramsMap.put("description", "魏凯的小商铺"); // 订单描述
+ paramsMap.put("out_trade_no", "123456789987"); // 订单号
+ paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.NATIVE_NOTIFY.getType()));// 二维码扫描支付成功后进行回调
+
+ Map amountMap = new HashMap<>();
+ amountMap.put("total", 1); // 金额 以分为单位 这里写1分钱 订单号123456789987对应的金额为1分
+ amountMap.put("currency", "CNY");
+
+ paramsMap.put("amount", amountMap);
+
+ //将参数转换成json字符串
+ String jsonParams = gson.toJson(paramsMap);
+ log.info("请求参数 ===> {}" + jsonParams);
+
+ StringEntity entity = new StringEntity(jsonParams, "utf-8");
+ entity.setContentType("application/json");
+ httpPost.setEntity(entity);
+ httpPost.setHeader("Accept", "application/json");
+
+ //完成签名并执行请求(这个地方就是mchId与商户证书密钥进行校验)
+ try (CloseableHttpResponse response = wxPayClient.execute(httpPost)) {
+ String bodyAsString = EntityUtils.toString(response.getEntity());//响应体
+ int statusCode = response.getStatusLine().getStatusCode();//响应状态码
+ if (statusCode == 200) { //处理成功
+ log.info("成功, 返回结果 = " + bodyAsString);
+ } else if (statusCode == 204) { //处理成功,无返回Body
+ log.info("成功");
+ } else {
+ log.info("Native下单失败,响应码 = " + statusCode + ",返回结果 = " + bodyAsString);
+ throw new IOException("request failed");
+ }
+ //响应结果
+ HashMap resultMap = gson.fromJson(bodyAsString, HashMap.class);
+ //二维码
+ String codeUrl = (String) resultMap.get("code_url");
+
+ log.info("二维码为: " + codeUrl);
+
+ }
+ }
+
+ /**
+ * 查询订单
+ */
+ @GetMapping("/query/{orderNo}")
+ public void queryOrder(@PathVariable String orderNo) throws Exception {
+
+ log.info("查询订单");
+
+ log.info("查单接口调用 ===> {}", orderNo);
+
+ // 拼接url
+ String url = String.format(WxApiType.ORDER_QUERY_BY_NO.getType(), orderNo);
+ url = wxPayConfig.getDomain().concat(url).concat("?mchid=").concat(wxPayConfig.getMchId());
+
+ HttpGet httpGet = new HttpGet(url);
+ httpGet.setHeader("Accept", "application/json");
+
+ //完成签名并执行请求
+ try (CloseableHttpResponse response = wxPayClient.execute(httpGet)) {
+ String bodyAsString = EntityUtils.toString(response.getEntity());//响应体
+ int statusCode = response.getStatusLine().getStatusCode();//响应状态码
+ if (statusCode == 200) { //处理成功
+ log.info("成功, 返回结果 = " + bodyAsString);
+ } else if (statusCode == 204) { //处理成功,无返回Body
+ log.info("成功");
+ } else {
+ log.info("查单接口调用,响应码 = " + statusCode + ",返回结果 = " + bodyAsString);
+ throw new IOException("request failed");
+ }
+ }
+ }
+
+
+ /**
+ * 用户取消订单
+ */
+ @PostMapping("/cancel/{orderNo}")
+ public void cancel(@PathVariable String orderNo) throws Exception {
+
+ log.info("关单接口的调用,订单号 ===> {}", orderNo);
+
+ //创建远程请求对象
+ String url = String.format(WxApiType.CLOSE_ORDER_BY_NO.getType(), orderNo);
+ url = wxPayConfig.getDomain().concat(url);
+ HttpPost httpPost = new HttpPost(url);
+
+ //组装json请求体
+ Gson gson = new Gson();
+ Map paramsMap = new HashMap<>();
+ paramsMap.put("mchid", wxPayConfig.getMchId());
+ String jsonParams = gson.toJson(paramsMap);
+ log.info("请求参数 ===> {}", jsonParams);
+
+ //将请求参数设置到请求对象中
+ StringEntity entity = new StringEntity(jsonParams, "utf-8");
+ entity.setContentType("application/json");
+ httpPost.setEntity(entity);
+ httpPost.setHeader("Accept", "application/json");
+
+ //完成签名并执行请求
+ try (CloseableHttpResponse response = wxPayClient.execute(httpPost)) {
+ int statusCode = response.getStatusLine().getStatusCode();//响应状态码
+ if (statusCode == 200) { //处理成功
+ log.info("成功200");
+ } else if (statusCode == 204) { //处理成功,无返回Body
+ log.info("成功204");
+ } else {
+ log.info("Native下单失败,响应码 = " + statusCode);
+ throw new IOException("request failed");
+ }
+ }
+ }
+
+ /**
+ * 用户申请退款
+ */
+ @PostMapping("/refunds/{orderNo}")
+ public void refunds(@PathVariable String orderNo) throws Exception {
+
+ log.info("申请退款");
+ log.info("调用退款API");
+ //调用统一下单API
+ String url = wxPayConfig.getDomain().concat(WxApiType.DOMESTIC_REFUNDS.getType());
+ HttpPost httpPost = new HttpPost(url);
+
+ // 请求body参数
+ Gson gson = new Gson();
+ Map paramsMap = new HashMap<>();
+ paramsMap.put("out_trade_no", orderNo);//订单编号
+ paramsMap.put("out_refund_no", "123456");//退款单编号 随便填
+ paramsMap.put("reason", "随便填一个");//退款原因
+ paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.REFUND_NOTIFY.getType()));//退款成功通知地址
+
+ Map amountMap = new HashMap();
+ amountMap.put("refund", 1);//退款金额 这里的金额应该根据订单id查询出来
+ amountMap.put("total", 1);//原订单金额 这里的金额应该根据订单id查询出来
+ amountMap.put("currency", "CNY");//退款币种
+ paramsMap.put("amount", amountMap);
+
+ //将参数转换成json字符串
+ String jsonParams = gson.toJson(paramsMap);
+ log.info("请求参数 ===> {}" + jsonParams);
+
+ StringEntity entity = new StringEntity(jsonParams, "utf-8");
+ entity.setContentType("application/json");//设置请求报文格式
+ httpPost.setEntity(entity);//将请求报文放入请求对象
+ httpPost.setHeader("Accept", "application/json");//设置响应报文格式
+
+ //完成签名并执行请求,并完成验签
+ try (CloseableHttpResponse response = wxPayClient.execute(httpPost)) {
+ //解析响应结果
+ String bodyAsString = EntityUtils.toString(response.getEntity());
+ int statusCode = response.getStatusLine().getStatusCode();
+ if (statusCode == 200) {
+ log.info("成功, 退款返回结果 = " + bodyAsString);
+ } else if (statusCode == 204) {
+ log.info("成功");
+ } else {
+ throw new RuntimeException("退款异常, 响应码 = " + statusCode + ", 退款返回结果 = " + bodyAsString);
+ }
+ }
+ }
+
+ /**
+ * 查询退款
+ */
+ @GetMapping("/query-refund/{refundNo}")
+ public void queryRefund(@PathVariable String refundNo) throws Exception {
+
+ log.info("查询退款");
+ log.info("查询退款接口调用 ===> {}", refundNo);
+
+ String url = String.format(WxApiType.DOMESTIC_REFUNDS_QUERY.getType(), refundNo);
+ url = wxPayConfig.getDomain().concat(url);
+
+ //创建远程Get 请求对象
+ HttpGet httpGet = new HttpGet(url);
+ httpGet.setHeader("Accept", "application/json");
+
+ //完成签名并执行请求
+ try (CloseableHttpResponse response = wxPayClient.execute(httpGet)) {
+ String bodyAsString = EntityUtils.toString(response.getEntity());
+ int statusCode = response.getStatusLine().getStatusCode();
+ if (statusCode == 200) {
+ log.info("成功, 查询退款返回结果 = " + bodyAsString);
+ } else if (statusCode == 204) {
+ log.info("成功");
+ } else {
+ throw new RuntimeException("查询退款异常, 响应码 = " + statusCode + ", 查询退款返回结果 = " + bodyAsString);
+ }
+ }
+ }
+
+ /**
+ * 获取账单url 这个url无法在浏览器打开
+ */
+ @GetMapping("/querybill/{billDate}/{type}")
+ public void queryTradeBill(@PathVariable String billDate, @PathVariable String type) throws Exception {
+
+ log.info("获取账单url");
+
+ log.warn("申请账单接口调用 {}", billDate);
+
+ String url = "";
+ if ("tradebill".equals(type)) {
+ url = WxApiType.TRADE_BILLS.getType();
+ } else if ("fundflowbill".equals(type)) {
+ url = WxApiType.FUND_FLOW_BILLS.getType();
+ } else {
+ throw new RuntimeException("不支持的账单类型");
+ }
+
+ url = wxPayConfig.getDomain().concat(url).concat("?bill_date=").concat(billDate);
+
+ //创建远程Get 请求对象
+ HttpGet httpGet = new HttpGet(url);
+ httpGet.addHeader("Accept", "application/json");
+
+ //使用wxPayClient发送请求得到响应
+ try (CloseableHttpResponse response = wxPayClient.execute(httpGet)) {
+ String bodyAsString = EntityUtils.toString(response.getEntity());
+
+ int statusCode = response.getStatusLine().getStatusCode();
+ if (statusCode == 200) {
+ log.info("成功, 申请账单返回结果 = " + bodyAsString);
+ } else if (statusCode == 204) {
+ log.info("成功");
+ } else {
+ throw new RuntimeException("申请账单异常, 响应码 = " + statusCode + ", 申请账单返回结果 = " + bodyAsString);
+ }
+ //获取账单下载地址
+ Gson gson = new Gson();
+ Map resultMap = gson.fromJson(bodyAsString, HashMap.class);
+ log.info("账单链接;" + resultMap.get("download_url"));
+ }
+ }
+
+ /**
+ * 下载账单
+ */
+ @GetMapping("/downloadbill/{billDate}/{type}")
+ public void downloadBill(@PathVariable String billDate, @PathVariable String type) throws Exception {
+
+ log.info("下载账单");
+ log.warn("下载账单接口调用 {}, {}", billDate, type);
+
+ //获取账单url地址
+ String downloadUrl = this.queryBill(billDate, type);
+ //创建远程Get 请求对象
+ HttpGet httpGet = new HttpGet(downloadUrl);
+ httpGet.addHeader("Accept", "application/json");
+
+ //使用wxPayClient发送请求得到响应
+ try (CloseableHttpResponse response = wxPayNoSignClient.execute(httpGet)) {
+ String bodyAsString = EntityUtils.toString(response.getEntity());
+ int statusCode = response.getStatusLine().getStatusCode();
+ if (statusCode == 200) {
+ log.info("成功, 下载账单返回结果 = " + bodyAsString);
+ } else if (statusCode == 204) {
+ log.info("成功");
+ } else {
+ throw new RuntimeException("下载账单异常, 响应码 = " + statusCode + ", 下载账单返回结果 = " + bodyAsString);
+ }
+ }
+
+ }
+
+ /**
+ * 申请账单
+ */
+ public String queryBill(String billDate, String type) throws Exception {
+ log.warn("申请账单接口调用 {}", billDate);
+
+ String url = "";
+ if ("tradebill".equals(type)) {
+ url = WxApiType.TRADE_BILLS.getType();
+ } else if ("fundflowbill".equals(type)) {
+ url = WxApiType.FUND_FLOW_BILLS.getType();
+ } else {
+ throw new RuntimeException("不支持的账单类型");
+ }
+
+ url = wxPayConfig.getDomain().concat(url).concat("?bill_date=").concat(billDate);
+
+ //创建远程Get 请求对象
+ HttpGet httpGet = new HttpGet(url);
+ httpGet.addHeader("Accept", "application/json");
+
+ //使用wxPayClient发送请求得到响应
+ try (CloseableHttpResponse response = wxPayClient.execute(httpGet)) {
+ String bodyAsString = EntityUtils.toString(response.getEntity());
+
+ int statusCode = response.getStatusLine().getStatusCode();
+ if (statusCode == 200) {
+ log.info("成功, 申请账单返回结果 = " + bodyAsString);
+ } else if (statusCode == 204) {
+ log.info("成功");
+ } else {
+ throw new RuntimeException("申请账单异常, 响应码 = " + statusCode + ", 申请账单返回结果 = " + bodyAsString);
+ }
+
+ //获取账单下载地址
+ Gson gson = new Gson();
+ Map resultMap = gson.fromJson(bodyAsString, HashMap.class);
+ return resultMap.get("download_url");
+ }
+ }
+
+}
diff --git a/src/main/java/com/cultural/heritage/controller/wxPayDemo/WxPayNotifyController.java b/src/main/java/com/cultural/heritage/controller/wxPayDemo/WxPayNotifyController.java
new file mode 100644
index 0000000..6d6abb6
--- /dev/null
+++ b/src/main/java/com/cultural/heritage/controller/wxPayDemo/WxPayNotifyController.java
@@ -0,0 +1,124 @@
+package com.cultural.heritage.controller.wxPayDemo;
+
+
+import com.google.gson.Gson;
+import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+@RestController
+@RequestMapping("/api/wx-pay/notify")
+@Slf4j
+public class WxPayNotifyController {
+ @Resource
+ private Verifier verifier;
+
+ /**
+ * 订单支付成功回调
+ */
+ @PostMapping("/native")
+ public String nativeNotify(HttpServletRequest request, HttpServletResponse response) {
+
+ Gson gson = new Gson();
+ Map map = new HashMap<>();//应答对象
+
+ try {
+ //处理通知参数
+ String body = HttpUtils.readData(request);
+ Map bodyMap = gson.fromJson(body, HashMap.class);
+ String requestId = (String) bodyMap.get("id");
+ log.info("支付通知的id ===> {}", requestId);
+
+ //签名的验证
+ WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest
+ = new WechatPay2ValidatorForRequest(verifier, requestId, body);
+ if (!wechatPay2ValidatorForRequest.validate(request)) {
+
+ log.error("通知验签失败");
+ //失败应答
+ response.setStatus(500);
+ map.put("code", "ERROR");
+ map.put("message", "通知验签失败");
+ return gson.toJson(map);
+ }
+ log.info("通知验签成功");
+
+ //处理订单 这里可以对订单进行处理 比如订单支付成功 修改数据库订单表订单状态为已支付
+// processOrder(bodyMap);
+
+ //应答超时
+ //模拟接收微信端的重复通知
+ TimeUnit.SECONDS.sleep(5);
+
+ //成功应答
+ response.setStatus(200);
+ map.put("code", "SUCCESS");
+ map.put("message", "成功");
+ return gson.toJson(map);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ //失败应答
+ response.setStatus(500);
+ map.put("code", "ERROR");
+ map.put("message", "失败");
+ return gson.toJson(map);
+ }
+ }
+
+ @PostMapping("/refunds")
+ public String refundsNotify(HttpServletRequest request, HttpServletResponse response){
+
+ log.info("退款通知执行");
+ Gson gson = new Gson();
+ Map map = new HashMap<>();//应答对象
+
+ try {
+ //处理通知参数
+ String body = HttpUtils.readData(request);
+ Map bodyMap = gson.fromJson(body, HashMap.class);
+ String requestId = (String)bodyMap.get("id");
+ log.info("支付通知的id ===> {}", requestId);
+
+ //签名的验证
+ WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest
+ = new WechatPay2ValidatorForRequest(verifier, requestId, body);
+ if(!wechatPay2ValidatorForRequest.validate(request)){
+
+ log.error("通知验签失败");
+ //失败应答
+ response.setStatus(500);
+ map.put("code", "ERROR");
+ map.put("message", "通知验签失败");
+ return gson.toJson(map);
+ }
+ log.info("通知验签成功");
+
+ //处理退款单 订单退款成功 修改订单表中订单状态为已退款
+// processRefund(bodyMap);
+
+ //成功应答
+ response.setStatus(200);
+ map.put("code", "SUCCESS");
+ map.put("message", "成功");
+ return gson.toJson(map);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ //失败应答
+ response.setStatus(500);
+ map.put("code", "ERROR");
+ map.put("message", "失败");
+ return gson.toJson(map);
+ }
+ }
+}
diff --git a/src/main/java/com/cultural/heritage/service/wxpay/WeChatService.java b/src/main/java/com/cultural/heritage/service/wxpay/WeChatService.java
index b163dad..304854b 100644
--- a/src/main/java/com/cultural/heritage/service/wxpay/WeChatService.java
+++ b/src/main/java/com/cultural/heritage/service/wxpay/WeChatService.java
@@ -1,53 +1,53 @@
-package com.cultural.heritage.service.wxpay;
-
-
-import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
-import com.wechat.pay.java.service.payments.model.Transaction;
-import com.wechat.pay.java.service.refund.model.Refund;
-import com.wechat.pay.java.service.refund.model.RefundNotification;
-import jakarta.servlet.http.HttpServletRequest;
-
-import java.io.IOException;
-import java.math.BigDecimal;
-
-/**
- * @author 玄德
- */
-public interface WeChatService {
-
- /**
- * 微信支付
- */
- PrepayWithRequestPaymentResponse createPayment(String orderId, String miniOpenId, BigDecimal amount);
-
- /**
- * 获取支付回调信息
- */
- Transaction getTransactionInfo(HttpServletRequest request);
-
- /**
- * 支付回调
- */
- boolean paymentCallback(Transaction transaction) throws IOException;
-
- /**
- * 退款申请
- */
- Refund refundPayment(String orderId, BigDecimal amount);
-
- /**
- * 获取退款回调信息
- */
- RefundNotification getRefundInfo(HttpServletRequest request);
-
- /**
- * 退款回调
- */
- boolean refundCallback(RefundNotification refundNotification);
-
- /**
- * 发送订阅模板消息
- */
- boolean sendSubscribeMessage(String openid, String templateId);
-
-}
+//package com.cultural.heritage.service.wxpay;
+//
+//
+//import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
+//import com.wechat.pay.java.service.payments.model.Transaction;
+//import com.wechat.pay.java.service.refund.model.Refund;
+//import com.wechat.pay.java.service.refund.model.RefundNotification;
+//import jakarta.servlet.http.HttpServletRequest;
+//
+//import java.io.IOException;
+//import java.math.BigDecimal;
+//
+///**
+// * @author 玄德
+// */
+//public interface WeChatService {
+//
+// /**
+// * 微信支付
+// */
+// PrepayWithRequestPaymentResponse createPayment(String orderId, String miniOpenId, BigDecimal amount);
+//
+// /**
+// * 获取支付回调信息
+// */
+// Transaction getTransactionInfo(HttpServletRequest request);
+//
+// /**
+// * 支付回调
+// */
+// boolean paymentCallback(Transaction transaction) throws IOException;
+//
+// /**
+// * 退款申请
+// */
+// Refund refundPayment(String orderId, BigDecimal amount);
+//
+// /**
+// * 获取退款回调信息
+// */
+// RefundNotification getRefundInfo(HttpServletRequest request);
+//
+// /**
+// * 退款回调
+// */
+// boolean refundCallback(RefundNotification refundNotification);
+//
+// /**
+// * 发送订阅模板消息
+// */
+// boolean sendSubscribeMessage(String openid, String templateId);
+//
+//}
diff --git a/src/main/java/com/cultural/heritage/service/wxpay/impl/WeChatServiceImpl.java b/src/main/java/com/cultural/heritage/service/wxpay/impl/WeChatServiceImpl.java
index fe1bcbb..d5a5cd8 100644
--- a/src/main/java/com/cultural/heritage/service/wxpay/impl/WeChatServiceImpl.java
+++ b/src/main/java/com/cultural/heritage/service/wxpay/impl/WeChatServiceImpl.java
@@ -1,265 +1,265 @@
-package com.cultural.heritage.service.wxpay.impl;
-
-
-import cn.binarywang.wx.miniapp.api.WxMaMsgService;
-import cn.binarywang.wx.miniapp.api.WxMaService;
-import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
-import cn.hutool.core.util.RandomUtil;
-import com.cultural.heritage.common.ErrorCode;
-import com.cultural.heritage.config.WxOpenConfig;
-import com.cultural.heritage.config.WxPayConfig;
-import com.cultural.heritage.exception.BusinessException;
-import com.cultural.heritage.model.entity.Order;
-import com.cultural.heritage.service.order.OrderService;
-import com.cultural.heritage.service.wxpay.WeChatService;
-import com.wechat.pay.java.core.notification.NotificationParser;
-import com.wechat.pay.java.core.notification.RequestParam;
-import com.wechat.pay.java.service.payments.jsapi.model.Amount;
-import com.wechat.pay.java.service.payments.jsapi.model.Payer;
-import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
-import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
-import com.wechat.pay.java.service.payments.model.Transaction;
-import com.wechat.pay.java.service.refund.model.AmountReq;
-import com.wechat.pay.java.service.refund.model.CreateRequest;
-import com.wechat.pay.java.service.refund.model.Refund;
-import com.wechat.pay.java.service.refund.model.RefundNotification;
-import jakarta.annotation.Resource;
-import jakarta.servlet.http.HttpServletRequest;
-import lombok.SneakyThrows;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author 玄德
- */
-@Slf4j
-@Service
-public class WeChatServiceImpl implements WeChatService {
-
- @Resource
- private WxPayConfig wxPayConfig;
-
- @Resource
- private WxOpenConfig wxOpenConfig;
-
- @Resource
- private OrderService ordersService;
-
- /**
- * 请求参数
- */
- public static RequestParam requestParam = null;
-
- @Override
- @Transactional(rollbackFor = Exception.class)
- public synchronized PrepayWithRequestPaymentResponse createPayment(String orderId, String miniOpenId, BigDecimal amount) {
- // request.setXxx(val)设置所需参数,具体参数可见Request定义
- PrepayRequest request = new PrepayRequest();
- // 金额
- Amount WxAmount = new Amount();
- WxAmount.setTotal(amount.movePointRight(2).intValue());
- WxAmount.setCurrency("CNY");
- request.setAmount(WxAmount);
- // 公众号id
- request.setAppid(wxPayConfig.getAppId());
- // 商户号
- request.setMchid(wxPayConfig.getMerchantId());
- // 支付者信息
- Payer payer = new Payer();
- payer.setOpenid(miniOpenId);
- request.setPayer(payer);
- // 描述
- request.setDescription("订单号:" + orderId);
- // 微信回调地址
- request.setNotifyUrl(wxPayConfig.getNotifyUrl() + "/api/wechat/payment/callback");
- // 商户订单号
- request.setOutTradeNo(RandomUtil.randomNumbers(12));
- //返回数据,前端调起支付
- return wxPayConfig.getJsapiServiceExtension().prepayWithRequestPayment(request);
- }
-
- @Override
- public Transaction getTransactionInfo(HttpServletRequest request) {
- NotificationParser notificationParser = getNotificationParser(request);
- return notificationParser.parse(requestParam, Transaction.class);
- }
-
- @Override
- @Transactional(rollbackFor = Exception.class)
- public synchronized boolean paymentCallback(Transaction transaction) throws IOException {
- System.out.println("---------------------------微信支付回调(开始)-------------------------------");
- // 获取订单信息
- String orderIdByString = transaction.getOutTradeNo();
- Order order = ordersService.getById(orderIdByString);
- if (order == null) {
- log.error("订单不存在");
- throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "订单不存在,订单号:" + transaction.getOutTradeNo());
- }
- // 生成取餐码
- // 获取当日的日期
- LocalDate today = LocalDate.now();
- // 获取当日的 00:00 时间
- LocalDateTime startTime = today.atStartOfDay();
- // 获取当日的 23:59 时间
- LocalDateTime endTime = today.atTime(LocalTime.MAX);
+//package com.cultural.heritage.service.wxpay.impl;
+//
+//
+//import cn.binarywang.wx.miniapp.api.WxMaMsgService;
+//import cn.binarywang.wx.miniapp.api.WxMaService;
+//import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
+//import cn.hutool.core.util.RandomUtil;
+//import com.cultural.heritage.common.ErrorCode;
+//import com.cultural.heritage.config.WxOpenConfig;
+//import com.cultural.heritage.config.WxPayConfig;
+//import com.cultural.heritage.exception.BusinessException;
+//import com.cultural.heritage.model.entity.Order;
+//import com.cultural.heritage.service.order.OrderService;
+//import com.cultural.heritage.service.wxpay.WeChatService;
+//import com.wechat.pay.java.core.notification.NotificationParser;
+//import com.wechat.pay.java.core.notification.RequestParam;
+//import com.wechat.pay.java.service.payments.jsapi.model.Amount;
+//import com.wechat.pay.java.service.payments.jsapi.model.Payer;
+//import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
+//import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
+//import com.wechat.pay.java.service.payments.model.Transaction;
+//import com.wechat.pay.java.service.refund.model.AmountReq;
+//import com.wechat.pay.java.service.refund.model.CreateRequest;
+//import com.wechat.pay.java.service.refund.model.Refund;
+//import com.wechat.pay.java.service.refund.model.RefundNotification;
+//import jakarta.annotation.Resource;
+//import jakarta.servlet.http.HttpServletRequest;
+//import lombok.SneakyThrows;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.stereotype.Service;
+//import org.springframework.transaction.annotation.Transactional;
+//
+//import java.io.BufferedReader;
+//import java.io.IOException;
+//import java.math.BigDecimal;
+//import java.time.LocalDate;
+//import java.time.LocalDateTime;
+//import java.time.LocalTime;
+//import java.util.ArrayList;
+//import java.util.List;
+//
+///**
+// * @author 玄德
+// */
+//@Slf4j
+//@Service
+//public class WeChatServiceImpl implements WeChatService {
+//
+// @Resource
+// private WxPayConfig wxPayConfig;
+//
+// @Resource
+// private WxOpenConfig wxOpenConfig;
+//
+// @Resource
+// private OrderService ordersService;
+//
+// /**
+// * 请求参数
+// */
+// public static RequestParam requestParam = null;
+//
+// @Override
+// @Transactional(rollbackFor = Exception.class)
+// public synchronized PrepayWithRequestPaymentResponse createPayment(String orderId, String miniOpenId, BigDecimal amount) {
+// // request.setXxx(val)设置所需参数,具体参数可见Request定义
+// PrepayRequest request = new PrepayRequest();
+// // 金额
+// Amount WxAmount = new Amount();
+// WxAmount.setTotal(amount.movePointRight(2).intValue());
+// WxAmount.setCurrency("CNY");
+// request.setAmount(WxAmount);
+// // 公众号id
+// request.setAppid(wxPayConfig.getAppId());
+// // 商户号
+// request.setMchid(wxPayConfig.getMerchantId());
+// // 支付者信息
+// Payer payer = new Payer();
+// payer.setOpenid(miniOpenId);
+// request.setPayer(payer);
+// // 描述
+// request.setDescription("订单号:" + orderId);
+// // 微信回调地址
+// request.setNotifyUrl(wxPayConfig.getNotifyUrl() + "/api/wechat/payment/callback");
+// // 商户订单号
+// request.setOutTradeNo(RandomUtil.randomNumbers(12));
+// //返回数据,前端调起支付
+// return wxPayConfig.getJsapiServiceExtension().prepayWithRequestPayment(request);
+// }
+//
+// @Override
+// public Transaction getTransactionInfo(HttpServletRequest request) {
+// NotificationParser notificationParser = getNotificationParser(request);
+// return notificationParser.parse(requestParam, Transaction.class);
+// }
+//
+// @Override
+// @Transactional(rollbackFor = Exception.class)
+// public synchronized boolean paymentCallback(Transaction transaction) throws IOException {
+// System.out.println("---------------------------微信支付回调(开始)-------------------------------");
+// // 获取订单信息
+// String orderIdByString = transaction.getOutTradeNo();
+// Order order = ordersService.getById(orderIdByString);
+// if (order == null) {
+// log.error("订单不存在");
+// throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "订单不存在,订单号:" + transaction.getOutTradeNo());
+// }
// // 生成取餐码
-// QueryWrapper queryWrapper = new QueryWrapper<>();
-// queryWrapper.eq("businessId", order.getBusinessId());
-// queryWrapper.between("createTime", startTime, endTime);
-// queryWrapper.in("state", 1, 2);
-// long count = ordersService.count(queryWrapper);
-// String pickupCode = String.format("%04d", count + 1);
+// // 获取当日的日期
+// LocalDate today = LocalDate.now();
+// // 获取当日的 00:00 时间
+// LocalDateTime startTime = today.atStartOfDay();
+// // 获取当日的 23:59 时间
+// LocalDateTime endTime = today.atTime(LocalTime.MAX);
+//// // 生成取餐码
+//// QueryWrapper queryWrapper = new QueryWrapper<>();
+//// queryWrapper.eq("businessId", order.getBusinessId());
+//// queryWrapper.between("createTime", startTime, endTime);
+//// queryWrapper.in("state", 1, 2);
+//// long count = ordersService.count(queryWrapper);
+//// String pickupCode = String.format("%04d", count + 1);
+//// // 修改订单信息
+//// order.setState(1);
+//// order.setPickupCode(pickupCode);
+//// Date date = new Date();
+//// order.setUpdateTime(date);
+//// boolean update = ordersService.updateById(order);
+//// ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "修改订单状态失败");
+//// // 通知商家新订单
+//// Business business = businessService.getById(order.getBusinessId());
+//// Long userId = order.getUserId();
+//// Long businessId = business.getUserId();
+//// MessageVO messageVO = new MessageVO();
+//// messageVO.setType(1);
+//// messageVO.setUserId(userId);
+//// messageVO.setToUserId(businessId);
+//// messageVO.setContent(orderIdByString);
+//// String message = JSONUtil.toJsonStr(messageVO);
+//// // 通知商家新订单
+//// webSocketServer.onMessage(message);
+// System.out.println("---------------------------微信支付回调(结束)-------------------------------");
+// return true;
+// }
+//
+// @Override
+// public Refund refundPayment(String orderId, BigDecimal amount) {
+// // 退款请求
+// CreateRequest createRequest = new CreateRequest();
+// // 商户订单号
+// createRequest.setOutTradeNo(orderId);
+// // 商户退款单号
+// createRequest.setOutRefundNo(orderId);
+// // 退款结果回调
+// createRequest.setNotifyUrl(wxPayConfig.getNotifyUrl() + "/api/wechat/refund/callback");
+// // 退款金额
+// AmountReq amountReq = new AmountReq();
+// long refundAmount = amount.movePointRight(2).intValue();
+// amountReq.setRefund(refundAmount);
+// amountReq.setTotal(refundAmount);
+// amountReq.setCurrency("CNY");
+// createRequest.setAmount(amountReq);
+// // 申请退款
+// System.out.println("退款请求:" + createRequest);
+// Refund refund = wxPayConfig.getRefundService().create(createRequest);
+// System.out.println("退款申请结果:" + refund);
+// return refund;
+// }
+//
+// @Override
+// public RefundNotification getRefundInfo(HttpServletRequest request) {
+// NotificationParser notificationParser = getNotificationParser(request);
+// return notificationParser.parse(requestParam, RefundNotification.class);
+// }
+//
+// @Override
+// @Transactional(rollbackFor = Exception.class)
+// public synchronized boolean refundCallback(RefundNotification refundNotification) {
+// System.out.println("---------------------------微信退款回调(开始)-------------------------------");
+// // 获取订单信息
+// String orderIdByString = refundNotification.getOutTradeNo();
+// Order order = ordersService.getById(orderIdByString);
// // 修改订单信息
-// order.setState(1);
-// order.setPickupCode(pickupCode);
-// Date date = new Date();
-// order.setUpdateTime(date);
-// boolean update = ordersService.updateById(order);
-// ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "修改订单状态失败");
-// // 通知商家新订单
-// Business business = businessService.getById(order.getBusinessId());
-// Long userId = order.getUserId();
-// Long businessId = business.getUserId();
-// MessageVO messageVO = new MessageVO();
-// messageVO.setType(1);
-// messageVO.setUserId(userId);
-// messageVO.setToUserId(businessId);
-// messageVO.setContent(orderIdByString);
-// String message = JSONUtil.toJsonStr(messageVO);
-// // 通知商家新订单
-// webSocketServer.onMessage(message);
- System.out.println("---------------------------微信支付回调(结束)-------------------------------");
- return true;
- }
-
- @Override
- public Refund refundPayment(String orderId, BigDecimal amount) {
- // 退款请求
- CreateRequest createRequest = new CreateRequest();
- // 商户订单号
- createRequest.setOutTradeNo(orderId);
- // 商户退款单号
- createRequest.setOutRefundNo(orderId);
- // 退款结果回调
- createRequest.setNotifyUrl(wxPayConfig.getNotifyUrl() + "/api/wechat/refund/callback");
- // 退款金额
- AmountReq amountReq = new AmountReq();
- long refundAmount = amount.movePointRight(2).intValue();
- amountReq.setRefund(refundAmount);
- amountReq.setTotal(refundAmount);
- amountReq.setCurrency("CNY");
- createRequest.setAmount(amountReq);
- // 申请退款
- System.out.println("退款请求:" + createRequest);
- Refund refund = wxPayConfig.getRefundService().create(createRequest);
- System.out.println("退款申请结果:" + refund);
- return refund;
- }
-
- @Override
- public RefundNotification getRefundInfo(HttpServletRequest request) {
- NotificationParser notificationParser = getNotificationParser(request);
- return notificationParser.parse(requestParam, RefundNotification.class);
- }
-
- @Override
- @Transactional(rollbackFor = Exception.class)
- public synchronized boolean refundCallback(RefundNotification refundNotification) {
- System.out.println("---------------------------微信退款回调(开始)-------------------------------");
- // 获取订单信息
- String orderIdByString = refundNotification.getOutTradeNo();
- Order order = ordersService.getById(orderIdByString);
- // 修改订单信息
- order.setOrderStatus("已退款");
- ordersService.updateById(order);
- System.out.println("---------------------------微信退款回调(结束)-------------------------------");
- return true;
- }
-
- @Override
- public boolean sendSubscribeMessage(String openid, String templateId) {
- try {
- // 获取小程序对象
- WxMaService wxMaService = wxOpenConfig.getWxMaService();
- // 获取消息接口
- WxMaMsgService msgService = wxMaService.getMsgService();
- // 构建订阅消息体
- WxMaSubscribeMessage wxMaSubscribeMessage = new WxMaSubscribeMessage();
- wxMaSubscribeMessage.setToUser(openid);
- wxMaSubscribeMessage.setTemplateId(templateId);
- List msgDataList = getMsgData();
- wxMaSubscribeMessage.setData(msgDataList);
- // 发送消息
- msgService.sendSubscribeMsg(wxMaSubscribeMessage);
- return true;
- } catch (Exception e) {
- log.error("发送订阅消息失败:", e);
- throw new BusinessException(ErrorCode.SYSTEM_ERROR, "发送订阅消息失败");
- }
- }
-
- /**
- * 提取消息数据
- */
- private static List getMsgData() {
- List msgDataList = new ArrayList<>();
- String[][] dataItems = {
- {"thing1", "新订单"},
- {"phrase2", "已支付"},
- {"amount3", "666"},
- {"thing10", "666666"},
- {"time8", "2019-12-18 12:12:12"}
- };
- for (String[] item : dataItems) {
- WxMaSubscribeMessage.MsgData msgData = new WxMaSubscribeMessage.MsgData();
- msgData.setName(item[0]);
- msgData.setValue(item[1]);
- msgDataList.add(msgData);
- }
- return msgDataList;
- }
-
- /**
- * 根据微信官方发送的请求获取信息
- */
- @SneakyThrows
- public NotificationParser getNotificationParser(HttpServletRequest request) {
- System.out.println("---------------------------获取信息-------------------------------");
- // 获取RSA配置
- NotificationParser notificationParser = new NotificationParser(wxPayConfig.getRSAConfig());
- // 构建请求
- StringBuilder bodyBuilder = new StringBuilder();
- BufferedReader reader = request.getReader();
- String line;
- while ((line = reader.readLine()) != null) {
- bodyBuilder.append(line);
- }
- String body = bodyBuilder.toString();
- String timestamp = request.getHeader("Wechatpay-Timestamp");
- String nonce = request.getHeader("Wechatpay-Nonce");
- String signature = request.getHeader("Wechatpay-Signature");
- String singType = request.getHeader("Wechatpay-Signature-Type");
- String wechatPayCertificateSerialNumber = request.getHeader("Wechatpay-Serial");
- requestParam = new RequestParam.Builder()
- .serialNumber(wechatPayCertificateSerialNumber)
- .nonce(nonce)
- .signature(signature)
- .timestamp(timestamp)
- .signType(singType)
- .body(body)
- .build();
- System.out.println(requestParam.toString());
- System.out.println("---------------------------信息获取完毕-------------------------------");
- return notificationParser;
- }
-}
+// order.setOrderStatus("已退款");
+// ordersService.updateById(order);
+// System.out.println("---------------------------微信退款回调(结束)-------------------------------");
+// return true;
+// }
+//
+// @Override
+// public boolean sendSubscribeMessage(String openid, String templateId) {
+// try {
+// // 获取小程序对象
+// WxMaService wxMaService = wxOpenConfig.getWxMaService();
+// // 获取消息接口
+// WxMaMsgService msgService = wxMaService.getMsgService();
+// // 构建订阅消息体
+// WxMaSubscribeMessage wxMaSubscribeMessage = new WxMaSubscribeMessage();
+// wxMaSubscribeMessage.setToUser(openid);
+// wxMaSubscribeMessage.setTemplateId(templateId);
+// List msgDataList = getMsgData();
+// wxMaSubscribeMessage.setData(msgDataList);
+// // 发送消息
+// msgService.sendSubscribeMsg(wxMaSubscribeMessage);
+// return true;
+// } catch (Exception e) {
+// log.error("发送订阅消息失败:", e);
+// throw new BusinessException(ErrorCode.SYSTEM_ERROR, "发送订阅消息失败");
+// }
+// }
+//
+// /**
+// * 提取消息数据
+// */
+// private static List getMsgData() {
+// List msgDataList = new ArrayList<>();
+// String[][] dataItems = {
+// {"thing1", "新订单"},
+// {"phrase2", "已支付"},
+// {"amount3", "666"},
+// {"thing10", "666666"},
+// {"time8", "2019-12-18 12:12:12"}
+// };
+// for (String[] item : dataItems) {
+// WxMaSubscribeMessage.MsgData msgData = new WxMaSubscribeMessage.MsgData();
+// msgData.setName(item[0]);
+// msgData.setValue(item[1]);
+// msgDataList.add(msgData);
+// }
+// return msgDataList;
+// }
+//
+// /**
+// * 根据微信官方发送的请求获取信息
+// */
+// @SneakyThrows
+// public NotificationParser getNotificationParser(HttpServletRequest request) {
+// System.out.println("---------------------------获取信息-------------------------------");
+// // 获取RSA配置
+// NotificationParser notificationParser = new NotificationParser(wxPayConfig.getRSAConfig());
+// // 构建请求
+// StringBuilder bodyBuilder = new StringBuilder();
+// BufferedReader reader = request.getReader();
+// String line;
+// while ((line = reader.readLine()) != null) {
+// bodyBuilder.append(line);
+// }
+// String body = bodyBuilder.toString();
+// String timestamp = request.getHeader("Wechatpay-Timestamp");
+// String nonce = request.getHeader("Wechatpay-Nonce");
+// String signature = request.getHeader("Wechatpay-Signature");
+// String singType = request.getHeader("Wechatpay-Signature-Type");
+// String wechatPayCertificateSerialNumber = request.getHeader("Wechatpay-Serial");
+// requestParam = new RequestParam.Builder()
+// .serialNumber(wechatPayCertificateSerialNumber)
+// .nonce(nonce)
+// .signature(signature)
+// .timestamp(timestamp)
+// .signType(singType)
+// .body(body)
+// .build();
+// System.out.println(requestParam.toString());
+// System.out.println("---------------------------信息获取完毕-------------------------------");
+// return notificationParser;
+// }
+//}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index a32ff44..96f5680 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -70,17 +70,19 @@ wx:
#应用id(小程序id)
appId: wx61b63e27bddf4ea2
#商户号
- merchantId: 1700326544
+ #merchantId: 1700326544
+ mchSerialNo: 1700326544
#商户API私钥
privateKeyPath: apiclient_key.pem
#商户证书序列号
merchantSerialNumber: 6DC8953AB741D309920DA650B92F837BE38A2757
#商户APIv3密钥
apiV3Key: fbemuj4Xql7CYlQJAoTEPYxvPSNgYT2t
-# 通知地址
+ #通知地址
notifyUrl: https://winning-mouse-internally.ngrok-free.app
-# notifyUrl: http://localhost:9092
-
+ #notifyUrl: http://localhost:9092
+ #微信服务器地址
+ domain: https://api.mch.weixin.qq.com
knife4j: