From 2378e99c3b7cba6a16c0313484acbda1e289cf37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A3=B7=E5=8F=B6?= <14103883+leaf-phos@user.noreply.gitee.com> Date: Tue, 7 Jan 2025 18:22:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ruoyi/common/auth/ali/AliConfig.java | 48 +++++++------ .../java/com/ruoyi/common/pay/PayApi.java | 10 +-- .../common/pay/ali/service/AliPayService.java | 46 ++++++++---- .../common/pay/syb/service/SybPayClient.java | 6 +- .../common/pay/syb/service/SybPayService.java | 19 ++--- .../com/ruoyi/common/pay/tm/TmPayService.java | 36 +++++++--- .../common/pay/wx/config/WxPayConfig.java | 3 +- .../common/pay/wx/service/WxPayService.java | 45 ++++++------ .../common/utils/file/MimeTypeUtils.java | 9 ++- .../typehandler/ObjectJsonTypeHandler.java | 8 +++ .../com/ruoyi/iot/service/IotService.java | 2 +- .../iot/service/impl/IotServiceImpl.java | 33 +++++---- .../com/ruoyi/ss/channel/domain/Channel.java | 12 ++++ .../ss/channel/domain/ChannelConfig.java | 46 ++++++++++++ .../ruoyi/ss/channel/domain/ChannelVO.java | 2 +- .../{ChannelEnum.java => ChannelApiType.java} | 28 ++++---- .../ss/channel/domain/enums/ChannelType.java | 20 ++++++ .../ss/channel/mapper/ChannelMapper.java | 7 ++ .../ruoyi/ss/channel/mapper/ChannelMapper.xml | 32 ++++++++- .../ChannelConfigJsonTypeHandler.java | 11 +++ .../ss/channel/service/ChannelConverter.java | 15 ++++ .../ss/channel/service/ChannelService.java | 9 +++ .../service/impl/ChannelConverterImpl.java | 38 ++++++++++ .../service/impl/ChannelServiceImpl.java | 31 ++++++++ .../service/impl/DeviceServiceImpl.java | 2 +- .../service/impl/PayBillServiceImpl.java | 37 +++++----- .../service/impl/RefundServiceImpl.java | 14 ++-- .../web/controller/app/AppPayController.java | 13 ++-- .../controller/ss/SmChannelController.java | 71 +++++++++++++------ 29 files changed, 480 insertions(+), 173 deletions(-) create mode 100644 smart-switch-ruoyi/smart-switch-system/src/main/java/com/ruoyi/system/mapper/typehandler/ObjectJsonTypeHandler.java create mode 100644 smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/ChannelConfig.java rename smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/enums/{ChannelEnum.java => ChannelApiType.java} (58%) create mode 100644 smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/enums/ChannelType.java create mode 100644 smart-switch-service/src/main/java/com/ruoyi/ss/channel/mapper/typehandler/ChannelConfigJsonTypeHandler.java create mode 100644 smart-switch-service/src/main/java/com/ruoyi/ss/channel/service/ChannelConverter.java create mode 100644 smart-switch-service/src/main/java/com/ruoyi/ss/channel/service/impl/ChannelConverterImpl.java diff --git a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/auth/ali/AliConfig.java b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/auth/ali/AliConfig.java index 3ca616a4..7718736d 100644 --- a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/auth/ali/AliConfig.java +++ b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/auth/ali/AliConfig.java @@ -1,9 +1,9 @@ package com.ruoyi.common.auth.ali; -import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.AlipayConfig; import com.alipay.api.DefaultAlipayClient; +import com.ruoyi.common.exception.ServiceException; import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; @@ -65,27 +65,31 @@ public class AliConfig { // 证书模式 @Bean - public AlipayClient alipayClient() throws AlipayApiException { - AlipayConfig alipayConfig = new AlipayConfig(); - //设置网关地址 - alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do"); - //设置应用APPID - alipayConfig.setAppId(this.getAppId()); - //设置应用私钥 - alipayConfig.setPrivateKey(this.getPrivateKey()); - //设置应用公钥证书路径 - alipayConfig.setAppCertPath(this.getAppCertPath()); - //设置支付宝公钥证书路径 - alipayConfig.setAlipayPublicCertPath(this.getAlipayCertPath()); - //设置支付宝根证书路径 - alipayConfig.setRootCertPath(this.alipayRootCertPath); - //设置请求格式,固定值json - alipayConfig.setFormat("json"); - //设置字符集 - alipayConfig.setCharset("UTF-8"); - //设置签名类型 - alipayConfig.setSignType("RSA2"); + public AlipayClient alipayClient() { + try { + AlipayConfig alipayConfig = new AlipayConfig(); + //设置网关地址 + alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do"); + //设置应用APPID + alipayConfig.setAppId(this.getAppId()); + //设置应用私钥 + alipayConfig.setPrivateKey(this.getPrivateKey()); + //设置应用公钥证书路径 + alipayConfig.setAppCertPath(this.getAppCertPath()); + //设置支付宝公钥证书路径 + alipayConfig.setAlipayPublicCertPath(this.getAlipayCertPath()); + //设置支付宝根证书路径 + alipayConfig.setRootCertPath(this.alipayRootCertPath); + //设置请求格式,固定值json + alipayConfig.setFormat("json"); + //设置字符集 + alipayConfig.setCharset("UTF-8"); + //设置签名类型 + alipayConfig.setSignType("RSA2"); - return new DefaultAlipayClient(alipayConfig); + return new DefaultAlipayClient(alipayConfig); + } catch (Exception e) { + throw new ServiceException(e.getMessage()); + } } } diff --git a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/PayApi.java b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/PayApi.java index 50c42da1..94381e7e 100644 --- a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/PayApi.java +++ b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/PayApi.java @@ -9,19 +9,19 @@ import java.time.LocalDateTime; public interface PayApi { // 发起支付 - Object pay(Payable payable); + Object pay(Payable payable, Object config); // 关闭支付单 - void closeByOutTradeNo(String outTradeNo); + void closeByOutTradeNo(String outTradeNo, Object config); // 查询支付单 - Object queryByOutTradeNo(String outTradeNo); + Object queryByOutTradeNo(String outTradeNo, Object config); // 退款 - Object refund(Refundable refundAble); + Object refund(Refundable refundAble, Object config); // 是否支付成功 - boolean isPaySuccessByOutTradeNo(String outTradeNo); + boolean isPaySuccessByOutTradeNo(String outTradeNo, Object config); // 是否支付成功 boolean isPaySuccess(Object result); diff --git a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/ali/service/AliPayService.java b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/ali/service/AliPayService.java index 03832f41..b99cdb7b 100644 --- a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/ali/service/AliPayService.java +++ b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/ali/service/AliPayService.java @@ -22,15 +22,10 @@ import com.ruoyi.common.pay.Refundable; import com.ruoyi.common.pay.ali.enums.AliTradeStatusEnum; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.ServiceUtil; -import com.ruoyi.common.utils.http.HttpUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpRequest; import org.springframework.stereotype.Service; -import javax.servlet.http.HttpServletRequest; import java.time.LocalDateTime; -import java.util.HashMap; -import java.util.Iterator; import java.util.Map; /** @@ -41,12 +36,16 @@ import java.util.Map; public class AliPayService implements PayApi { @Autowired - private AlipayClient alipayClient; + private AlipayClient defaultAliPayConfig; @Autowired - private AliConfig aliConfig; + private AliConfig defaultAliConfig; + + public String pay(Payable payable, Object config) { + // 初始化支付宝客户端 + AliConfig aliConfig = (AliConfig) config; + AlipayClient alipayClient = aliConfig.alipayClient(); - public String pay(Payable payable) { // 构造请求参数以调用接口 AlipayTradeCreateRequest request = new AlipayTradeCreateRequest(); AlipayTradeCreateModel data = new AlipayTradeCreateModel(); @@ -79,7 +78,12 @@ public class AliPayService implements PayApi { /** * 关闭支付订单 */ - public void closeByOutTradeNo(String outTradeNo) { + public void closeByOutTradeNo(String outTradeNo, Object config) { + // 初始化支付宝客户端 + AliConfig aliConfig = (AliConfig) config; + AlipayClient alipayClient = aliConfig.alipayClient(); + + AlipayTradeCloseRequest request = new AlipayTradeCloseRequest(); JSONObject bizContent = new JSONObject(); bizContent.put("out_trade_no", outTradeNo); @@ -93,7 +97,11 @@ public class AliPayService implements PayApi { } - public AlipayTradeQueryResponse queryByOutTradeNo(String outTradeNo) { + public AlipayTradeQueryResponse queryByOutTradeNo(String outTradeNo, Object config) { + // 初始化支付宝客户端 + AliConfig aliConfig = (AliConfig) config; + AlipayClient alipayClient = aliConfig.alipayClient(); + // 构造请求参数以调用接口 AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); AlipayTradeQueryModel model = new AlipayTradeQueryModel(); @@ -116,8 +124,14 @@ public class AliPayService implements PayApi { * 发起退款 * * @param refund + * @param config */ - public AlipayTradeRefundResponse refund(Refundable refund) { + public AlipayTradeRefundResponse refund(Refundable refund, Object config) { + + // 初始化支付宝客户端 + AliConfig aliConfig = (AliConfig) config; + AlipayClient alipayClient = aliConfig.alipayClient(); + // 构造请求参数以调用接口 AlipayTradeRefundRequest request = new AlipayTradeRefundRequest(); AlipayTradeRefundModel model = new AlipayTradeRefundModel(); @@ -144,8 +158,8 @@ public class AliPayService implements PayApi { } @Override - public boolean isPaySuccessByOutTradeNo(String outTradeNo) { - AlipayTradeQueryResponse res = this.queryByOutTradeNo(outTradeNo); + public boolean isPaySuccessByOutTradeNo(String outTradeNo, Object config) { + AlipayTradeQueryResponse res = this.queryByOutTradeNo(outTradeNo, config); return isPaySuccess(res); } @@ -163,11 +177,13 @@ public class AliPayService implements PayApi { /** * 对通知进行验签 + * @param params 参数 + * @param aliCertPath 支付宝公钥证书路径 */ - public void checkNotifySign(Map params) { + public void checkNotifySign(Map params, String aliCertPath) { //调用SDK验证签名 try { - boolean signVerified = AlipaySignature.rsaCertCheckV1(params, aliConfig.getAlipayCertPath(),"UTF-8","RSA2"); + boolean signVerified = AlipaySignature.rsaCertCheckV1(params, aliCertPath,"UTF-8","RSA2"); ServiceUtil.assertion(!signVerified, "验签失败"); } catch (Exception e) { throw new ServiceException("验签失败" + e.getMessage()); diff --git a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/syb/service/SybPayClient.java b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/syb/service/SybPayClient.java index 52800edd..4ea3539a 100644 --- a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/syb/service/SybPayClient.java +++ b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/syb/service/SybPayClient.java @@ -4,22 +4,20 @@ import com.alibaba.fastjson2.JSON; import com.ruoyi.common.pay.syb.config.SybConfig; import com.ruoyi.common.pay.syb.util.HttpConnectionUtil; import com.ruoyi.common.pay.syb.util.SybUtil; +import lombok.Data; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.springframework.stereotype.Service; -import java.math.BigDecimal; import java.util.Map; import java.util.TreeMap; @Component +@Data public class SybPayClient { @Autowired private SybConfig sybConfig; - - /** * * @param trxamt diff --git a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/syb/service/SybPayService.java b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/syb/service/SybPayService.java index 68cdb6d9..a74adaad 100644 --- a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/syb/service/SybPayService.java +++ b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/syb/service/SybPayService.java @@ -3,11 +3,11 @@ package com.ruoyi.common.pay.syb.service; import com.alibaba.fastjson2.JSON; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.pay.PayApi; +import com.ruoyi.common.pay.Payable; +import com.ruoyi.common.pay.Refundable; import com.ruoyi.common.pay.syb.config.SybConfig; import com.ruoyi.common.pay.syb.enums.SybTrxStatus; import com.ruoyi.common.pay.syb.util.SybUtil; -import com.ruoyi.common.pay.Payable; -import com.ruoyi.common.pay.Refundable; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.ServiceUtil; import com.ruoyi.common.utils.StringUtils; @@ -35,7 +35,10 @@ public class SybPayService implements PayApi { /** * 微信小程序预下单 */ - public PrepayWithRequestPaymentResponse pay(Payable payable) { + public PrepayWithRequestPaymentResponse pay(Payable payable, Object config) { + + // TODO + try { Map result = sybPayClient.pay( payable.payableFen().longValue(), @@ -97,7 +100,7 @@ public class SybPayService implements PayApi { /** * 使用商户自定义订单编号查询支付订单 */ - public Map queryByOutTradeNo(String outTradeNo) { + public Map queryByOutTradeNo(String outTradeNo, Object config) { try { return sybPayClient.query(outTradeNo, ""); } catch (Exception e) { @@ -108,7 +111,7 @@ public class SybPayService implements PayApi { /** * 微信退款 */ - public Map refund(Refundable refundAble) { + public Map refund(Refundable refundAble, Object config) { try { Map result = sybPayClient.refund( refundAble.refundAmount().getRefund(), @@ -126,8 +129,8 @@ public class SybPayService implements PayApi { } @Override - public boolean isPaySuccessByOutTradeNo(String outTradeNo) { - return isPaySuccess(this.queryByOutTradeNo(outTradeNo)); + public boolean isPaySuccessByOutTradeNo(String outTradeNo, Object config) { + return isPaySuccess(this.queryByOutTradeNo(outTradeNo, )); } @Override @@ -144,7 +147,7 @@ public class SybPayService implements PayApi { /** * 关闭微信支付订单 */ - public void closeByOutTradeNo(String outTradeNo) { + public void closeByOutTradeNo(String outTradeNo, Object config) { try { sybPayClient.close("", outTradeNo); } catch (Exception e) { diff --git a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/TmPayService.java b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/TmPayService.java index 0d8a0ef2..4bf4b116 100644 --- a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/TmPayService.java +++ b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/TmPayService.java @@ -4,12 +4,12 @@ import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.pay.PayApi; +import com.ruoyi.common.pay.Payable; +import com.ruoyi.common.pay.Refundable; import com.ruoyi.common.pay.tm.config.TmPayConfig; import com.ruoyi.common.pay.tm.enums.TmPayStatus; import com.ruoyi.common.pay.tm.vo.RefundInfo; import com.ruoyi.common.pay.tm.vo.TmTradeInfo; -import com.ruoyi.common.pay.Payable; -import com.ruoyi.common.pay.Refundable; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.ServiceUtil; import com.ruoyi.common.utils.http.HttpUtils; @@ -28,12 +28,15 @@ import java.util.Map; public class TmPayService implements PayApi { @Autowired - private TmPayConfig config; + private TmPayConfig defaultTmPayConfig; /** * 订单查询 */ - public TmTradeInfo queryByOutTradeNo(String outTradeNo) { + public TmTradeInfo queryByOutTradeNo(String outTradeNo, Object tmConfig) { + // 初始化配置 + TmPayConfig config = (TmPayConfig) tmConfig; + HashMap body = new HashMap<>(); body.put("outTradeId", outTradeNo); body.put("terminalType", "1"); @@ -55,7 +58,10 @@ public class TmPayService implements PayApi { /** * 退款 */ - public RefundInfo refund(Refundable refundAble) { + public RefundInfo refund(Refundable refundAble, Object tmConfig) { + // 初始化配置 + TmPayConfig config = (TmPayConfig) tmConfig; + HashMap body = new HashMap<>(); body.put("refundFee", String.valueOf(refundAble.refundAmount().getRefund())); body.put("terminalType", "1"); @@ -77,8 +83,8 @@ public class TmPayService implements PayApi { } @Override - public boolean isPaySuccessByOutTradeNo(String outTradeNo) { - TmTradeInfo result = queryByOutTradeNo(outTradeNo); + public boolean isPaySuccessByOutTradeNo(String outTradeNo, Object config) { + TmTradeInfo result = queryByOutTradeNo(outTradeNo, config); return isPaySuccess(result); } @@ -97,7 +103,10 @@ public class TmPayService implements PayApi { /** * 关闭订单 */ - public void closeByOutTradeNo(String outTradeNo) { + public void closeByOutTradeNo(String outTradeNo, Object tmConfig) { + // 初始化配置 + TmPayConfig config = (TmPayConfig) tmConfig; + HashMap body = new HashMap<>(); body.put("outTradeId", outTradeNo); body.put("terminalType", "1"); @@ -116,7 +125,10 @@ public class TmPayService implements PayApi { /** * 微信小程序支付 */ - public PrepayWithRequestPaymentResponse pay(Payable payable) { + public PrepayWithRequestPaymentResponse pay(Payable payable, Object tmConfig) { + // 初始化配置 + TmPayConfig config = (TmPayConfig) tmConfig; + HashMap body = new HashMap<>(); body.put("payAmount", String.valueOf(payable.payableFen())); body.put("terminalType", "1"); @@ -163,7 +175,9 @@ public class TmPayService implements PayApi { return response; } - public boolean validSign(Map params) { + public boolean validSign(Map params, String signKey) { + + // 获取传递过来的签名 String receivedSign = (String)params.get("sign"); // 获取签名字段 @@ -175,7 +189,7 @@ public class TmPayService implements PayApi { params.remove("sign"); // 按照请求时的签名逻辑,生成签名字符串 String paramsStr = TmPayUtil.getAsciiSort(params); // 按ASCII排序 - String generatedSign = TmPayUtil.getMD5Code(paramsStr + "&key=" + config.getSignKey()).toUpperCase(); // 重新生成签名 + String generatedSign = TmPayUtil.getMD5Code(paramsStr + "&key=" + signKey).toUpperCase(); // 重新生成签名 System.out.println("新生成的签名-----------:"+generatedSign); // 比较签名是否一致 return generatedSign.equals(receivedSign); diff --git a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/wx/config/WxPayConfig.java b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/wx/config/WxPayConfig.java index 67fb3cf4..4a784b58 100644 --- a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/wx/config/WxPayConfig.java +++ b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/wx/config/WxPayConfig.java @@ -8,8 +8,8 @@ import com.wechat.pay.java.service.payments.app.AppService; import com.wechat.pay.java.service.payments.jsapi.JsapiService; import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension; import com.wechat.pay.java.service.refund.RefundService; -import com.wechat.pay.java.service.transferbatch.TransferBatchService; import lombok.Getter; +import lombok.Setter; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -21,6 +21,7 @@ import org.springframework.context.annotation.Configuration; */ @Configuration @Getter +@Setter public class WxPayConfig { // 小程序id diff --git a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/wx/service/WxPayService.java b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/wx/service/WxPayService.java index efbd131e..acb68390 100644 --- a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/wx/service/WxPayService.java +++ b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/wx/service/WxPayService.java @@ -31,24 +31,25 @@ import java.time.LocalDateTime; public class WxPayService implements PayApi { @Autowired - private JsapiService jsapiService; + private JsapiService defaultJsapiService; @Autowired - private JsapiServiceExtension jsapiServiceExtension; + private JsapiServiceExtension defaultJsapiServiceExtension; @Autowired - private WxPayConfig wxPayConfig; + private WxPayConfig defaultWxPayConfig; @Autowired private RefundService refundService; private static final String CNY = "CNY"; - public PrepayWithRequestPaymentResponse pay(Payable payable) { - return this.prepayWithRequestPayment(payable.payableOutTradeNo(), payable.payableFen(), payable.payableDescription(), payable.payableOpenId(), payable.payableAttach()); + public PrepayWithRequestPaymentResponse pay(Payable payable, Object config) { + WxPayConfig wxPayConfig = (WxPayConfig) config; + return this.prepayWithRequestPayment(payable.payableOutTradeNo(), payable.payableFen(), payable.payableDescription(), payable.payableOpenId(), payable.payableAttach(), wxPayConfig); } - public PrepayWithRequestPaymentResponse prepayWithRequestPayment(String billNo, BigDecimal money, String description, String wxOpenId, String attach) { + public PrepayWithRequestPaymentResponse prepayWithRequestPayment(String billNo, BigDecimal money, String description, String wxOpenId, String attach, WxPayConfig wxPayConfig) { // 获取JSAPI所需参数 PrepayRequest request = new PrepayRequest(); request.setAmount(getAmount(money)); @@ -59,41 +60,45 @@ public class WxPayService implements PayApi { request.setNotifyUrl(wxPayConfig.getNotifyUrl()); request.setPayer(getPayer(wxOpenId)); request.setAttach(attach); - return jsapiServiceExtension.prepayWithRequestPayment(request); + return wxPayConfig.jsapiServiceExtension().prepayWithRequestPayment(request); } /** * 关闭支付订单 * * @param billNo 平台订单编号 + * @param config */ - public void closeByOutTradeNo(String billNo) { + public void closeByOutTradeNo(String billNo, Object config) { + // 初始化配置 + WxPayConfig wxPayConfig = (WxPayConfig) config; + CloseOrderRequest request = new CloseOrderRequest(); request.setMchid(wxPayConfig.getMerchantId()); request.setOutTradeNo(billNo); - jsapiService.closeOrder(request); + wxPayConfig.jsapiService().closeOrder(request); } - public Transaction queryOrderById(String prePayId) { - QueryOrderByIdRequest request = new QueryOrderByIdRequest(); - request.setMchid(wxPayConfig.getMerchantId()); - request.setTransactionId(prePayId); - return jsapiService.queryOrderById(request); - } + public Transaction queryByOutTradeNo(String billNo, Object config) { + // 初始化配置 + WxPayConfig wxPayConfig = (WxPayConfig) config; - public Transaction queryByOutTradeNo(String billNo) { QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest(); request.setMchid(wxPayConfig.getMerchantId()); request.setOutTradeNo(billNo); - return jsapiService.queryOrderByOutTradeNo(request); + return wxPayConfig.jsapiService().queryOrderByOutTradeNo(request); } /** * 发起退款 * * @param refund + * @param config */ - public Refund refund(Refundable refund) { + public Refund refund(Refundable refund, Object config) { + // 初始化配置 + WxPayConfig wxPayConfig = (WxPayConfig) config; + CreateRequest request = new CreateRequest(); request.setOutTradeNo(refund.refundOutTradeNo()); request.setOutRefundNo(refund.refundOutRefundNo()); @@ -107,8 +112,8 @@ public class WxPayService implements PayApi { } @Override - public boolean isPaySuccessByOutTradeNo(String outTradeNo) { - return isPaySuccess(this.queryByOutTradeNo(outTradeNo)); + public boolean isPaySuccessByOutTradeNo(String outTradeNo, Object config) { + return isPaySuccess(this.queryByOutTradeNo(outTradeNo, config)); } @Override diff --git a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java index f968f1a1..eeb0805a 100644 --- a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java +++ b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java @@ -2,7 +2,7 @@ package com.ruoyi.common.utils.file; /** * 媒体类型工具类 - * + * * @author ruoyi */ public class MimeTypeUtils @@ -16,7 +16,7 @@ public class MimeTypeUtils public static final String IMAGE_BMP = "image/bmp"; public static final String IMAGE_GIF = "image/gif"; - + public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" }; public static final String[] FLASH_EXTENSION = { "swf", "flv" }; @@ -36,7 +36,10 @@ public class MimeTypeUtils // 视频格式 "mp4", "avi", "rmvb", // pdf - "pdf" }; + "pdf", + // 证书 + "pem", "cert" + }; public static String getExtension(String prefix) { diff --git a/smart-switch-ruoyi/smart-switch-system/src/main/java/com/ruoyi/system/mapper/typehandler/ObjectJsonTypeHandler.java b/smart-switch-ruoyi/smart-switch-system/src/main/java/com/ruoyi/system/mapper/typehandler/ObjectJsonTypeHandler.java new file mode 100644 index 00000000..560af948 --- /dev/null +++ b/smart-switch-ruoyi/smart-switch-system/src/main/java/com/ruoyi/system/mapper/typehandler/ObjectJsonTypeHandler.java @@ -0,0 +1,8 @@ +package com.ruoyi.system.mapper.typehandler; + +/** + * @author wjh + * 2025/1/7 + */ +public class ObjectJsonTypeHandler extends AbstractJsonTypeHandler{ +} diff --git a/smart-switch-service/src/main/java/com/ruoyi/iot/service/IotService.java b/smart-switch-service/src/main/java/com/ruoyi/iot/service/IotService.java index a317d135..6a731623 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/iot/service/IotService.java +++ b/smart-switch-service/src/main/java/com/ruoyi/iot/service/IotService.java @@ -144,7 +144,7 @@ public interface IotService { /** * 上传数据 */ - CommandResponse uploadData(IotDevice device, String reason); + CommandResponse uploadData(IotDevice device, String reason, boolean recordLog); /** * 重启设备 diff --git a/smart-switch-service/src/main/java/com/ruoyi/iot/service/impl/IotServiceImpl.java b/smart-switch-service/src/main/java/com/ruoyi/iot/service/impl/IotServiceImpl.java index f234908d..893155a8 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/iot/service/impl/IotServiceImpl.java +++ b/smart-switch-service/src/main/java/com/ruoyi/iot/service/impl/IotServiceImpl.java @@ -100,7 +100,7 @@ public class IotServiceImpl implements IotService { if (StringUtils.isBlank(status)) { // log.info("进入command"); // 发送命令 - CommandResponse res = uploadData(deviceName, productId, "获取在线状态"); + CommandResponse res = uploadData(deviceName, productId, "获取在线状态", false); // 若是离线,则直接返回离线 if (res != null && res.isNotOnline()) { @@ -276,23 +276,23 @@ public class IotServiceImpl implements IotService { } @Override - public CommandResponse uploadData(IotDevice device, String reason) { + public CommandResponse uploadData(IotDevice device, String reason, boolean recordLog) { ServiceUtil.assertion(device == null || StringUtils.isBlank(device.getProductId()), "设备为空"); CommandResponse res = null; if (StringUtils.hasText(device.iotMac2())) { - res = this.uploadData(device.iotMac2(), device.getProductId(), reason); + res = this.uploadData(device.iotMac2(), device.getProductId(), reason, recordLog); } if ((res == null || !res.isSuccess()) && StringUtils.hasText(device.iotMac1())) { - res = this.uploadData(device.iotMac1(), device.getProductId(), reason); + res = this.uploadData(device.iotMac1(), device.getProductId(), reason, recordLog); } return res; } - private CommandResponse uploadData(String deviceName, String productId, String reason) { + private CommandResponse uploadData(String deviceName, String productId, String reason, boolean recordLog) { if (StringUtils.isBlank(deviceName) || StringUtils.isBlank(productId)) { return null; } - return sendCommand(deviceName, IotConstants.COMMAND_UPLOAD_DATA, productId, reason); + return sendCommand(deviceName, IotConstants.COMMAND_UPLOAD_DATA, productId, reason, recordLog); } private CommandResponse setVxs(String deviceName, BigDecimal vxs, String productId, String reason) { @@ -397,7 +397,7 @@ public class IotServiceImpl implements IotService { if (seconds < 0) { throw new ServiceException("设置剩余时长参数错误:读数不允许小于0"); } - return sendCommand(deviceName, IotConstants.COMMAND_RECHARGE + seconds + IotConstants.COMMAND_SEPARATOR, 5, productId, reason); + return sendCommand(deviceName, IotConstants.COMMAND_RECHARGE + seconds + IotConstants.COMMAND_SEPARATOR, 5, productId, reason, true); } @Override @@ -421,7 +421,7 @@ public class IotServiceImpl implements IotService { if (ele == null || ele.compareTo(BigDecimal.ZERO) < 0) { throw new ServiceException("充值电量错误:充值电量不允许小于0"); } - return sendCommand(deviceName, IotConstants.COMMAND_ADD_ELE + ele.multiply(BigDecimal.valueOf(1000)) + IotConstants.COMMAND_SEPARATOR, 5, productId, reason); + return sendCommand(deviceName, IotConstants.COMMAND_ADD_ELE + ele.multiply(BigDecimal.valueOf(1000)) + IotConstants.COMMAND_SEPARATOR, 5, productId, reason, true); } @Override @@ -445,7 +445,7 @@ public class IotServiceImpl implements IotService { if (ele == null) { throw new ServiceException("设置电量错误:电量不允许为空"); } - return sendCommand(deviceName, IotConstants.COMMAND_SET_ELE + ele.multiply(BigDecimal.valueOf(1000)) + IotConstants.COMMAND_SEPARATOR, 5, productId, reason); + return sendCommand(deviceName, IotConstants.COMMAND_SET_ELE + ele.multiply(BigDecimal.valueOf(1000)) + IotConstants.COMMAND_SEPARATOR, 5, productId, reason, true); } @Override @@ -532,11 +532,16 @@ public class IotServiceImpl implements IotService { } private CommandResponse sendCommand(String deviceName, String command, String productId, String reason) { - return sendCommand(deviceName, command, null, productId, reason); + return sendCommand(deviceName, command, null, productId, reason, true); + } + + + private CommandResponse sendCommand(String deviceName, String command, String productId, String reason, boolean recordLog) { + return sendCommand(deviceName, command, null, productId, reason, recordLog); } // 发送MQTT命令 - private CommandResponse sendCommand(String deviceName, String command, Integer timeout, String productId, String reason) { + private CommandResponse sendCommand(String deviceName, String command, Integer timeout, String productId, String reason, boolean recordLog) { if (timeout == null) { timeout = this.timeout; } @@ -550,8 +555,10 @@ public class IotServiceImpl implements IotService { ServiceUtil.assertion(!StringUtils.hasText(result), "与OneNet通信异常"); CommandResponse res = JSON.parseObject(result, CommandResponse.class); - // 记录日志 - this.addCommandLog(deviceName, command, res.getMsg(), reason, res.getCode()); + // 记录成功日志 + if (recordLog) { + this.addCommandLog(deviceName, command, res.getMsg(), reason, res.getCode()); + } // 若返回数据为离线或者超时,则判断设备是否在线 // if (IotHttpStatus.checkOnlineList().contains(res.getCode())) { diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/Channel.java b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/Channel.java index 495eb285..4bf2427e 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/Channel.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/Channel.java @@ -56,4 +56,16 @@ public class Channel extends BaseEntity @Excel(name = "适用平台(1微信 2支付宝)") @ApiModelProperty("适用平台(1微信 2支付宝)") private String platform; + + @Excel(name = "渠道API类型", readConverterExp = "1=微信支付,2=支付宝,3=银行卡,4=通联微信,5=太米微信") + @ApiModelProperty("渠道API类型") + private String apiType; + + @Excel(name = "渠道类型", readConverterExp = "1=官方渠道,2=自定义渠道") + @ApiModelProperty("渠道类型") + private String type; + + @Excel(name = "渠道配置") + @ApiModelProperty("渠道配置") + private ChannelConfig channelConfig; } diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/ChannelConfig.java b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/ChannelConfig.java new file mode 100644 index 00000000..11279f5e --- /dev/null +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/ChannelConfig.java @@ -0,0 +1,46 @@ +package com.ruoyi.ss.channel.domain; + +import lombok.Data; + +/** + * @author wjh + * 2025/1/7 + */ +@Data +public class ChannelConfig { + + // 微信 + // 应用id(微信、支付宝) + private String appId; + // 商户id + private String merchantId; + // apiV3私钥 + private String apiV3Key; + // 私钥证书路径 + private String privateKeyPath; + // 证书序列号 + private String merchantSerialNumber; + + + // 支付宝 + // 应用私钥 + private String privateKey; + // AES秘钥 + private String aesPrivateKey; + // 应用公钥证书地址 + private String appCertPath; + // 支付宝公钥证书地址 + private String alipayCertPath; + // 支付宝根证书地址 + private String alipayRootCertPath; + + + // 太米 + // 开发者ID + private String developerId; + // 门店ID + private String shopId; + // 签名Key + private String signKey; + +} diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/ChannelVO.java b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/ChannelVO.java index 64257874..31a25046 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/ChannelVO.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/ChannelVO.java @@ -7,5 +7,5 @@ import lombok.Data; * 2024/7/28 */ @Data -public class ChannelVO extends Channel{ +public class ChannelVO extends Channel { } diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/enums/ChannelEnum.java b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/enums/ChannelApiType.java similarity index 58% rename from smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/enums/ChannelEnum.java rename to smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/enums/ChannelApiType.java index 91b19160..be79fbf9 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/enums/ChannelEnum.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/enums/ChannelApiType.java @@ -22,23 +22,23 @@ import java.util.stream.Collectors; */ @Getter @AllArgsConstructor -public enum ChannelEnum { +public enum ChannelApiType { - WECHAT(1L, "微信支付", AccountType.WECHAT, WxPayService.class, false), - ALI(2L, "支付宝", AccountType.ALIPAY, AliPayService.class, true), - BANK(3L, "银行卡", AccountType.BANK_CARD, null, false), - BALANCE(4L, "余额支付", null, null, true), - TL_WX(5L, "通联微信支付", null, SybPayService.class, true), - TM_WX(6L, "太米微信支付", null, TmPayService.class, true); + WECHAT("1", "微信支付", AccountType.WECHAT, WxPayService.class, false), + ALI("2", "支付宝", AccountType.ALIPAY, AliPayService.class, true), + BANK("3", "银行卡", AccountType.BANK_CARD, null, false), + BALANCE("4", "余额支付", null, null, true), + TL_WX("5", "通联微信支付", null, SybPayService.class, true), + TM_WX("6", "太米微信支付", null, TmPayService.class, true); - private final Long type; + private final String type; private final String name; private final AccountType accountType; private final Class payApi; private final Boolean isRefundSync; // 退款是否同步通知 - public static ChannelEnum parse(Long type) { - for (ChannelEnum value : ChannelEnum.values()) { + public static ChannelApiType parse(String type) { + for (ChannelApiType value : ChannelApiType.values()) { if (Objects.equals(value.getType(), type)) { return value; } @@ -46,15 +46,15 @@ public enum ChannelEnum { return null; } - public static List asList(ChannelEnum...types) { - return Arrays.stream(types).map(ChannelEnum::getType).collect(Collectors.toList()); + public static List asList(ChannelApiType...types) { + return Arrays.stream(types).map(ChannelApiType::getType).collect(Collectors.toList()); } /** * 获取支付API */ - public static PayApi getPayApi(Long type) { - ChannelEnum parse = parse(type); + public static PayApi getPayApi(String type) { + ChannelApiType parse = parse(type); if (parse == null || parse.getPayApi() == null) { return null; } diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/enums/ChannelType.java b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/enums/ChannelType.java new file mode 100644 index 00000000..d68faee6 --- /dev/null +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/domain/enums/ChannelType.java @@ -0,0 +1,20 @@ +package com.ruoyi.ss.channel.domain.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author wjh + * 2025/1/7 + */ +@Getter +@AllArgsConstructor +public enum ChannelType { + + SYSTEM("1", "系统预设"), + CUSTOM("2", "自定义"); + + private final String type; + private final String msg; + +} diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/channel/mapper/ChannelMapper.java b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/mapper/ChannelMapper.java index 894a0fb1..99190f02 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/channel/mapper/ChannelMapper.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/mapper/ChannelMapper.java @@ -62,4 +62,11 @@ public interface ChannelMapper * @return 结果 */ public int deleteSmChannelByChannelIds(Long[] channelIds); + + /** + * 逻辑删除 + * @param ids + * @return + */ + int logicDel(@Param("ids") List ids); } diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/channel/mapper/ChannelMapper.xml b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/mapper/ChannelMapper.xml index e03a6da8..1cf2c363 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/channel/mapper/ChannelMapper.xml +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/mapper/ChannelMapper.xml @@ -7,6 +7,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + @@ -18,7 +19,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" sc.cost_rate, sc.service_type, sc.picture, - sc.platform + sc.platform, + sc.api_type, + sc.type, + sc.channel_config, + sc.deleted from sm_channel sc @@ -26,7 +31,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and sc.name like concat('%', #{query.name}, '%') and sc.enabled = #{query.enabled} and sc.service_type = #{query.serviceType} - and platform = #{query.platform} + and sc.platform = #{query.platform} + and sc.api_type = #{query.apiType} + and sc.type = #{query.type} + and sc.deleted = false + and sc.deleted = #{query.deleted} and sc.channel_id in @@ -58,6 +67,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" service_type, picture, platform, + api_type, + type, + channel_config, #{channelId}, @@ -68,6 +80,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{serviceType}, #{picture}, #{platform}, + #{apiType}, + #{type}, + #{channelConfig,typeHandler=com.ruoyi.ss.channel.mapper.typehandler.ChannelConfigJsonTypeHandler}, @@ -81,10 +96,23 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" service_type = #{data.serviceType}, picture = #{data.picture}, platform = #{data.platform}, + api_type = #{data.apiType}, + type = #{data.type}, + channel_config = #{data.channelConfig,typeHandler=com.ruoyi.ss.channel.mapper.typehandler.ChannelConfigJsonTypeHandler}, where channel_id = #{data.channelId} + + update sm_channel + set deleted = true + where channel_id in + + #{channelId} + + and deleted = false + + delete from sm_channel where channel_id = #{channelId} diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/channel/mapper/typehandler/ChannelConfigJsonTypeHandler.java b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/mapper/typehandler/ChannelConfigJsonTypeHandler.java new file mode 100644 index 00000000..aeec7039 --- /dev/null +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/mapper/typehandler/ChannelConfigJsonTypeHandler.java @@ -0,0 +1,11 @@ +package com.ruoyi.ss.channel.mapper.typehandler; + +import com.ruoyi.ss.channel.domain.ChannelConfig; +import com.ruoyi.system.mapper.typehandler.AbstractJsonTypeHandler; + +/** + * @author wjh + * 2025/1/7 + */ +public class ChannelConfigJsonTypeHandler extends AbstractJsonTypeHandler { +} diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/channel/service/ChannelConverter.java b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/service/ChannelConverter.java new file mode 100644 index 00000000..71273d31 --- /dev/null +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/service/ChannelConverter.java @@ -0,0 +1,15 @@ +package com.ruoyi.ss.channel.service; + +import com.ruoyi.ss.channel.domain.ChannelVO; + +/** + * @author wjh + * 2025/1/7 + */ +public interface ChannelConverter { + + /** + * 转换渠道信息为渠道配置 + */ + Object toConfig(ChannelVO channel); +} diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/channel/service/ChannelService.java b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/service/ChannelService.java index 3d4b2207..eaf91bca 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/channel/service/ChannelService.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/service/ChannelService.java @@ -79,4 +79,13 @@ public interface ChannelService */ Map selectMap(ChannelQuery query, Function keyMapper); + /** + * 批量逻辑删除 + */ + int logicDel(List ids); + + /** + * 根据id查询 + */ + List selectByIds(List ids); } diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/channel/service/impl/ChannelConverterImpl.java b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/service/impl/ChannelConverterImpl.java new file mode 100644 index 00000000..9d7d20bf --- /dev/null +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/service/impl/ChannelConverterImpl.java @@ -0,0 +1,38 @@ +package com.ruoyi.ss.channel.service.impl; + +import com.ruoyi.common.pay.wx.config.WxPayConfig; +import com.ruoyi.ss.channel.domain.ChannelConfig; +import com.ruoyi.ss.channel.domain.ChannelVO; +import com.ruoyi.ss.channel.domain.enums.ChannelApiType; +import com.ruoyi.ss.channel.service.ChannelConverter; +import org.springframework.stereotype.Service; + +/** + * @author wjh + * 2025/1/7 + */ +@Service +public class ChannelConverterImpl implements ChannelConverter { + @Override + public Object toConfig(ChannelVO channel) { + if (channel == null || channel.getChannelConfig() == null) { + return null; + } + + ChannelConfig channelConfig = channel.getChannelConfig(); + + if (ChannelApiType.WECHAT.getType().equals(channel.getApiType())) { + WxPayConfig config = new WxPayConfig(); + config.setAppId(channelConfig.getAppId()); + config.setMerchantId(channelConfig.getMerchantId()); + config.setApiV3Key(channelConfig.getApiV3Key()); + // TODO + config.setNotifyUrl(""); + config.setRefundNotifyUrl(); + config.setPrivateKeyPath(channelConfig.getPrivateKeyPath()); + config.setMerchantSerialNumber(channelConfig.getMerchantSerialNumber()); + return config; + } + //TODO 其他渠道 + } +} diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/channel/service/impl/ChannelServiceImpl.java b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/service/impl/ChannelServiceImpl.java index 7db58edd..cad12b32 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/channel/service/impl/ChannelServiceImpl.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/channel/service/impl/ChannelServiceImpl.java @@ -1,10 +1,12 @@ package com.ruoyi.ss.channel.service.impl; +import com.ruoyi.common.utils.ServiceUtil; import com.ruoyi.common.utils.collection.CollectionUtils; import com.ruoyi.ss.account.service.AccountService; import com.ruoyi.ss.channel.domain.Channel; import com.ruoyi.ss.channel.domain.ChannelQuery; import com.ruoyi.ss.channel.domain.ChannelVO; +import com.ruoyi.ss.channel.domain.enums.ChannelType; import com.ruoyi.ss.channel.mapper.ChannelMapper; import com.ruoyi.ss.channel.service.ChannelService; import org.springframework.beans.factory.annotation.Autowired; @@ -123,4 +125,33 @@ public class ChannelServiceImpl implements ChannelService } return list.stream().collect(Collectors.toMap(keyMapper, item -> item)); } + + @Override + public int logicDel(List ids) { + if (CollectionUtils.isEmptyElement(ids)) { + return 0; + } + + List channelList = this.selectByIds(ids); + if (CollectionUtils.isEmpty(channelList)) { + return 0; + } + + // 校验 + for (ChannelVO channel : channelList) { + ServiceUtil.assertion(ChannelType.SYSTEM.getType().equals(channel.getType()), "不允许删除系统预设渠道 \"%s\"}", channel.getName()); + } + + return channelMapper.logicDel(ids); + } + + @Override + public List selectByIds(List ids) { + if (CollectionUtils.isEmptyElement(ids)) { + return Collections.emptyList(); + } + ChannelQuery query = new ChannelQuery(); + query.setChannelIds(ids); + return this.selectSmChannelList(query); + } } diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/impl/DeviceServiceImpl.java b/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/impl/DeviceServiceImpl.java index adb8bb80..85fdc8ba 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/impl/DeviceServiceImpl.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/impl/DeviceServiceImpl.java @@ -1257,7 +1257,7 @@ public class DeviceServiceImpl implements DeviceService @Override public int uploadData(DeviceVO device, String reason) { ServiceUtil.assertion(device == null, "设备不存在"); - CommandResponse res = iotService.uploadData(device, reason); + CommandResponse res = iotService.uploadData(device, reason, true); return res != null && res.isSuccess() ? 1 : 0; } diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/payBill/service/impl/PayBillServiceImpl.java b/smart-switch-service/src/main/java/com/ruoyi/ss/payBill/service/impl/PayBillServiceImpl.java index 24b7d8f0..51355079 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/payBill/service/impl/PayBillServiceImpl.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/payBill/service/impl/PayBillServiceImpl.java @@ -5,9 +5,6 @@ import com.ruoyi.common.core.redis.enums.RedisLockKey; import com.ruoyi.common.domain.vo.LocalDateDecimalVO; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.pay.PayApi; -import com.ruoyi.common.pay.ali.service.AliPayService; -import com.ruoyi.common.pay.syb.service.SybPayService; -import com.ruoyi.common.pay.tm.TmPayService; import com.ruoyi.common.pay.wx.service.WxPayService; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.ServiceUtil; @@ -15,7 +12,10 @@ import com.ruoyi.common.utils.SnowFlakeUtil; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.collection.CollectionUtils; import com.ruoyi.common.utils.spring.SpringUtils; -import com.ruoyi.ss.channel.domain.enums.ChannelEnum; +import com.ruoyi.ss.channel.domain.ChannelVO; +import com.ruoyi.ss.channel.domain.enums.ChannelApiType; +import com.ruoyi.ss.channel.service.ChannelConverter; +import com.ruoyi.ss.channel.service.ChannelService; import com.ruoyi.ss.payBill.domain.PayBill; import com.ruoyi.ss.payBill.domain.PayBillQuery; import com.ruoyi.ss.payBill.domain.PayBillVO; @@ -77,13 +77,10 @@ public class PayBillServiceImpl implements PayBillService private RefundService refundService; @Autowired - private SybPayService sybPayService; + private ChannelService channelService; @Autowired - private TmPayService tmPayService; - - @Autowired - private AliPayService aliPayService; + private ChannelConverter channelConverter; /** * 查询支付订单 @@ -226,17 +223,25 @@ public class PayBillServiceImpl implements PayBillService for (PayBillVO bill : payingList) { // 关闭支付中的订单 if (PayBillStatus.PAYING.getStatus().equals(bill.getStatus())) { + + // TODO 查询渠道信息 + ChannelVO channel = channelService.selectSmChannelByChannelId(bill.getChannelId()); + if (channel == null) { + continue; + } + // 获取支付API - PayApi payApi = ChannelEnum.getPayApi(bill.getChannelId()); + PayApi payApi = ChannelApiType.getPayApi(channel.getApiType()); if (payApi == null) { continue; } + // 调用关闭API try { - payApi.closeByOutTradeNo(bill.getPayNo()); + payApi.closeByOutTradeNo(bill.getPayNo(), channelConverter.toConfig(channel)); } catch (Exception e) { // 关闭失败,尝试查询订单信息,判断是否已经支付成功 - if (payApi.isPaySuccessByOutTradeNo(bill.getPayNo())) { + if (payApi.isPaySuccessByOutTradeNo(bill.getPayNo(), channelConverter.toConfig(channel))) { throw new ServiceException("当前交易已成功,无法关闭"); } else { log.error("关闭支付订单失败: payNo = {} 原因:{}", bill.getPayNo(), e.getMessage()); @@ -333,9 +338,9 @@ public class PayBillServiceImpl implements PayBillService this.handleSuccess(bill.getPayNo(), LocalDateTime.now()); }, 1L, TimeUnit.SECONDS); } else { - PayApi payApi = ChannelEnum.getPayApi(bill.getChannelId()); + PayApi payApi = ChannelApiType.getPayApi(bill.getChannelId()); ServiceUtil.assertion(payApi == null, "暂不支持该支付方式"); - vo.setPayParams(payApi.pay(bill)); + vo.setPayParams(payApi.pay(bill, )); // 异步刷新支付结果 scheduledExecutorService.schedule(() -> { this.refreshPayResultMaxCount(bill, 20L, TimeUnit.SECONDS, 10); @@ -513,13 +518,13 @@ public class PayBillServiceImpl implements PayBillService } // 获取支付API - PayApi payApi = ChannelEnum.getPayApi(bill.getChannelId()); + PayApi payApi = ChannelApiType.getPayApi(bill.getChannelId()); if (payApi == null) { return PayResultVO.fail("暂不支持该支付方式"); } // 获取支付结果 - Object result = payApi.queryByOutTradeNo(bill.getPayNo()); + Object result = payApi.queryByOutTradeNo(bill.getPayNo(), ); if (payApi.isPaySuccess(result)) { return PayResultVO.success(payApi.getPayTime(result), result); } else { diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/refund/service/impl/RefundServiceImpl.java b/smart-switch-service/src/main/java/com/ruoyi/ss/refund/service/impl/RefundServiceImpl.java index 29c5b593..6b68ea1a 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/refund/service/impl/RefundServiceImpl.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/refund/service/impl/RefundServiceImpl.java @@ -3,15 +3,13 @@ package com.ruoyi.ss.refund.service.impl; import com.ruoyi.common.domain.vo.LocalDateDecimalVO; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.pay.PayApi; -import com.ruoyi.common.pay.syb.enums.SybTrxStatus; import com.ruoyi.common.pay.syb.service.SybPayService; import com.ruoyi.common.pay.tm.TmPayService; -import com.ruoyi.common.pay.tm.enums.TmRefundStatus; -import com.ruoyi.common.pay.tm.vo.RefundInfo; import com.ruoyi.common.pay.wx.service.WxPayService; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.ServiceUtil; import com.ruoyi.common.utils.SnowFlakeUtil; +import com.ruoyi.ss.channel.domain.enums.ChannelApiType; import com.ruoyi.ss.payBill.service.PayBillService; import com.ruoyi.ss.refund.domain.Refund; import com.ruoyi.ss.refund.domain.RefundQuery; @@ -19,7 +17,6 @@ import com.ruoyi.ss.refund.domain.RefundVO; import com.ruoyi.ss.refund.domain.enums.RefundStatus; import com.ruoyi.ss.refund.mapper.RefundMapper; import com.ruoyi.ss.refund.service.RefundService; -import com.ruoyi.ss.channel.domain.enums.ChannelEnum; import com.ruoyi.ss.transactionBill.service.TransactionBillService; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -27,7 +24,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.support.TransactionTemplate; import java.util.List; -import java.util.Map; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -196,15 +192,15 @@ public class RefundServiceImpl implements RefundService RefundVO vo = this.selectRefundByRefundNo(refund.getRefundNo()); // 发起退款 - PayApi payApi = ChannelEnum.getPayApi(refund.getChannelId()); + PayApi payApi = ChannelApiType.getPayApi(refund.getChannelId()); if (payApi == null) { throw new ServiceException("当前支付方式不支持退款"); } - payApi.refund(vo); + payApi.refund(vo, ); // 判断是否同步通知,若是则直接处理支付成功 - ChannelEnum channelEnum = ChannelEnum.parse(refund.getChannelId()); - if (channelEnum != null && channelEnum.getIsRefundSync() != null && channelEnum.getIsRefundSync()) { + ChannelApiType channelApiType = ChannelApiType.parse(refund.getChannelId()); + if (channelApiType != null && channelApiType.getIsRefundSync() != null && channelApiType.getIsRefundSync()) { scheduledExecutorService.schedule(() -> { this.handleRefundSuccess(refund.getRefundNo()); }, 10, TimeUnit.SECONDS); diff --git a/smart-switch-web/src/main/java/com/ruoyi/web/controller/app/AppPayController.java b/smart-switch-web/src/main/java/com/ruoyi/web/controller/app/AppPayController.java index 3a9ab034..d8876430 100644 --- a/smart-switch-web/src/main/java/com/ruoyi/web/controller/app/AppPayController.java +++ b/smart-switch-web/src/main/java/com/ruoyi/web/controller/app/AppPayController.java @@ -15,19 +15,19 @@ import com.ruoyi.common.pay.syb.service.SybPayService; import com.ruoyi.common.pay.syb.util.SybUtil; import com.ruoyi.common.pay.tm.TmPayService; import com.ruoyi.common.pay.tm.enums.TmPayStatus; +import com.ruoyi.common.pay.wx.domain.enums.AttachEnums; import com.ruoyi.common.pay.wx.domain.enums.WxNotifyEventType; import com.ruoyi.common.pay.wx.domain.enums.WxTransferBatchStatus; import com.ruoyi.common.pay.wx.util.WxPayUtil; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.http.HttpUtils; +import com.ruoyi.ss.channel.domain.enums.ChannelApiType; import com.ruoyi.ss.payBill.service.PayBillService; import com.ruoyi.ss.refund.service.RefundService; import com.ruoyi.ss.transactionBill.domain.dto.RechargePayBO; -import com.ruoyi.ss.channel.domain.enums.ChannelEnum; import com.ruoyi.ss.transactionBill.domain.vo.TransactionBillVO; import com.ruoyi.ss.transactionBill.service.TransactionBillConverter; import com.ruoyi.ss.transactionBill.service.TransactionBillService; -import com.ruoyi.common.pay.wx.domain.enums.AttachEnums; import com.wechat.pay.java.core.exception.ValidationException; import com.wechat.pay.java.core.notification.Notification; import com.wechat.pay.java.service.payments.model.Transaction; @@ -85,7 +85,7 @@ public class AppPayController extends BaseController { if (bill == null || bill.getUserId() == null || !bill.getUserId().equals(getUserId())) { return error("这不是您的订单"); } - RechargePayBO bo = transactionBillConverter.toRechargePayBO(bill, ChannelEnum.WECHAT.getType()); + RechargePayBO bo = transactionBillConverter.toRechargePayBO(bill, ChannelApiType.WECHAT.getType()); return success(transactionBillService.pay(bo)); } @@ -217,8 +217,8 @@ public class AppPayController extends BaseController { log.info("【太米微信支付回调】接收对象 : " + body); // 先把body转成map Map params = JSON.parseObject(body, Map.class); - // 验证签名 - boolean sign = tmPayService.validSign(params); + // TODO signKey 验证签名 + boolean sign = tmPayService.validSign(params, null); if (sign) { JSONObject tradeInfo = (JSONObject)params.get("tradeInfo"); String payType = tradeInfo.getString("payType"); // 交易类型 @@ -243,7 +243,8 @@ public class AppPayController extends BaseController { try { log.info("收到支付宝支付通知{}", request); Map params = HttpUtils.convertRequestParamsToMap(request); - aliPayService.checkNotifySign(params); + // TODO + aliPayService.checkNotifySign(params, null); log.info("收到支付宝支付通知{}", params); diff --git a/smart-switch-web/src/main/java/com/ruoyi/web/controller/ss/SmChannelController.java b/smart-switch-web/src/main/java/com/ruoyi/web/controller/ss/SmChannelController.java index 916f34d3..9e9d50bf 100644 --- a/smart-switch-web/src/main/java/com/ruoyi/web/controller/ss/SmChannelController.java +++ b/smart-switch-web/src/main/java/com/ruoyi/web/controller/ss/SmChannelController.java @@ -1,29 +1,24 @@ package com.ruoyi.web.controller.ss; -import java.util.List; -import javax.servlet.http.HttpServletResponse; - -import com.ruoyi.common.core.domain.ValidGroup; -import com.ruoyi.ss.channel.domain.ChannelQuery; -import com.ruoyi.ss.channel.domain.ChannelVO; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.ss.channel.domain.Channel; -import com.ruoyi.ss.channel.service.ChannelService; -import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.domain.ValidGroup; import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.ss.channel.domain.Channel; +import com.ruoyi.ss.channel.domain.ChannelQuery; +import com.ruoyi.ss.channel.domain.ChannelVO; +import com.ruoyi.ss.channel.domain.enums.ChannelType; +import com.ruoyi.ss.channel.service.ChannelService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import java.util.List; /** * 充值渠道Controller @@ -82,13 +77,47 @@ public class SmChannelController extends BaseController public AjaxResult edit(@RequestBody @Validated(ValidGroup.Update.class) Channel form) { Channel channel = new Channel(); + channel.setName(form.getName()); channel.setChannelId(form.getChannelId()); channel.setEnabled(form.getEnabled()); - channel.setServiceRate(form.getServiceRate()); channel.setCostRate(form.getCostRate()); channel.setServiceType(form.getServiceType()); channel.setPicture(form.getPicture()); + channel.setApiType(form.getApiType()); + channel.setPlatform(form.getPlatform()); + channel.setChannelConfig(form.getChannelConfig()); return toAjax(smChannelService.updateSmChannel(channel)); } + /** + * 新增充值渠道 + */ + @PreAuthorize("@ss.hasPermi('system:channel:add')") + @Log(title = "充值渠道", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody @Validated(ValidGroup.Create.class) Channel form) + { + Channel channel = new Channel(); + channel.setName(form.getName()); + channel.setType(ChannelType.CUSTOM.getType()); + channel.setEnabled(form.getEnabled()); + channel.setCostRate(form.getCostRate()); + channel.setServiceType(form.getServiceType()); + channel.setPicture(form.getPicture()); + channel.setApiType(form.getApiType()); + channel.setPlatform(form.getPlatform()); + channel.setChannelConfig(form.getChannelConfig()); + return toAjax(smChannelService.insertSmChannel(channel)); + } + + /** + * 新增充值渠道 + */ + @PreAuthorize("@ss.hasPermi('system:channel:delete')") + @Log(title = "充值渠道", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public AjaxResult delete(@PathVariable List ids) { + return toAjax(smChannelService.logicDel(ids)); + } + }