From 991ab454f168bddc88d13ab863ef9f33554d4453 Mon Sep 17 00:00:00 2001 From: dftre <3066417822@qq.com> Date: Mon, 10 Mar 2025 14:33:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8C=81=E7=BB=AD=E5=AE=8C=E5=96=84=E4=B8=9A?= =?UTF-8?q?=E5=8A=A1=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application-pay.yml | 7 +- .../ruoyi/auth/controller/TfaController.java | 19 ++- .../alipay/service/Impl/AliPayService.java | 62 ++++++++- .../java/com/ruoyi/pay/domain/PayOrder.java | 17 ++- .../com/ruoyi/pay/service/PayService.java | 4 +- .../resources/mapper/pay/PayOrderMapper.xml | 5 + .../pay/sqb/service/Impl/SQBServiceImpl.java | 26 +++- .../ruoyi/pay/controller/PayController.java | 39 ++++-- .../com/ruoyi/pay/wx/config/WxPayConfig.java | 124 ++++++++++-------- .../ruoyi/pay/wx/service/IWxPayService.java | 2 - .../pay/wx/service/Impl/WxPayService.java | 47 +++++-- sql/mysql/pay.sql | 1 + sql/postgresql/pay.sql | 2 + 13 files changed, 259 insertions(+), 96 deletions(-) diff --git a/ruoyi-admin/src/main/resources/application-pay.yml b/ruoyi-admin/src/main/resources/application-pay.yml index 86d865a..eb24f65 100644 --- a/ruoyi-admin/src/main/resources/application-pay.yml +++ b/ruoyi-admin/src/main/resources/application-pay.yml @@ -1,4 +1,7 @@ +# 当前支付模块写的并不完善,请根据自己的业务需求进行修改 +# 回调地址使用的内网穿透http://e2vca6.natappfree.cc pay: + # https://doc.shouqianba.com/zh-cn/ sqb: enabled: false appId: "appId" @@ -9,12 +12,14 @@ pay: vendorKey: "vendorKey" publicKey: classpath:pay/sqb/sqb_public_key.pem notifyUrl: http://e2vca6.natappfree.cc/pay/sqb/notify + # https://opendocs.alipay.com/open/02np95 alipay: enabled: false appId: appid appPrivateKey: classpath:pay/alipay/alipay_private_key.pem alipayPublicKey: classpath:pay/alipay/alipay_public_key.pem notifyUrl: http://e2vca6.natappfree.cc/alipay/notify + # https://github.com/wechatpay-apiv3/wechatpay-java wechat: enabled: false appId: appid @@ -22,5 +27,5 @@ pay: privateKeyPath: classpath:pay/wx/apiclient_key.pem merchantId: merchantId merchantSerialNumber: merchantSerialNumber - # 回调地址,此处使用的内网穿透http://e2vca6.natappfree.cc + notifyUrl: http://e2vca6.natappfree.cc/pay/wechat/notify diff --git a/ruoyi-auth/ruoyi-auth-starter/src/main/java/com/ruoyi/auth/controller/TfaController.java b/ruoyi-auth/ruoyi-auth-starter/src/main/java/com/ruoyi/auth/controller/TfaController.java index c21d5d3..79ed279 100644 --- a/ruoyi-auth/ruoyi-auth-starter/src/main/java/com/ruoyi/auth/controller/TfaController.java +++ b/ruoyi-auth/ruoyi-auth-starter/src/main/java/com/ruoyi/auth/controller/TfaController.java @@ -1,5 +1,6 @@ package com.ruoyi.auth.controller; +import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; @@ -16,13 +17,27 @@ import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.model.LoginBody; import com.ruoyi.common.core.domain.model.RegisterBody; +import jakarta.annotation.PostConstruct; + @RestController -@RequestMapping("/auth/") // dySms mail +@RequestMapping("/auth/{channel}") // dySms mail public class TfaController extends BaseController { - @Autowired + @Autowired(required = false) Map tfaServiceMap; + @PostConstruct + public void init() { + if (tfaServiceMap == null) { + tfaServiceMap = new HashMap<>(); + logger.warn("请注意,没有加载任何双认证服务"); + } else { + tfaServiceMap.forEach((k, v) -> { + logger.info("已加载双认证服务 {}", k); + }); + } + } + @PostMapping("/send/bind") public AjaxResult send(@PathVariable String channel, @RequestBody LoginBody loginBody) { TfaService tfaService = tfaServiceMap.get(channel + "AuthService"); diff --git a/ruoyi-pay/ruoyi-pay-alipay/src/main/java/com/ruoyi/pay/alipay/service/Impl/AliPayService.java b/ruoyi-pay/ruoyi-pay-alipay/src/main/java/com/ruoyi/pay/alipay/service/Impl/AliPayService.java index 2d14e1b..593e5de 100644 --- a/ruoyi-pay/ruoyi-pay-alipay/src/main/java/com/ruoyi/pay/alipay/service/Impl/AliPayService.java +++ b/ruoyi-pay/ruoyi-pay-alipay/src/main/java/com/ruoyi/pay/alipay/service/Impl/AliPayService.java @@ -8,6 +8,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import com.alipay.easysdk.factory.Factory; +import com.alipay.easysdk.payment.common.models.AlipayTradeRefundResponse; import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.pay.alipay.service.IAliPayService; @@ -63,14 +64,63 @@ public class AliPayService implements IAliPayService { } @Override - public String query(PayOrder payOrder) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'query'"); + public PayOrder query(PayOrder payOrder) { + try { + // 使用支付宝SDK查询订单状态 + com.alipay.easysdk.payment.common.models.AlipayTradeQueryResponse response = Factory.Payment.Common() + .query(payOrder.getOrderNumber()); + + // 根据查询结果更新订单状态 + if ("10000".equals(response.code)) { + String tradeStatus = response.tradeStatus; + String orderStatus = ""; + + // 根据支付宝交易状态映射到系统订单状态 + switch (tradeStatus) { + case "TRADE_SUCCESS": + case "TRADE_FINISHED": + orderStatus = "已支付"; + break; + case "WAIT_BUYER_PAY": + orderStatus = "待支付"; + break; + case "TRADE_CLOSED": + orderStatus = "已关闭"; + break; + default: + orderStatus = "未知状态"; + } + + // 更新订单信息 + payOrderService.updateStatus(payOrder.getOrderNumber(), orderStatus); + } else { + throw new ServiceException("查询支付宝订单失败:" + response.subMsg); + } + + return payOrder; + } catch (Exception e) { + throw new ServiceException("查询支付宝订单异常:" + e.getMessage()); + } } @Override - public String refund(PayOrder payOrder) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'refund'"); + public PayOrder refund(PayOrder payOrder) { + try { + // 使用支付宝SDK进行退款 + AlipayTradeRefundResponse response = Factory.Payment.Common().refund( + payOrder.getOrderNumber(), + payOrder.getActualAmount()); + + // 处理退款结果 + if ("10000".equals(response.code)) { + payOrderService.updateStatus(payOrder.getOrderNumber(), "已退款"); + } else { + throw new ServiceException("支付宝退款失败:" + response.subMsg); + } + + return payOrder; + } catch (Exception e) { + throw new ServiceException("支付宝退款异常:" + e.getMessage()); + } } } diff --git a/ruoyi-pay/ruoyi-pay-common/src/main/java/com/ruoyi/pay/domain/PayOrder.java b/ruoyi-pay/ruoyi-pay-common/src/main/java/com/ruoyi/pay/domain/PayOrder.java index 24f80bb..ea4f029 100644 --- a/ruoyi-pay/ruoyi-pay-common/src/main/java/com/ruoyi/pay/domain/PayOrder.java +++ b/ruoyi-pay/ruoyi-pay-common/src/main/java/com/ruoyi/pay/domain/PayOrder.java @@ -23,10 +23,15 @@ public class PayOrder extends BaseEntity { private Long orderId; /** 订单号 */ - @Schema(title = "订单号") - @Excel(name = "订单号") + @Schema(title = "商户订单号") + @Excel(name = "商户订单号") private String orderNumber; + /** 第三方订单号 */ + @Schema(title = "第三方订单号") + @Excel(name = "第三方订单号") + private String thirdNumber; + /** 订单状态 */ @Schema(title = "订单状态") @Excel(name = "订单状态") @@ -68,6 +73,14 @@ public class PayOrder extends BaseEntity { return orderNumber; } + public void setThirdNumber(String thirdNumber) { + this.thirdNumber = thirdNumber; + } + + public String getThirdNumber() { + return thirdNumber; + } + public void setOrderStatus(String orderStatus) { this.orderStatus = orderStatus; } diff --git a/ruoyi-pay/ruoyi-pay-common/src/main/java/com/ruoyi/pay/service/PayService.java b/ruoyi-pay/ruoyi-pay-common/src/main/java/com/ruoyi/pay/service/PayService.java index 2bddb3a..a4f71dc 100644 --- a/ruoyi-pay/ruoyi-pay-common/src/main/java/com/ruoyi/pay/service/PayService.java +++ b/ruoyi-pay/ruoyi-pay-common/src/main/java/com/ruoyi/pay/service/PayService.java @@ -10,7 +10,7 @@ public interface PayService { String notify(HttpServletRequest servletRequest, HttpServletResponse response); - String query(PayOrder payOrder); + PayOrder query(PayOrder payOrder); - String refund(PayOrder payOrder); + PayOrder refund(PayOrder payOrder); } diff --git a/ruoyi-pay/ruoyi-pay-common/src/main/resources/mapper/pay/PayOrderMapper.xml b/ruoyi-pay/ruoyi-pay-common/src/main/resources/mapper/pay/PayOrderMapper.xml index 6083c9c..982b5b4 100644 --- a/ruoyi-pay/ruoyi-pay-common/src/main/resources/mapper/pay/PayOrderMapper.xml +++ b/ruoyi-pay/ruoyi-pay-common/src/main/resources/mapper/pay/PayOrderMapper.xml @@ -7,6 +7,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + @@ -27,6 +28,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and order_number = #{orderNumber} + and third_number = #{thirdNumber} and order_status = #{orderStatus} and total_amount = #{totalAmount} and actual_amount = #{actualAmount} @@ -44,6 +46,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" insert into pay_order order_number, + third_number, order_status, total_amount, actual_amount, @@ -57,6 +60,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{orderNumber}, + #{thirdNumber}, #{orderStatus}, #{totalAmount}, #{actualAmount}, @@ -74,6 +78,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" update pay_order order_number = #{orderNumber}, + third_number = #{thirdNumber}, order_status = #{orderStatus}, total_amount = #{totalAmount}, actual_amount = #{actualAmount}, diff --git a/ruoyi-pay/ruoyi-pay-sqb/src/main/java/com/ruoyi/pay/sqb/service/Impl/SQBServiceImpl.java b/ruoyi-pay/ruoyi-pay-sqb/src/main/java/com/ruoyi/pay/sqb/service/Impl/SQBServiceImpl.java index 4207414..52b82c6 100644 --- a/ruoyi-pay/ruoyi-pay-sqb/src/main/java/com/ruoyi/pay/sqb/service/Impl/SQBServiceImpl.java +++ b/ruoyi-pay/ruoyi-pay-sqb/src/main/java/com/ruoyi/pay/sqb/service/Impl/SQBServiceImpl.java @@ -28,18 +28,24 @@ import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.http.HttpClientUtil; import com.ruoyi.common.utils.sign.Md5Utils; import com.ruoyi.pay.domain.PayOrder; +import com.ruoyi.pay.service.IPayOrderService; import com.ruoyi.pay.sqb.config.SqbConfig; import com.ruoyi.pay.sqb.service.ISqbPayService; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +@Slf4j @Service("sqbPayService") @ConditionalOnProperty(prefix = "pay.sqb", name = "enabled", havingValue = "true") public class SQBServiceImpl implements ISqbPayService { @Autowired private SqbConfig sqbConfig; + @Autowired + private IPayOrderService payOrderService; + /** * http POST 请求 * @@ -146,7 +152,7 @@ public class SQBServiceImpl implements ISqbPayService { * * @return */ - public String refund(PayOrder payOrder) { + public PayOrder refund(PayOrder payOrder) { String url = sqbConfig.getApiDomain() + "/upay/v2/refund"; JSONObject params = new JSONObject(); try { @@ -158,8 +164,14 @@ public class SQBServiceImpl implements ISqbPayService { String sign = getSign(params.toString() + sqbConfig.getTerminalKey()); String result = httpPost(url, params, sign, sqbConfig.getTerminalSn()); - - return result; + JSONObject retObj = JSON.parseObject(result); + JSONObject bizResponse = retObj.getJSONObject("biz_response"); + if ("REFUNDED".equals(bizResponse.getString("order_status"))) { + payOrderService.updateStatus(payOrder.getOrderNumber(), "已退款"); + } else { + log.error("退款失败"); + } + return payOrder; } catch (Exception e) { return null; } @@ -170,8 +182,8 @@ public class SQBServiceImpl implements ISqbPayService { * * @return */ - - public String query(PayOrder payOrder) { + @Override + public PayOrder query(PayOrder payOrder) { String url = sqbConfig.getApiDomain() + "/upay/v2/query"; JSONObject params = new JSONObject(); try { @@ -185,8 +197,8 @@ public class SQBServiceImpl implements ISqbPayService { if (!"200".equals(resCode)) { return null; } - String responseStr = retObj.get("biz_response").toString(); - return responseStr; + // String responseStr = retObj.get("biz_response").toString(); + return payOrder; } catch (Exception e) { return null; } diff --git a/ruoyi-pay/ruoyi-pay-starter/src/main/java/com/ruoyi/pay/controller/PayController.java b/ruoyi-pay/ruoyi-pay-starter/src/main/java/com/ruoyi/pay/controller/PayController.java index cdb7612..a3348d0 100644 --- a/ruoyi-pay/ruoyi-pay-starter/src/main/java/com/ruoyi/pay/controller/PayController.java +++ b/ruoyi-pay/ruoyi-pay-starter/src/main/java/com/ruoyi/pay/controller/PayController.java @@ -1,5 +1,6 @@ package com.ruoyi.pay.controller; +import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; @@ -8,8 +9,8 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; -import com.alibaba.fastjson2.JSON; import com.ruoyi.common.annotation.Anonymous; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; @@ -20,19 +21,35 @@ import com.ruoyi.pay.service.PayService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; +import jakarta.annotation.PostConstruct; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -@RequestMapping("/pay/") +@RequestMapping("/pay/{channel}") +@RestController public class PayController extends BaseController { - @Autowired + + @Autowired(required = false) private Map payServiceMap; // alipay wechat sqb + @PostConstruct + public void init() { + if (payServiceMap == null) { + payServiceMap = new HashMap<>(); + logger.warn("请注意,没有加载任何支付服务"); + } else { + payServiceMap.forEach((k, v) -> { + logger.info("已加载支付服务 {}", k); + }); + } + } + @Autowired private IPayOrderService payOrderService; @Operation(summary = "微信支付") @Parameters({ + @Parameter(name = "channel", description = "支付方式", required = true), @Parameter(name = "orderNumber", description = "订单号", required = true) }) @GetMapping("/url/{orderNumber}") @@ -44,6 +61,9 @@ public class PayController extends BaseController { @Anonymous @Operation(summary = "微信支付查询订单") + @Parameters({ + @Parameter(name = "channel", description = "支付方式", required = true) + }) @PostMapping("/notify") public String notify(@PathVariable String channel, HttpServletRequest request, HttpServletResponse response) throws Exception { @@ -52,7 +72,8 @@ public class PayController extends BaseController { } @Operation(summary = "查询支付状态") - @Parameters(value = { + @Parameters({ + @Parameter(name = "channel", description = "支付方式", required = true), @Parameter(name = "orderNumber", description = "订单号", required = true) }) @PostMapping("/query/{orderNumber}") @@ -64,13 +85,11 @@ public class PayController extends BaseController { } @PostMapping("/refund") + @Parameters({ + @Parameter(name = "channel", description = "支付方式", required = true), + }) public AjaxResult refund(@PathVariable String channel, @RequestBody PayOrder payOrder) { PayService payService = payServiceMap.get(channel + "PayService"); - String refund = payService.refund(payOrder); - if (refund == null) { - return error("退款失败"); - } - Object parse = JSON.parse(refund); - return success(parse); + return success(payService.refund(payOrder)); } } diff --git a/ruoyi-pay/ruoyi-pay-wx/src/main/java/com/ruoyi/pay/wx/config/WxPayConfig.java b/ruoyi-pay/ruoyi-pay-wx/src/main/java/com/ruoyi/pay/wx/config/WxPayConfig.java index 0b7896a..fda8210 100644 --- a/ruoyi-pay/ruoyi-pay-wx/src/main/java/com/ruoyi/pay/wx/config/WxPayConfig.java +++ b/ruoyi-pay/ruoyi-pay-wx/src/main/java/com/ruoyi/pay/wx/config/WxPayConfig.java @@ -16,6 +16,7 @@ import org.springframework.core.io.Resource; import com.wechat.pay.java.core.RSAAutoCertificateConfig; import com.wechat.pay.java.core.notification.NotificationParser; import com.wechat.pay.java.service.payments.nativepay.NativePayService; +import com.wechat.pay.java.service.refund.RefundService; /** * 配置我们自己的信息 @@ -26,79 +27,54 @@ import com.wechat.pay.java.service.payments.nativepay.NativePayService; @ConditionalOnProperty(prefix = "pay.wechat", name = "enabled", havingValue = "true") public class WxPayConfig { + /** 商户号 */ @Value("${pay.wechat.merchantId}") - private String wxchantId; + private String merchantId; + + /** 商户证书序列号 */ @Value("${pay.wechat.merchantSerialNumber}") - private String wxchantSerialNumber; + private String merchantSerialNumber; + + /** 商户APIV3密钥 */ @Value("${pay.wechat.apiV3Key}") - private String wxapiV3Key; + private String apiV3Key; + + /** 商户API私钥路径 */ @Value("${pay.wechat.privateKeyPath}") - private String wxcertPath; + private String privateKeyPath; + @Value("${pay.wechat.appId}") private String appId; + @Value("${pay.wechat.notifyUrl}") private String notifyUrl; - @Bean - public RSAAutoCertificateConfig wxpayBaseConfig() throws Exception { - return new RSAAutoCertificateConfig.Builder() - .merchantId(getWxchantId()) - .privateKeyFromPath(getWxcertPath()) - .merchantSerialNumber(getWxchantSerialNumber()) - .apiV3Key(getWxapiV3Key()) - .build(); + public String getMerchantId() { + return merchantId; } - @Bean - public NativePayService nativePayService() throws Exception { - return new NativePayService.Builder().config(wxpayBaseConfig()).build(); + public void setMerchantId(String merchantId) { + this.merchantId = merchantId; } - @Bean - public NotificationParser notificationParser() throws Exception { - return new NotificationParser(wxpayBaseConfig()); + public String getMerchantSerialNumber() { + return merchantSerialNumber; } - @Autowired - private ApplicationContext applicationContext; - - public String getWxcertPath() throws Exception { - if (wxcertPath.startsWith("classpath:")) { - Resource resource = applicationContext.getResource(wxcertPath); - String tempFilePath = System.getProperty("java.io.tmpdir") + "/temp_wxcert.pem"; - try (InputStream inputStream = resource.getInputStream()) { - Files.copy(inputStream, Paths.get(tempFilePath), StandardCopyOption.REPLACE_EXISTING); - wxcertPath = tempFilePath; - } catch (Exception e) { - Files.deleteIfExists(Paths.get(tempFilePath)); - throw new RuntimeException("微信支付证书文件读取失败", e); - } - } - return wxcertPath; + public void setMerchantSerialNumber(String merchantSerialNumber) { + this.merchantSerialNumber = merchantSerialNumber; } - public String getWxchantId() { - return wxchantId; + public String getApiV3Key() { + return apiV3Key; } - public void setWxchantId(String wxchantId) { - this.wxchantId = wxchantId; + public void setApiV3Key(String apiV3Key) { + this.apiV3Key = apiV3Key; } - public String getWxchantSerialNumber() { - return wxchantSerialNumber; - } - - public void setWxchantSerialNumber(String wxchantSerialNumber) { - this.wxchantSerialNumber = wxchantSerialNumber; - } - - public String getWxapiV3Key() { - return wxapiV3Key; - } - - public void setWxapiV3Key(String wxapiV3Key) { - this.wxapiV3Key = wxapiV3Key; + public void setPrivateKeyPath(String privateKeyPath) { + this.privateKeyPath = privateKeyPath; } public String getAppId() { @@ -116,4 +92,48 @@ public class WxPayConfig { public void setNotifyUrl(String notifyUrl) { this.notifyUrl = notifyUrl; } + + @Bean + public RSAAutoCertificateConfig wxpayBaseConfig() throws Exception { + return new RSAAutoCertificateConfig.Builder() + .merchantId(getMerchantId()) + .privateKeyFromPath(getPrivateKeyPath()) + .merchantSerialNumber(getMerchantSerialNumber()) + .apiV3Key(getApiV3Key()) + .build(); + } + + @Bean + public NativePayService nativePayService() throws Exception { + return new NativePayService.Builder().config(wxpayBaseConfig()).build(); + } + + @Bean + public RefundService refundService() throws Exception { + return new RefundService.Builder().config(wxpayBaseConfig()).build(); + } + + @Bean + public NotificationParser notificationParser() throws Exception { + return new NotificationParser(wxpayBaseConfig()); + } + + @Autowired + private ApplicationContext applicationContext; + + public String getPrivateKeyPath() throws Exception { + if (privateKeyPath.startsWith("classpath:")) { + Resource resource = applicationContext.getResource(privateKeyPath); + String tempFilePath = System.getProperty("java.io.tmpdir") + "/temp_wxcert.pem"; + try (InputStream inputStream = resource.getInputStream()) { + Files.copy(inputStream, Paths.get(tempFilePath), StandardCopyOption.REPLACE_EXISTING); + privateKeyPath = tempFilePath; + } catch (Exception e) { + Files.deleteIfExists(Paths.get(tempFilePath)); + throw new RuntimeException("微信支付证书文件读取失败", e); + } + } + return privateKeyPath; + } + } diff --git a/ruoyi-pay/ruoyi-pay-wx/src/main/java/com/ruoyi/pay/wx/service/IWxPayService.java b/ruoyi-pay/ruoyi-pay-wx/src/main/java/com/ruoyi/pay/wx/service/IWxPayService.java index cf4fd7d..46f6538 100644 --- a/ruoyi-pay/ruoyi-pay-wx/src/main/java/com/ruoyi/pay/wx/service/IWxPayService.java +++ b/ruoyi-pay/ruoyi-pay-wx/src/main/java/com/ruoyi/pay/wx/service/IWxPayService.java @@ -1,8 +1,6 @@ package com.ruoyi.pay.wx.service; import com.ruoyi.pay.service.PayService; -import com.wechat.pay.java.service.wexinpayscoreparking.model.Transaction; public interface IWxPayService extends PayService { - public void callback(Transaction transaction); } diff --git a/ruoyi-pay/ruoyi-pay-wx/src/main/java/com/ruoyi/pay/wx/service/Impl/WxPayService.java b/ruoyi-pay/ruoyi-pay-wx/src/main/java/com/ruoyi/pay/wx/service/Impl/WxPayService.java index f44b6db..acd105c 100644 --- a/ruoyi-pay/ruoyi-pay-wx/src/main/java/com/ruoyi/pay/wx/service/Impl/WxPayService.java +++ b/ruoyi-pay/ruoyi-pay-wx/src/main/java/com/ruoyi/pay/wx/service/Impl/WxPayService.java @@ -11,13 +11,20 @@ import com.ruoyi.pay.domain.PayOrder; import com.ruoyi.pay.service.IPayOrderService; import com.ruoyi.pay.wx.config.WxPayConfig; import com.ruoyi.pay.wx.service.IWxPayService; +import com.wechat.pay.java.core.exception.ServiceException; import com.wechat.pay.java.core.notification.NotificationParser; import com.wechat.pay.java.core.notification.RequestParam; +import com.wechat.pay.java.service.payments.model.Transaction; +import com.wechat.pay.java.service.payments.model.Transaction.TradeStateEnum; import com.wechat.pay.java.service.payments.nativepay.NativePayService; import com.wechat.pay.java.service.payments.nativepay.model.Amount; import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest; import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse; -import com.wechat.pay.java.service.wexinpayscoreparking.model.Transaction; +import com.wechat.pay.java.service.payments.nativepay.model.QueryOrderByIdRequest; +import com.wechat.pay.java.service.refund.RefundService; +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.Status; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -38,9 +45,8 @@ public class WxPayService implements IWxPayService { @Autowired private NotificationParser notificationParser; - public void callback(Transaction transaction) { - - } + @Autowired + private RefundService refundService; @Override public String payUrl(PayOrder payOrder) { @@ -49,7 +55,7 @@ public class WxPayService implements IWxPayService { amount.setTotal(Integer.parseInt(payOrder.getActualAmount())); request.setAmount(amount); request.setAppid(wxPayAppConfig.getAppId()); - request.setMchid(wxPayAppConfig.getWxchantId()); + request.setMchid(wxPayAppConfig.getMerchantId()); request.setDescription(payOrder.getOrderContent()); request.setNotifyUrl(wxPayAppConfig.getNotifyUrl()); request.setOutTradeNo(payOrder.getOrderNumber()); @@ -75,7 +81,7 @@ public class WxPayService implements IWxPayService { Transaction transaction = notificationParser.parse(requestParam, Transaction.class); String orderNumber = transaction.getOutTradeNo(); String otherOrderNumber = transaction.getTransactionId(); - String orderState = transaction.getTradeState(); + TradeStateEnum orderState = transaction.getTradeState(); System.out.println("orderNumber: " + orderNumber); System.out.println("otherOrderNumber: " + otherOrderNumber); System.out.println("orderState: " + orderState); @@ -87,15 +93,32 @@ public class WxPayService implements IWxPayService { } @Override - public String query(PayOrder payOrder) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'query'"); + public PayOrder query(PayOrder payOrder) { + QueryOrderByIdRequest queryRequest = new QueryOrderByIdRequest(); + queryRequest.setMchid(wxPayAppConfig.getMerchantId()); + queryRequest.setTransactionId(payOrder.getOrderNumber()); + try { + Transaction result = nativePayService.queryOrderById(queryRequest); + System.out.println(result.getTradeState()); + } catch (ServiceException e) { + System.out.printf("code=[%s], message=[%s]\n", e.getErrorCode(), e.getErrorMessage()); + System.out.printf("reponse body=[%s]\n", e.getResponseBody()); + } + return payOrder; } @Override - public String refund(PayOrder payOrder) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'refund'"); + public PayOrder refund(PayOrder payOrder) { + CreateRequest request = new CreateRequest(); + request.setTransactionId(payOrder.getOrderNumber()); + request.setOutRefundNo(payOrder.getOrderNumber()); + request.setOutTradeNo(payOrder.getOrderNumber()); + Refund refund = refundService.create(request); + Status status = refund.getStatus(); + if (status.equals(Status.SUCCESS)) { + payOrderService.updateStatus(payOrder.getOrderNumber(), "已退款"); + } + return payOrder; } } diff --git a/sql/mysql/pay.sql b/sql/mysql/pay.sql index 7708ceb..c9d9011 100644 --- a/sql/mysql/pay.sql +++ b/sql/mysql/pay.sql @@ -5,6 +5,7 @@ DROP TABLE IF EXISTS `pay_order`; CREATE TABLE `pay_order` ( order_id bigint NOT NULL AUTO_INCREMENT COMMENT '订单id', order_number varchar(255) NULL DEFAULT NULL COMMENT '订单号', + third_number varchar(255) NULL DEFAULT NULL COMMENT '第三方订单号', order_status varchar(255) NULL DEFAULT NULL COMMENT '订单状态', total_amount varchar(255) NULL DEFAULT NULL COMMENT '订单总金额', actual_amount varchar(255) NULL DEFAULT NULL COMMENT '实际支付金额', diff --git a/sql/postgresql/pay.sql b/sql/postgresql/pay.sql index 0c9bc74..689f5a6 100644 --- a/sql/postgresql/pay.sql +++ b/sql/postgresql/pay.sql @@ -5,6 +5,7 @@ DROP TABLE IF EXISTS pay_order; CREATE TABLE pay_order ( order_id bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, order_number varchar(255) NULL DEFAULT NULL, + third_number varchar(255) NULL DEFAULT NULL, order_status varchar(255) NULL DEFAULT NULL, total_amount varchar(255) NULL DEFAULT NULL, actual_amount varchar(255) NULL DEFAULT NULL, @@ -19,6 +20,7 @@ CREATE TABLE pay_order ( COMMENT ON COLUMN pay_order.order_id IS '订单id'; COMMENT ON COLUMN pay_order.order_number IS '订单号'; +COMMENT ON COLUMN pay_order.third_number IS '第三方订单号'; COMMENT ON COLUMN pay_order.order_status IS '订单状态'; COMMENT ON COLUMN pay_order.total_amount IS '订单总金额'; COMMENT ON COLUMN pay_order.actual_amount IS '实际支付金额';