diff --git a/pay/pom.xml b/pay/pom.xml
new file mode 100644
index 0000000..0558d6f
--- /dev/null
+++ b/pay/pom.xml
@@ -0,0 +1,59 @@
+
+
+
+ ruoyi
+ com.ruoyi
+ 3.8.6
+
+ 4.0.0
+ pay
+ 1.0.0-SNAPSHOT
+
+
+ 8
+ 8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure
+ 2.7.10
+ true
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.22
+
+
+ com.alibaba
+ fastjson
+ 1.2.72
+
+
+ cn.hutool
+ hutool-all
+ 5.7.12
+
+
+ com.github.wechatpay-apiv3
+ wechatpay-apache-httpclient
+ 0.4.7
+
+
+ com.alipay.sdk
+ alipay-sdk-java
+ 4.34.8.ALL
+
+
+
+
+
\ No newline at end of file
diff --git a/pay/src/main/java/com/ruoyi/CallBackService.java b/pay/src/main/java/com/ruoyi/CallBackService.java
new file mode 100644
index 0000000..29fb770
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/CallBackService.java
@@ -0,0 +1,32 @@
+package com.ruoyi;
+
+/**
+ * 业务回调处理接口
+ */
+public interface CallBackService {
+
+ /**
+ * 成功支付--处理业务逻辑
+ * @param orderSn 订单号
+ */
+ void successPay(String orderSn);
+
+ /**
+ * 失败支付-处理业务逻辑
+ * @param orderSn 订单号
+ */
+ void failPay(String orderSn);
+
+ /**
+ * 退款成功-处理业务逻辑
+ * @param orderSn 订单号
+ */
+ void successRefund(String orderSn);
+
+ /**
+ * 退款失败-处理业务逻辑
+ * @param orderSn 订单号
+ */
+ void failRefund(String orderSn);
+
+}
diff --git a/pay/src/main/java/com/ruoyi/ElegentPay.java b/pay/src/main/java/com/ruoyi/ElegentPay.java
new file mode 100644
index 0000000..e79ae0e
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/ElegentPay.java
@@ -0,0 +1,66 @@
+package com.ruoyi;
+
+
+import com.ruoyi.dto.*;
+import com.ruoyi.exceptions.TradeException;
+
+public interface ElegentPay {
+
+
+ /**
+ * 统一下单接口
+ * @param payRequest 支付请求
+ * @param tradeType 交易类型
+ * @param platform 平台
+ * @return 支付响应
+ * @throws TradeException
+ */
+ PayResponse requestPay(PayRequest payRequest, String tradeType, String platform) throws TradeException;
+
+
+ /**
+ * 关闭订单
+ * @param orderSn 订单号
+ * @param platform 平台
+ * @return 是否成功关闭订单
+ * @throws TradeException
+ */
+ Boolean closePay(String orderSn, String platform) throws TradeException;
+
+ /**
+ * 退款
+ * @param refundRequest 退款请求封装对象
+ * @param platform 平台
+ * @return 是否成功退款
+ * @throws TradeException
+ */
+ Boolean refund(RefundRequest refundRequest, String platform) throws TradeException;
+
+ /**
+ * 根据订单号查询订单
+ * @param orderSn 订单号
+ * @param platform 平台
+ * @return 查询响应对象
+ * @throws TradeException
+ */
+ QueryResponse queryTradingOrderNo(String orderSn , String platform) throws TradeException;
+
+
+ /**
+ * 查询单笔退款API
+ * @param orderSn 订单号
+ * @param platform 平台
+ * @return 查询退款响应对象
+ * @throws TradeException
+ */
+ QueryRefundResponse queryRefundTrading(String orderSn , String platform) throws TradeException;
+
+
+ /**
+ * 获得openID
+ * @param code
+ * @return
+ */
+ public String getOpenid(String code, String platform);
+
+}
diff --git a/pay/src/main/java/com/ruoyi/ali/AlipayConfig.java b/pay/src/main/java/com/ruoyi/ali/AlipayConfig.java
new file mode 100644
index 0000000..1648dde
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/ali/AlipayConfig.java
@@ -0,0 +1,40 @@
+package com.ruoyi.ali;
+
+import com.ruoyi.key.KeyManager;
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 支付宝权限对接类
+ */
+@Component
+@ConfigurationProperties("elegent.pay.alipay")
+@Data
+public class AlipayConfig {
+ /**
+ * 应用识别码
+ */
+ private String appId;
+
+ /**
+ * 密钥加密方式 RSA2
+ */
+ @Value("${elegent.pay.alipay.charset:RSA2}")
+ private String signType;
+
+ @Autowired
+ private KeyManager keyManager;
+
+ public String getPrivateKey(){
+ return keyManager.getKey("alipay_private.key");
+ }
+
+ public String getPublicKey(){
+ return keyManager.getKey("alipay_public.key");
+ }
+
+
+}
\ No newline at end of file
diff --git a/pay/src/main/java/com/ruoyi/ali/AlipayConstant.java b/pay/src/main/java/com/ruoyi/ali/AlipayConstant.java
new file mode 100644
index 0000000..db7417d
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/ali/AlipayConstant.java
@@ -0,0 +1,30 @@
+package com.ruoyi.ali;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * ZFBConstant
+ * @description 支付宝相关的常量
+*/
+public class AlipayConstant {
+
+ public static final String SUCCESS = "SUCCESS";
+
+ public static final String FAIL = "FAIL";
+
+ /**
+ * 交易状态(用于转换)
+ */
+ public static final Map TRADE_STATE = new HashMap(){
+ {
+ put("TRADE_SUCCESS", "SUCCESS");
+ put("WAIT_BUYER_PAY", "NOTPAY");
+ put("TRADE_CLOSED", "CLOSED");
+ put("TRADE_FINISHED", "FINISHED");
+ }
+ };
+
+ public static final String domain="https://openapi.alipay.com/gateway.do";
+
+}
diff --git a/pay/src/main/java/com/ruoyi/ali/AlipayElegentTrade.java b/pay/src/main/java/com/ruoyi/ali/AlipayElegentTrade.java
new file mode 100644
index 0000000..aefd560
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/ali/AlipayElegentTrade.java
@@ -0,0 +1,461 @@
+package com.ruoyi.ali;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.alipay.api.AlipayApiException;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.DefaultAlipayClient;
+import com.alipay.api.request.*;
+import com.alipay.api.response.*;
+import com.ruoyi.CallBackService;
+import com.ruoyi.annotation.TradePlatform;
+import com.ruoyi.config.CallbackConfig;
+import com.ruoyi.constant.PayConstant;
+import com.ruoyi.constant.Platform;
+import com.ruoyi.constant.TradeType;
+import com.ruoyi.core.ElegentTrade;
+import com.ruoyi.dto.*;
+import com.ruoyi.exceptions.TradeException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.Map;
+
+/**
+ * 支付宝支付的策略类
+ * @author wgl
+ */
+@Service
+@TradePlatform(Platform.ALI)
+@Slf4j
+public class AlipayElegentTrade implements ElegentTrade {
+
+ @Autowired
+ private AlipayConfig alipayConfig;
+
+ @Autowired
+ private CallbackConfig callbackConfig;
+
+ @Autowired
+ private CallBackService callBackService;
+
+
+ /**
+ * 获取回调地址
+ * @return
+ */
+ private String getPayNotifyUrl(){
+ return callbackConfig.getDomain()+ PayConstant.CALLBACK_PATH+ PayConstant.NOTIFY +"/"+ Platform.ALI;
+ }
+
+ /**
+ * 获取退款回调
+ * @return
+ */
+ private String getRefundNotifyUrl(){
+ return callbackConfig.getDomain()+ PayConstant.CALLBACK_PATH+ PayConstant.REFUND_NOTIFY +"/"+ Platform.ALI;
+ }
+
+
+
+ /**
+ * 创建支付订单
+ * @param payRequest
+ * @return
+ * @throws TradeException
+ */
+ @Override
+ public PayResponse requestPay(PayRequest payRequest, String tradeType) throws TradeException {
+ if(TradeType.NATIVE.equals( tradeType )){
+ return createNativeOrder(payRequest);
+ }
+ if(TradeType.JSAPI.equals( tradeType )){
+ return createJsApiOrder(payRequest);
+ }
+ if(TradeType.H5.equals( tradeType )){
+ return createH5Order(payRequest);
+ }
+ if(TradeType.APP.equals( tradeType )){
+ return createAPPOrder(payRequest);
+ }
+ return createNativeOrder(payRequest);
+ }
+
+
+ /**
+ * 本地支付(扫码)
+ * https://opendocs.alipay.com/open/194/106078?ref=api#预下单
+ * @param payRequest
+ * @return
+ * @throws TradeException
+ */
+ private PayResponse createNativeOrder(PayRequest payRequest) throws TradeException {
+ try {
+ AlipayClient alipayClient = getAliHttpClient();
+ AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
+
+ request.setNotifyUrl(getPayNotifyUrl());
+
+ JSONObject bizContent = new JSONObject();
+ bizContent.put("out_trade_no", payRequest.getOrderSn());
+ //转换
+ //String totalFee= BigDecimal.valueOf(payRequest.getTotalFee()).divide(new BigDecimal(100) ).toString();
+ bizContent.put("total_amount", fenToYuan(payRequest.getTotalFee()));
+ bizContent.put("subject", payRequest.getBody());
+ request.setBizContent(bizContent.toString());
+ AlipayTradePrecreateResponse response = alipayClient.execute(request);
+
+ if (response.isSuccess()) {
+ PayResponse payResponse =new PayResponse();
+ payResponse.setSuccess(true);
+ payResponse.setCode_url(response.getQrCode()); //本地支付二维码
+ payResponse.setOrder_sn(payRequest.getOrderSn());
+ return payResponse;
+ } else {
+ log.error("调用失败");
+ return null;
+ }
+ }catch (Exception e){
+ e.printStackTrace();
+ throw new TradeException("订单创建失败,订单号:"+ payRequest.getOrderSn());
+ }
+ }
+
+
+ /**
+ * 小程序
+ * https://opendocs.alipay.com/mini/03l5wn
+ * @param payRequest
+ * @return
+ * @throws TradeException
+ */
+ private PayResponse createJsApiOrder(PayRequest payRequest) throws TradeException {
+ AlipayClient alipayClient = getAliHttpClient();
+ try {
+ AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
+ request.setNotifyUrl(getPayNotifyUrl());
+ JSONObject bizContent = new JSONObject();
+ bizContent.put("out_trade_no", payRequest.getOrderSn());
+ bizContent.put("total_amount", fenToYuan( payRequest.getTotalFee() ));
+ bizContent.put("subject", payRequest.getBody());
+ bizContent.put("buyer_id", payRequest.getOpenid());
+ bizContent.put("timeout_express", "10m");
+ request.setBizContent(bizContent.toString());
+ AlipayTradeCreateResponse response = alipayClient.sdkExecute(request);
+ if (response.isSuccess()) {
+ PayResponse payResponse =new PayResponse();
+ payResponse.setSuccess(true);
+ payResponse.setPrepay_id(response.getTradeNo());
+ payResponse.setOrder_sn(response.getOutTradeNo());
+ return payResponse;
+ } else {
+ log.error("调用失败");
+ return null;
+ }
+ }catch (Exception e){
+ throw new TradeException("订单创建失败,订单号:"+ payRequest.getOrderSn());
+ }
+ }
+
+
+ /**
+ * H5
+ * https://opendocs.alipay.com/mini/03l5wn
+ * @param payRequest
+ * @return
+ * @throws TradeException
+ */
+ private PayResponse createH5Order(PayRequest payRequest) throws TradeException {
+ AlipayClient alipayClient = getAliHttpClient();
+ try {
+ AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
+ request.setNotifyUrl(getPayNotifyUrl());
+ request.setReturnUrl("");
+ JSONObject bizContent = new JSONObject();
+ bizContent.put("out_trade_no", payRequest.getOrderSn());
+ bizContent.put("total_amount", fenToYuan( payRequest.getTotalFee() ));
+ bizContent.put("subject", payRequest.getBody());
+ bizContent.put("product_code", "QUICK_WAP_WAY");
+
+ request.setBizContent(bizContent.toString());
+ AlipayTradeWapPayResponse response = alipayClient.pageExecute(request);
+ if (response.isSuccess()) {
+ PayResponse payResponse =new PayResponse();
+ payResponse.setSuccess(true);
+ payResponse.setPrepay_id(response.getTradeNo());
+ payResponse.setOrder_sn(response.getOutTradeNo());
+ return payResponse;
+ } else {
+ log.error("调用失败");
+ return null;
+ }
+ }catch (Exception e){
+ throw new TradeException("订单创建失败,订单号:"+ payRequest.getOrderSn());
+ }
+ }
+
+
+ /**
+ * APP
+ * https://opendocs.alipay.com/open/02e7gq?ref=api&scene=20
+ * @param payRequest
+ * @return
+ * @throws TradeException
+ */
+ private PayResponse createAPPOrder(PayRequest payRequest) throws TradeException {
+ AlipayClient alipayClient = getAliHttpClient();
+ try {
+ AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
+ request.setNotifyUrl(getPayNotifyUrl());
+ JSONObject bizContent = new JSONObject();
+ bizContent.put("out_trade_no", payRequest.getOrderSn());
+ bizContent.put("total_amount", fenToYuan( payRequest.getTotalFee() ));
+ bizContent.put("subject", payRequest.getBody());
+ bizContent.put("product_code", "QUICK_MSECURITY_PAY");
+
+ request.setBizContent(bizContent.toString());
+ AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
+ if (response.isSuccess()) {
+ PayResponse payResponse =new PayResponse();
+ payResponse.setSuccess(true);
+ payResponse.setPrepay_id(response.getTradeNo());
+ payResponse.setOrder_sn(response.getOutTradeNo());
+ return payResponse;
+ } else {
+ log.error("调用失败");
+ return null;
+ }
+ }catch (Exception e){
+ throw new TradeException("订单创建失败,订单号:"+ payRequest.getOrderSn());
+ }
+ }
+
+
+
+ /**
+ * 关闭订单
+ * @param orderSn
+ * @return
+ * @throws TradeException
+ */
+ @Override
+ public Boolean closePay(String orderSn) throws TradeException {
+ try {
+ AlipayClient alipayClient = getAliHttpClient();
+ AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
+ JSONObject bizContent = new JSONObject();
+ bizContent.put("trade_no", orderSn);
+ request.setBizContent(bizContent.toString());
+ AlipayTradeCloseResponse response = alipayClient.execute(request);
+ if (response.isSuccess()) {
+ log.info("调用成功");
+ return true;
+ } else {
+ log.error("调用失败");
+ return false;
+ }
+ }catch (Exception e){
+ throw new TradeException("订单关闭失败,订单号:"+orderSn);
+ }
+ }
+
+ /**
+ * 退款接口
+ * alipay.trade.refund(统一收单交易退款接口)
+ * https://opendocs.alipay.com/open/02ekfk
+ * @param refundRequest
+ * @return
+ * @throws TradeException
+ */
+ @Override
+ public Boolean refund(RefundRequest refundRequest) throws TradeException {
+ try {
+ AlipayClient alipayClient = getAliHttpClient();
+ AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
+ request.setNotifyUrl(getRefundNotifyUrl()); //退款回调
+ JSONObject bizContent = new JSONObject();
+ bizContent.put("refund_amount", fenToYuan(refundRequest.getRefundAmount() ));
+ bizContent.put("out_trade_no", refundRequest.getOrderSn());
+ //退款请求号,做幂等性校验
+ if(refundRequest.getRequestNo()!=null){
+ bizContent.put("out_request_no", refundRequest.getRequestNo());
+ }else{
+ bizContent.put("out_request_no", refundRequest.getOrderSn());
+ }
+ request.setBizContent(bizContent.toString());
+ AlipayTradeRefundResponse response = alipayClient.execute(request);
+ if (response.isSuccess()) {
+ if("Y".equals(response.getFundChange())) {
+ log.info("退款成功{}",refundRequest.getOrderSn());
+ callBackService.successRefund(refundRequest.getOrderSn());
+ return true;
+ }else{
+ //退款失败
+ log.error("退款失败{}",refundRequest.getOrderSn());
+ callBackService.failRefund(refundRequest.getOrderSn());
+ return false;
+ }
+ } else {
+ log.error("退款调用失败{}",refundRequest.getOrderSn());
+ return false;
+ }
+ }catch (Exception e){
+ e.printStackTrace();
+ throw new TradeException("订单退款失败,订单号:"+ refundRequest.getOrderSn());
+ }
+ }
+
+ /**
+ * 查询单笔交易订单
+ * 参考官网: https://opendocs.alipay.com/open/02e7gm?ref=api#请求示例
+ *
+ * @param orderSn
+ * @return
+ * @throws TradeException
+ */
+ @Override
+ public QueryResponse queryTradingOrderNo(String orderSn) throws TradeException {
+ AlipayClient alipayClient = getAliHttpClient();
+ try {
+ AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
+ JSONObject bizContent = new JSONObject();
+ bizContent.put("out_trade_no", orderSn);
+ request.setBizContent(bizContent.toString());
+ AlipayTradeQueryResponse response = alipayClient.execute(request);
+ QueryResponse queryResponse=new QueryResponse();
+ queryResponse.setOrder_sn(orderSn );
+ if (response.isSuccess()) {
+ queryResponse.setTransaction_id( response.getTradeNo() );
+ queryResponse.setTrade_state(AlipayConstant.TRADE_STATE.get( response.getTradeStatus()) );//交易状态
+
+ //int total = BigDecimal.valueOf(Double.valueOf(response.getTotalAmount())).multiply(new BigDecimal(100)).intValue();
+ queryResponse.setTotal( yuanToFen(response.getTotalAmount()) ); //总金额
+
+ //int buyer_pay_amount = BigDecimal.valueOf(Double.valueOf(response.getBuyerPayAmount())).multiply(new BigDecimal(100)).intValue();
+ //queryResponse.setPayer_total( yuanToFen(response.getBuyerPayAmount()) );//支付金额
+
+ queryResponse.setOpenid( response.getBuyerUserId());
+ Map map = JSON.parseObject(response.getBody(), Map.class ) ;
+ queryResponse.setExpand(map);//全部数据
+ return queryResponse;
+ } else {
+ queryResponse.setTrade_state("NOTPAY");
+ return queryResponse;
+ }
+ }catch (Exception e){
+ e.printStackTrace();
+ //throw new TradeException("订单查询失败,订单号:"+orderSn);
+ return null;
+ }
+ }
+
+ /**
+ * 查询退款订单
+ * @param orderSn
+ * @return
+ * @throws TradeException
+ */
+ @Override
+ public QueryRefundResponse queryRefundTrading(String orderSn) throws TradeException {
+ try {
+ AlipayClient alipayClient = getAliHttpClient();
+ AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
+ JSONObject bizContent = new JSONObject();
+ bizContent.put("out_request_no", orderSn);
+ request.setBizContent(bizContent.toString());
+ AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request);
+ if (response.isSuccess()) {
+ log.info("调用成功");
+ Map map = JSON.parseObject(response.getBody(), Map.class );
+
+ QueryRefundResponse queryRefundResponse=new QueryRefundResponse();
+
+ queryRefundResponse.setOrder_sn( (String) map.get("out_trade_no") );
+ queryRefundResponse.setTransaction_id( (String) map.get("trade_no") );
+ queryRefundResponse.setTotal( (Integer) map.get("total_amount") ); //总金额
+ //queryRefundResponse.setPayer_total( (Integer) map.get("total_amount") );//支付金额
+ queryRefundResponse.setRefund((Integer) map.get("refund_amount") ); //退款金额
+ queryRefundResponse.setRefund_id((String) map.get("trade_no") ); //退款单号
+ queryRefundResponse.setOut_refund_no( (String) map.get("out_request_no") );//退款订单号
+ //queryRefundResponse.setChannel( (String) map.get("channel") ); //通道
+ //queryRefundResponse.setUser_received_account( (String) map.get("user_received_account") ); //账号
+ queryRefundResponse.setStatus( (String) map.get("refund_status") ); //状态
+ queryRefundResponse.setSuccess_time( (String) map.get("gmt_refund_pay") );
+ //queryRefundResponse.setCreate_time( (String) map.get("gmt_refund_pay") );
+
+ queryRefundResponse.setExpand(map);
+ return queryRefundResponse;
+
+ } else {
+ log.error("调用失败");
+ return null;
+ }
+ }catch (Exception e){
+ e.printStackTrace();
+ //throw new TradeException("退款订单查询失败,订单号:"+ orderSn);
+ return null;
+ }
+ }
+
+ @Override
+ public String getOpenid(String code) {
+ AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
+ alipayConfig.getAppId(), alipayConfig.getPrivateKey(), "json", "utf-8", alipayConfig.getPublicKey(), alipayConfig.getSignType());
+ AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
+ request.setCode(code);
+ request.setGrantType("authorization_code");
+ try {
+ AlipaySystemOauthTokenResponse oauthTokenResponse = alipayClient.execute(request);
+ return oauthTokenResponse.getUserId();
+ } catch (AlipayApiException e) {
+ //处理异常
+ e.printStackTrace();
+ return "";
+ }
+ }
+
+
+ /**
+ * 获取支付宝连接
+ * 参考官网:https://opendocs.alipay.com/open/01csp3?ref=api#公钥模式加签
+ * 公钥模式加签
+ * @return
+ */
+ private AlipayClient getAliHttpClient(){
+ try {
+ com.alipay.api.AlipayConfig alipayConfig = new com.alipay.api.AlipayConfig();
+ alipayConfig.setServerUrl(AlipayConstant.domain);
+ alipayConfig.setAppId(this.alipayConfig.getAppId());
+ alipayConfig.setPrivateKey(this.alipayConfig.getPrivateKey());
+ alipayConfig.setFormat("json");
+ alipayConfig.setCharset("utf-8");
+ alipayConfig.setAlipayPublicKey(this.alipayConfig.getPublicKey());
+ alipayConfig.setSignType(this.alipayConfig.getSignType());
+ //构造client
+ AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig);
+ return alipayClient;
+ }catch (Exception e){
+ e.printStackTrace();
+ throw new TradeException("支付宝支付--初始化,校验系统参数失败");
+ }
+
+ }
+
+ /**
+ * 分转换为元
+ * @param fen
+ * @return
+ */
+ private String fenToYuan(int fen){
+ //转换为元
+ return BigDecimal.valueOf(fen).divide(new BigDecimal(100) ).toString();
+ }
+
+ private int yuanToFen(String yuan){
+ return BigDecimal.valueOf(Double.valueOf(yuan)).multiply(new BigDecimal(100)).intValue();
+ }
+
+
+}
\ No newline at end of file
diff --git a/pay/src/main/java/com/ruoyi/ali/AlipayElegentValid.java b/pay/src/main/java/com/ruoyi/ali/AlipayElegentValid.java
new file mode 100644
index 0000000..0052a4f
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/ali/AlipayElegentValid.java
@@ -0,0 +1,124 @@
+package com.ruoyi.ali;
+
+
+import com.alipay.api.internal.util.AlipaySignature;
+import com.ruoyi.annotation.TradePlatform;
+import com.ruoyi.constant.Platform;
+import com.ruoyi.core.ElegentValid;
+import com.ruoyi.dto.ValidResponse;
+import com.ruoyi.exceptions.TradeException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+@Service
+@TradePlatform(Platform.ALI)
+@Slf4j
+public class AlipayElegentValid implements ElegentValid {
+
+
+ @Autowired
+ private AlipayConfig alipayConfig;
+
+
+ /**
+ * 订单回调结果通知验签
+ * 参考代码: https://opendocs.alipay.com/open/194/103296?ref=api 异步返回结果的验签
+ * @param httpEntity
+ * @param httpRequest
+ * @return
+ */
+ @Override
+ public ValidResponse validPay(HttpEntity httpEntity, HttpServletRequest httpRequest) throws TradeException {
+ ValidResponse validResponse=new ValidResponse();
+ try {
+ Map params = getParams(httpRequest);
+ //获取支付宝POST过来反馈信息,将异步通知中收到的待验证所有参数都存放到map中
+ //String body = httpEntity.getBody();
+ //调用SDK验证签名
+ //公钥验签示例代码
+ boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.getPublicKey(), "utf-8", alipayConfig.getSignType());
+ if (signVerified) {
+ validResponse.setValid(true);
+ validResponse.setOrderSn((String) params.get("out_trade_no"));
+ return validResponse;
+ } else {
+ validResponse.setValid(false);
+ validResponse.setOrderSn( (String) params.get("out_trade_no") );
+ return validResponse;
+ }
+ }catch (Exception e){
+ e.printStackTrace();
+ throw new TradeException("验签异常");
+ }
+ }
+
+ /**
+ * 退款结果通知验签
+ * 参考官网 https://opendocs.alipay.com/support/01ravh
+ * @param httpEntity
+ * @param httpRequest
+ * @return
+ * @throws TradeException
+ */
+ @Override
+ public ValidResponse validRefund(HttpEntity httpEntity, HttpServletRequest httpRequest) throws TradeException {
+ ValidResponse validResponse=new ValidResponse();
+
+ try {
+ //获取支付宝POST过来反馈信息,将异步通知中收到的待验证所有参数都存放到map中
+ Map params = getParams(httpRequest);
+ //调用SDK验证签名
+ //公钥验签示例代码
+ boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.getPublicKey(), "utf-8", alipayConfig.getSignType());
+ if (signVerified) {
+ validResponse.setValid(true);
+ validResponse.setOrderSn( (String) params.get("out_trade_no") );
+ return validResponse;
+ } else {
+ validResponse.setValid(false);
+ validResponse.setOrderSn( (String) params.get("out_trade_no") );
+ return validResponse;
+ }
+ }catch (Exception e){
+ e.printStackTrace();
+ validResponse.setValid(false);
+ return validResponse;
+ }
+ }
+
+ private Map getParams(HttpServletRequest httpServletRequest){
+ Map params = new HashMap< String , String >();
+ Map requestParams = httpServletRequest.getParameterMap();
+
+ for(Iterator iter = requestParams.keySet().iterator(); iter.hasNext();){
+ String name = (String)iter.next();
+ String[] values = (String [])requestParams.get(name);
+ String valueStr = "";
+ for(int i = 0;i < values.length;i ++ ){
+ valueStr = (i==values.length-1)?valueStr + values [i]:valueStr + values[i] + ",";
+ }
+ //乱码解决,这段代码在出现乱码时使用。
+ //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
+ params.put (name,valueStr);
+ }
+ log.info("params:{}",params);
+ return params;
+ }
+
+ @Override
+ public String successResult() {
+ return AlipayConstant.SUCCESS;
+ }
+
+ @Override
+ public String failResult() {
+ return AlipayConstant.FAIL;
+ }
+}
diff --git a/pay/src/main/java/com/ruoyi/annotation/TradePlatform.java b/pay/src/main/java/com/ruoyi/annotation/TradePlatform.java
new file mode 100644
index 0000000..3cb71be
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/annotation/TradePlatform.java
@@ -0,0 +1,20 @@
+package com.ruoyi.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * create by: wgl
+ * desc: 自定义支付平台注解,支付平台 微信:wx 支付宝:zfb
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface TradePlatform {
+
+ /**
+ * 平台的id
+ * Platform.WX
+ * @return
+ */
+ String value();
+}
diff --git a/pay/src/main/java/com/ruoyi/config/CallbackConfig.java b/pay/src/main/java/com/ruoyi/config/CallbackConfig.java
new file mode 100644
index 0000000..2c656ee
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/config/CallbackConfig.java
@@ -0,0 +1,23 @@
+package com.ruoyi.config;
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 微信权限对接类
+ */
+@Component
+@ConfigurationProperties("elegent.pay.callback")
+@Data
+public class CallbackConfig {
+
+ private String domain; //回调域名
+
+ @Value("${elegent.pay.callback.watch:false}")
+ private boolean watch; //是否开启监听
+
+ @Value("${elegent.pay.callback.cycle:10}")
+ private int cycle;//检查周期
+
+}
\ No newline at end of file
diff --git a/pay/src/main/java/com/ruoyi/constant/PayConstant.java b/pay/src/main/java/com/ruoyi/constant/PayConstant.java
new file mode 100644
index 0000000..77695ce
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/constant/PayConstant.java
@@ -0,0 +1,11 @@
+package com.ruoyi.constant;
+
+public class PayConstant {
+
+ public final static String CALLBACK_PATH = "/payCallBack";
+
+ public final static String NOTIFY = "/notify";
+
+ public final static String REFUND_NOTIFY = "/refund_notify";
+
+}
diff --git a/pay/src/main/java/com/ruoyi/constant/Platform.java b/pay/src/main/java/com/ruoyi/constant/Platform.java
new file mode 100644
index 0000000..fd9a8d9
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/constant/Platform.java
@@ -0,0 +1,16 @@
+package com.ruoyi.constant;
+
+/**
+ * Platform
+ * 支付方式
+*/
+public class Platform {
+ /**
+ * 微信
+ */
+ public final static String WX = "wxpay";
+ /**
+ * 支付宝
+ */
+ public final static String ALI = "alipay";
+}
diff --git a/pay/src/main/java/com/ruoyi/constant/TradeType.java b/pay/src/main/java/com/ruoyi/constant/TradeType.java
new file mode 100644
index 0000000..c0a7ace
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/constant/TradeType.java
@@ -0,0 +1,33 @@
+package com.ruoyi.constant;
+
+import lombok.Data;
+
+/**
+ * 交易类型
+ */
+@Data
+public class TradeType {
+
+ /**
+ * native(扫码)
+ */
+ public final static String NATIVE = "native";
+
+ /**
+ * jsapi(小程序)
+ */
+ public final static String JSAPI = "jsapi";
+
+
+ /**
+ * app
+ */
+ public final static String APP = "app";
+
+
+ /**
+ * h5
+ */
+ public final static String H5 = "h5";
+
+}
diff --git a/pay/src/main/java/com/ruoyi/core/CallBackServiceImpl.java b/pay/src/main/java/com/ruoyi/core/CallBackServiceImpl.java
new file mode 100644
index 0000000..ea0148d
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/core/CallBackServiceImpl.java
@@ -0,0 +1,35 @@
+package com.ruoyi.core;
+
+import com.ruoyi.CallBackService;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 回调类
+ */
+@Slf4j
+public class CallBackServiceImpl implements CallBackService {
+
+
+ @Override
+ public void successPay(String orderSn) {
+ log.info("支付成功回调!"+orderSn);
+ }
+
+ @Override
+ public void failPay(String orderSn) {
+ log.info("支付失败回调!"+orderSn);
+ }
+
+
+ @Override
+ public void successRefund(String orderSn) {
+ log.info("退款成功回调!"+orderSn);
+ }
+
+ @Override
+ public void failRefund(String orderSn) {
+ log.info("退款失败回调!"+orderSn);
+ }
+
+
+}
diff --git a/pay/src/main/java/com/ruoyi/core/CallbackController.java b/pay/src/main/java/com/ruoyi/core/CallbackController.java
new file mode 100644
index 0000000..8b7170f
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/core/CallbackController.java
@@ -0,0 +1,90 @@
+package com.ruoyi.core;
+
+import com.ruoyi.CallBackService;
+import com.ruoyi.constant.PayConstant;
+import com.ruoyi.dto.ValidResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * CallbackController
+ * @description 系统默认提供的微信回调的Controller
+*/
+@RestController
+@Slf4j
+@RequestMapping(PayConstant.CALLBACK_PATH)
+public class CallbackController {
+
+ @Autowired
+ private CallBackService callBackService;
+
+ /**
+ * 系统提供的默认的微信回调的接口(支付回调)
+ * @param httpEntity
+ * @param response
+ * @return
+ */
+ @RequestMapping( PayConstant.NOTIFY + "/{platform}")
+ public String notify(HttpEntity httpEntity, HttpServletRequest request, HttpServletResponse response, @PathVariable("platform") String platform){
+
+ ElegentValid elegentValid = ElegentLoader.getElegentValid(platform); //获取验证器
+ try {
+ ValidResponse validResponse = elegentValid.validPay(httpEntity, request);//验证支付通知
+ String orderSn =validResponse.getOrderSn(); //订单号
+ if(validResponse.isValid()){ //返回码成功
+ callBackService.successPay(orderSn);
+ //返回成功消费
+ return elegentValid.successResult();
+ }else{
+ callBackService.failPay(orderSn);
+ return elegentValid.failResult();
+ }
+ }catch (Exception e){
+ log.error("支付回调处理失败",e);
+ //微信返回的状态非正常
+ return elegentValid.failResult();
+ }
+ }
+
+
+ /**
+ * 系统提供的默认的微信回调的接口(退款通知)
+ *
+ * @param httpEntity
+ * @param response
+ * @return
+ */
+ @RequestMapping( PayConstant.REFUND_NOTIFY + "/{platform}")
+ public String refundNotify(HttpEntity httpEntity, HttpServletRequest request, HttpServletResponse response,@PathVariable("platform") String platform) {
+
+ ElegentValid elegentValid = ElegentLoader.getElegentValid(platform); //获取验证器
+
+ try {
+ ValidResponse validResponse = elegentValid.validRefund(httpEntity, request);
+ String orderSn = validResponse.getOrderSn();
+ //订单号
+ if (validResponse.isValid()) { //返回码成功
+ callBackService.successRefund(orderSn);
+ //返回成功消费
+ return elegentValid.successResult();
+ } else {
+ callBackService.failRefund(orderSn);
+ return elegentValid.failResult();
+ }
+ } catch (Exception e) {
+ log.error("退款回调处理失败", e);
+ //微信返回的状态非正常
+ return elegentValid.failResult();
+ }
+
+ }
+
+
+}
diff --git a/pay/src/main/java/com/ruoyi/core/CallbackWatch.java b/pay/src/main/java/com/ruoyi/core/CallbackWatch.java
new file mode 100644
index 0000000..5bfe85e
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/core/CallbackWatch.java
@@ -0,0 +1,73 @@
+package com.ruoyi.core;
+
+
+
+import com.ruoyi.CallBackService;
+import com.ruoyi.ElegentPay;
+import com.ruoyi.config.CallbackConfig;
+import com.ruoyi.dto.QueryRefundResponse;
+import com.ruoyi.dto.QueryResponse;
+import com.ruoyi.dto.WatchDTO;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Component;
+import javax.annotation.PostConstruct;
+import java.util.Timer;
+import java.util.TimerTask;
+
+@Component
+@ConditionalOnProperty(prefix = "elegent.pay.callback",name = "watch",havingValue = "true")
+@Slf4j
+public class CallbackWatch {
+
+ @Autowired
+ private CallBackService callBackService;
+
+ @Autowired
+ private CallbackConfig callbackConfig;
+
+ @Autowired
+ private ElegentPay elegentPay;
+
+ @PostConstruct
+ public void queryWatch(){
+ if(callbackConfig.getCycle()<=0){
+ return;
+ }
+ //log.info("开启支付结果定期巡检");
+ Timer timer = new Timer();
+ // 2、创建 TimerTask 任务线程
+ TimerTask task=new TimerTask() {
+ @Override
+ public void run() {
+ try{
+ //查询支付状态
+ //log.info("支付状态定期巡检,{}",WatchList.payList);
+ for( WatchDTO watchDTO: WatchList.payList ){
+ //查询订单是否支付成功
+ QueryResponse queryResponse = elegentPay.queryTradingOrderNo(watchDTO.getOrderSn(),watchDTO.getPlatform());
+ if("SUCCESS".equals(queryResponse.getTrade_state())){
+ callBackService.successPay(queryResponse.getOrder_sn());
+ WatchList.payList.remove(watchDTO );
+ }
+ }
+ //log.info("退款状态定期巡检,{}",WatchList.refundList);
+ //查询退款状态
+ for( WatchDTO watchDTO: WatchList.refundList ){
+ //查询退款中订单
+ QueryRefundResponse queryResponse = elegentPay.queryRefundTrading( watchDTO.getOrderSn(),watchDTO.getPlatform());
+ if("SUCCESS".equals(queryResponse.getStatus())){
+ callBackService.successRefund(queryResponse.getOrder_sn());
+ WatchList.refundList.remove(watchDTO);
+ }
+ }
+ }catch (Exception ex){
+ }
+ }
+ };
+ // 4、启动定时任务
+ timer.schedule(task, callbackConfig.getCycle()*1000, callbackConfig.getCycle()*1000);
+ }
+
+}
diff --git a/pay/src/main/java/com/ruoyi/core/ElegentConfig.java b/pay/src/main/java/com/ruoyi/core/ElegentConfig.java
new file mode 100644
index 0000000..34cde57
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/core/ElegentConfig.java
@@ -0,0 +1,27 @@
+package com.ruoyi.core;
+
+
+import com.ruoyi.CallBackService;
+import com.ruoyi.key.KeyManager;
+import com.ruoyi.key.impl.DefaultKeyManager;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ElegentConfig {
+
+ @Bean
+ @ConditionalOnMissingBean
+ public CallBackService callBackService(){
+ return new CallBackServiceImpl();
+ }
+
+
+ @Bean
+ @ConditionalOnMissingBean
+ public KeyManager keyManager(){
+ return new DefaultKeyManager();
+ }
+
+}
diff --git a/pay/src/main/java/com/ruoyi/core/ElegentLoader.java b/pay/src/main/java/com/ruoyi/core/ElegentLoader.java
new file mode 100644
index 0000000..36dcb8b
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/core/ElegentLoader.java
@@ -0,0 +1,82 @@
+package com.ruoyi.core;
+
+import com.ruoyi.annotation.TradePlatform;
+import com.ruoyi.exceptions.TradeException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * PlatformLoader
+ * @description 第三方支付平台类加载器
+ * 服务启动的时候自动加载第三方支付组件
+*/
+@Component
+@Slf4j
+public class ElegentLoader implements ApplicationContextAware {
+
+ private static Map elegentTradeMap = new HashMap<>();
+
+ private static Map elegentValidMap = new HashMap<>();
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+
+ //加载所有的交易实现类
+ Collection elegentTrades = applicationContext.getBeansOfType(ElegentTrade.class).values();
+ elegentTrades.stream().forEach(e->{
+ //通过反射拿到类上的平台注解
+ TradePlatform annotation = e.getClass().getAnnotation(TradePlatform.class);
+ if (annotation != null) {
+ elegentTradeMap.put(annotation.value(), e);
+ }
+ });
+
+ //加载所有的验证实现类
+ Collection elegentValids = applicationContext.getBeansOfType(ElegentValid.class).values();
+ elegentValids.stream().forEach(e->{
+ //通过反射拿到类上的平台注解
+ TradePlatform annotation = e.getClass().getAnnotation(TradePlatform.class);
+ if (annotation != null) {
+ elegentValidMap.put(annotation.value(), e);
+ }
+ });
+
+ }
+
+ /**
+ * 根据平台id获取具体的第三方平台
+ * @param platform 平台id
+ * @return
+ */
+ public static ElegentTrade getElegentTrade(String platform){
+ ElegentTrade elegentPayTemplate = elegentTradeMap.get(platform);
+ if(elegentPayTemplate!=null){
+ return elegentPayTemplate;
+ }else{
+ throw new TradeException("未找到适配的交易类型,交易平台id:"+platform);
+ }
+ }
+
+
+ /**
+ * 根据平台id获取具体的验证类
+ * @param platform 平台id
+ * @return
+ */
+ public static ElegentValid getElegentValid(String platform){
+ ElegentValid elegentValidTemplate = elegentValidMap.get(platform);
+ if(elegentValidTemplate!=null){
+ return elegentValidTemplate;
+ }else{
+ throw new TradeException("未找到适配的交易类型,交易平台id:"+platform);
+ }
+ }
+
+}
diff --git a/pay/src/main/java/com/ruoyi/core/ElegentPayImpl.java b/pay/src/main/java/com/ruoyi/core/ElegentPayImpl.java
new file mode 100644
index 0000000..97f84d2
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/core/ElegentPayImpl.java
@@ -0,0 +1,136 @@
+package com.ruoyi.core;
+import com.ruoyi.ElegentPay;
+import com.ruoyi.config.CallbackConfig;
+import com.ruoyi.dto.*;
+import com.ruoyi.exceptions.TradeException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * ElegentPayTemplate
+ * @description 统一模板 在模板层进行第三方平台的选择
+*/
+@Component
+public class ElegentPayImpl implements ElegentPay {
+
+ @Autowired
+ private CallbackConfig callbackConfig;
+
+ /**
+ * 统一下单接口
+ * @param payRequest
+ * @return
+ */
+ @Override
+ public PayResponse requestPay(PayRequest payRequest, String tradeType, String platform) throws TradeException {
+ //获取交易策略
+ PayResponse payResponse = getPlatFormService(platform).requestPay(payRequest, tradeType);
+
+ //加入监听列表
+ if(callbackConfig.isWatch()){
+ WatchDTO watchDTO=new WatchDTO();
+ watchDTO.setOrderSn(payRequest.getOrderSn());
+ watchDTO.setPlatform(platform);
+ WatchList.payList.add( watchDTO );
+ }
+ return payResponse;
+ }
+
+
+ /**
+ * 关闭订单
+ * @param orderSn
+ * @param platform
+ * @return
+ * @throws Exception
+ */
+ @Override
+ public Boolean closePay(String orderSn, String platform) throws TradeException {
+ //调用对应第三方的创建订单接口
+ Boolean aBoolean = getPlatFormService(platform).closePay(orderSn);
+ //加入监听列表
+ if(callbackConfig.isWatch()){
+ WatchDTO watchDTO=new WatchDTO();
+ watchDTO.setOrderSn(orderSn);
+ watchDTO.setPlatform(platform);
+ WatchList.payList.remove( watchDTO );
+ }
+
+ return aBoolean;
+ }
+
+ /**
+ * 退款方法
+ * @param refundRequest
+ * @return
+ * @throws Exception
+ */
+ @Override
+ public Boolean refund(RefundRequest refundRequest, String platform) throws TradeException {
+ Boolean refund = getPlatFormService(platform).refund(refundRequest);
+ //加入监听列表
+ if(callbackConfig.isWatch() && refund){
+ WatchDTO watchDTO=new WatchDTO();
+ watchDTO.setOrderSn(refundRequest.getRequestNo());
+ watchDTO.setPlatform(platform);
+ WatchList.refundList.add( watchDTO );
+ }
+ return refund;
+ }
+
+
+ /**
+ * 手动查询订单的方法
+ * 商户订单号查询 根据订单号查询订单
+ * 该接口基于生成的订单号来进行订单的查询
+ * 可以基于查询的结果判断用户订单是否支付成功
+ * @param orderSn
+ * @param Platform
+ * @return
+ * @throws Exception
+ */
+ @Override
+ public QueryResponse queryTradingOrderNo(String orderSn , String Platform) throws TradeException {
+ //调用具体第三方的退款接口
+ return getPlatFormService(Platform).queryTradingOrderNo(orderSn);
+ }
+
+
+ /**
+ * 查询退款单号
+ *
+ * @return
+ * @throws Exception
+ */
+ @Override
+ public QueryRefundResponse queryRefundTrading(String orderSn , String platform) throws TradeException {
+ //获取请求参数
+ return getPlatFormService(platform).queryRefundTrading(orderSn);
+ }
+
+ /**
+ * 获得openId
+ * @param code
+ * @param platform
+ * @return
+ */
+ @Override
+ public String getOpenid(String code, String platform) {
+ return getPlatFormService(platform).getOpenid(code);
+ }
+
+/**
+ * ====================================提供的模板类需要使用的方法=====================================
+ */
+
+
+ /**
+ * 跟进具体内容获取实现类的方法
+ * @param platForm
+ * @return
+ */
+ private ElegentTrade getPlatFormService(String platForm) {
+ return ElegentLoader.getElegentTrade(platForm);
+ }
+
+}
diff --git a/pay/src/main/java/com/ruoyi/core/ElegentTrade.java b/pay/src/main/java/com/ruoyi/core/ElegentTrade.java
new file mode 100644
index 0000000..4474da3
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/core/ElegentTrade.java
@@ -0,0 +1,54 @@
+package com.ruoyi.core;
+
+
+import com.ruoyi.dto.*;
+import com.ruoyi.exceptions.TradeException;
+
+public interface ElegentTrade {
+
+
+ /**
+ * 单独的创建本地支付订单接口
+ * 该接口基于设计模式实现,对接了微信V3版支付代码和支付宝支付sdk
+ * 业务编写人员仅仅只需要准备好请求参数调用该方法即可完成下单请求
+ * @return 交易数据对象 包含有native支付的二维码+jsApi支付的支付组件
+ */
+ PayResponse requestPay(PayRequest payRequest, String tradeType) throws TradeException;
+
+ /**
+ * 关闭订单
+ * 该结构基于设计模式实现,对接了微信V3版支付代码和支付宝支付sdk
+ * 业务编写人员在处理超时订单的时候需要 通知微信 由于是超时订单需要进行远程关闭
+ */
+ Boolean closePay(String orderSn) throws TradeException;
+
+ /**
+ * 退款s申请
+ * 该接口基于设计模式实现,对接了微信V3版支付代码和支付宝支付sdk
+ * 业务编写人员在处理业务执行失败时需要进行退款
+ */
+ Boolean refund(RefundRequest refundRequest) throws TradeException;
+
+ /**
+ * 商户订单号查询 根据订单号查询订单
+ * 该接口基于生成的订单号来进行订单的查询
+ * 可以基于查询的结果判断用户订单是否支付成功
+ */
+ QueryResponse queryTradingOrderNo(String orderSn) throws TradeException;
+
+
+ /**
+ * 查询单笔退款API
+ *
+ */
+ QueryRefundResponse queryRefundTrading(String orderSn) throws TradeException;
+
+
+ /**
+ * 获得openId
+ * @param code
+ * @return
+ */
+ String getOpenid(String code);
+
+}
diff --git a/pay/src/main/java/com/ruoyi/core/ElegentValid.java b/pay/src/main/java/com/ruoyi/core/ElegentValid.java
new file mode 100644
index 0000000..fdb7cd5
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/core/ElegentValid.java
@@ -0,0 +1,48 @@
+package com.ruoyi.core;
+
+
+import com.ruoyi.dto.ValidResponse;
+import com.ruoyi.exceptions.TradeException;
+import org.springframework.http.HttpEntity;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * 验证器接口
+ *
+ */
+public interface ElegentValid {
+
+
+ /**
+ * 支付结果通知校验
+ * 该接口基于设计模式实现,对接了微信V3版支付代码和支付宝支付sdk
+ * 业务编写人员在接收到微信或支付宝回调的时候可以使用该方法验证回调是否成功,是否是伪回调
+ * @return 交易数据对象
+ */
+ ValidResponse validPay(HttpEntity httpEntity, HttpServletRequest request) throws TradeException;
+
+
+
+ /**
+ * 退款结果通知校验
+ * 该接口基于设计模式实现,对接了微信V3版支付代码和支付宝支付sdk
+ * 业务编写人员在接收到微信或支付宝回调的时候可以使用该方法验证回调是否成功,是否是伪回调
+ */
+ ValidResponse validRefund(HttpEntity httpEntity, HttpServletRequest request) throws TradeException;
+
+
+ /**
+ * 成功返回结构
+ * @return
+ */
+ String successResult();
+
+
+ /**
+ * 失败返回内容
+ * @return
+ */
+ String failResult();
+
+}
diff --git a/pay/src/main/java/com/ruoyi/core/WatchList.java b/pay/src/main/java/com/ruoyi/core/WatchList.java
new file mode 100644
index 0000000..a610939
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/core/WatchList.java
@@ -0,0 +1,20 @@
+package com.ruoyi.core;
+
+
+
+import com.ruoyi.dto.WatchDTO;
+
+import java.util.concurrent.CopyOnWriteArraySet;
+
+/**
+ * 监听列表
+ */
+public class WatchList {
+
+
+
+ public static CopyOnWriteArraySet payList=new CopyOnWriteArraySet<>(); //支付中列表
+
+ public static CopyOnWriteArraySet refundList=new CopyOnWriteArraySet<>(); //退款中列表
+
+}
diff --git a/pay/src/main/java/com/ruoyi/dto/PayRequest.java b/pay/src/main/java/com/ruoyi/dto/PayRequest.java
new file mode 100644
index 0000000..5d747da
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/dto/PayRequest.java
@@ -0,0 +1,20 @@
+package com.ruoyi.dto;
+
+
+import lombok.Data;
+
+/**
+ * PayRequest
+ * 支付请求外观类
+*/
+@Data
+public class PayRequest {
+
+ private String body;//商品描述
+
+ private String orderSn; //订单号
+
+ private int totalFee; //订单金额
+
+ private String openid;//openId
+}
diff --git a/pay/src/main/java/com/ruoyi/dto/PayResponse.java b/pay/src/main/java/com/ruoyi/dto/PayResponse.java
new file mode 100644
index 0000000..db4aafb
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/dto/PayResponse.java
@@ -0,0 +1,29 @@
+package com.ruoyi.dto;
+
+import lombok.Data;
+
+import java.util.Map;
+
+/**
+ * 结果统一封装类
+ */
+@Data
+public class PayResponse {
+
+ private boolean success; //是否成功
+
+ private String message;//信息
+
+ private String order_sn;//订单编号
+
+ private Map expand;//扩展属性
+
+ private String code_url;//二维码连接(native返回)
+
+ private String prepay_id;//预支付Id(小程序返回)
+
+ private String h5_url;//支付跳转链接
+
+ private Map jsapiData;//小程序返回
+
+}
diff --git a/pay/src/main/java/com/ruoyi/dto/QueryRefundResponse.java b/pay/src/main/java/com/ruoyi/dto/QueryRefundResponse.java
new file mode 100644
index 0000000..d938f63
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/dto/QueryRefundResponse.java
@@ -0,0 +1,24 @@
+package com.ruoyi.dto;
+
+import lombok.Data;
+
+@Data
+public class QueryRefundResponse extends QueryResponse{
+
+
+ private String refund_id; //微信支付退款单号
+
+ private String out_refund_no;//商户退款单号
+
+ private String channel;//退款渠道
+
+ private String user_received_account;//退款账号
+
+ private String success_time;//退款成功时间
+
+ private String status;//退款状态
+
+ private int refund;//退款金额
+
+
+}
diff --git a/pay/src/main/java/com/ruoyi/dto/QueryResponse.java b/pay/src/main/java/com/ruoyi/dto/QueryResponse.java
new file mode 100644
index 0000000..04ddb70
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/dto/QueryResponse.java
@@ -0,0 +1,25 @@
+package com.ruoyi.dto;
+
+import lombok.Data;
+
+import java.util.Map;
+
+/**
+ * 查询响应对象
+ */
+@Data
+public class QueryResponse {
+
+ private String openid;//用户id
+
+ private String trade_state;//交易状态
+
+ private String order_sn;//订单号
+
+ private String transaction_id;//交易单号
+
+ private int total;//金额
+
+ private Map expand;//扩展(全部的返回数据)
+
+}
diff --git a/pay/src/main/java/com/ruoyi/dto/RefundRequest.java b/pay/src/main/java/com/ruoyi/dto/RefundRequest.java
new file mode 100644
index 0000000..3f17046
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/dto/RefundRequest.java
@@ -0,0 +1,16 @@
+package com.ruoyi.dto;
+
+import lombok.Data;
+
+@Data
+public class RefundRequest {
+
+ private int totalFee; //订单金额
+
+ private int refundAmount; //退款金额
+
+ private String orderSn; //订单号
+
+ private String requestNo; //退款请求号,做退款幂等性校验,当部分退款时必须给出
+
+}
diff --git a/pay/src/main/java/com/ruoyi/dto/ValidResponse.java b/pay/src/main/java/com/ruoyi/dto/ValidResponse.java
new file mode 100644
index 0000000..f8e3973
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/dto/ValidResponse.java
@@ -0,0 +1,15 @@
+package com.ruoyi.dto;
+
+import lombok.Data;
+
+/**
+ * 验证签名
+ */
+@Data
+public class ValidResponse {
+
+ private boolean isValid;// 是否通过验签
+
+ private String orderSn;// 订单号
+
+}
diff --git a/pay/src/main/java/com/ruoyi/dto/WatchDTO.java b/pay/src/main/java/com/ruoyi/dto/WatchDTO.java
new file mode 100644
index 0000000..7411b91
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/dto/WatchDTO.java
@@ -0,0 +1,12 @@
+package com.ruoyi.dto;
+
+import lombok.Data;
+
+@Data
+public class WatchDTO {
+
+ private String orderSn; //订单号
+
+ private String platform;//平台
+
+}
diff --git a/pay/src/main/java/com/ruoyi/exceptions/TradeException.java b/pay/src/main/java/com/ruoyi/exceptions/TradeException.java
new file mode 100644
index 0000000..3a82860
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/exceptions/TradeException.java
@@ -0,0 +1,24 @@
+package com.ruoyi.exceptions;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 交易SDK提供的总的异常
+ */
+@Getter
+@Setter
+public class TradeException extends RuntimeException{
+ private String code;
+ private String msg;
+
+ public TradeException(String code, String msg) {
+ super(msg);
+ this.code = code;
+ this.msg = msg;
+ }
+
+ public TradeException(String msg) {
+ super(msg);
+ }
+}
diff --git a/pay/src/main/java/com/ruoyi/key/KeyManager.java b/pay/src/main/java/com/ruoyi/key/KeyManager.java
new file mode 100644
index 0000000..aacfee5
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/key/KeyManager.java
@@ -0,0 +1,16 @@
+package com.ruoyi.key;
+
+/**
+ * 密钥管理器接口
+ */
+public interface KeyManager {
+
+
+ /**
+ * 根据名字获取key字符串
+ * @param name
+ * @return
+ */
+ String getKey(String name);
+
+}
diff --git a/pay/src/main/java/com/ruoyi/key/impl/DefaultKeyManager.java b/pay/src/main/java/com/ruoyi/key/impl/DefaultKeyManager.java
new file mode 100644
index 0000000..0d48c66
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/key/impl/DefaultKeyManager.java
@@ -0,0 +1,19 @@
+package com.ruoyi.key.impl;
+
+
+import com.ruoyi.key.KeyManager;
+import com.ruoyi.util.FileUtil;
+
+/**
+ * 默认的key管理器-文件管理器
+ */
+public class DefaultKeyManager implements KeyManager {
+
+
+ @Override
+ public String getKey(String name) {
+ return FileUtil.readToStr(name);
+ }
+
+
+}
diff --git a/pay/src/main/java/com/ruoyi/util/FileUtil.java b/pay/src/main/java/com/ruoyi/util/FileUtil.java
new file mode 100644
index 0000000..13d0e9f
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/util/FileUtil.java
@@ -0,0 +1,37 @@
+package com.ruoyi.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * 文件读取类
+ */
+public class FileUtil {
+
+
+ /**
+ * 获取文件内容
+ * @param fileName
+ * @return
+ */
+ public static String readToStr(String fileName){
+ InputStream is = FileUtil.class.getClassLoader().getResourceAsStream(fileName);
+ ByteArrayOutputStream os = new ByteArrayOutputStream(2048);
+ byte[] buffer = new byte[1024];
+
+ String str;
+ try {
+ int length;
+ while((length = is.read(buffer)) != -1) {
+ os.write(buffer, 0, length);
+ }
+
+ str = os.toString("UTF-8");
+ } catch (IOException var5) {
+ throw new IllegalArgumentException("无效的密钥", var5);
+ }
+ return str;
+ }
+
+}
diff --git a/pay/src/main/java/com/ruoyi/wx/WxPayElegentTrade.java b/pay/src/main/java/com/ruoyi/wx/WxPayElegentTrade.java
new file mode 100644
index 0000000..d1dfc8c
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/wx/WxPayElegentTrade.java
@@ -0,0 +1,459 @@
+package com.ruoyi.wx;
+
+
+import cn.hutool.core.util.CharsetUtil;
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSON;
+import com.ruoyi.annotation.TradePlatform;
+import com.ruoyi.config.CallbackConfig;
+import com.ruoyi.constant.PayConstant;
+import com.ruoyi.constant.Platform;
+import com.ruoyi.core.ElegentTrade;
+import com.ruoyi.dto.*;
+import com.ruoyi.exceptions.TradeException;
+import com.ruoyi.util.FileUtil;
+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.WechatPay2Credentials;
+import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
+import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
+import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
+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.client.utils.URIBuilder;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.util.EntityUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestTemplate;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+@Slf4j
+@TradePlatform(Platform.WX)
+public class WxPayElegentTrade implements ElegentTrade {
+
+ @Autowired
+ private WxpayConfig wxpayConfig;
+
+ @Autowired
+ private CallbackConfig callbackConfig;
+
+ /**
+ * 创建微信支付订单方法
+ * 这里参考官网代码:
+ * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_1.shtml Native下单
+ * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml JSAPI 下单
+ * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_1.shtml H5下单
+ * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_1.shtml APP下单
+ * @param payRequest 支付请求
+ * @return 支付响应
+ * @throws IOException
+ */
+ @Override
+ public PayResponse requestPay(PayRequest payRequest, String tradeType)throws TradeException {
+ PayResponse payResponse = new PayResponse(); //返回结果
+ try {
+ // 请求body参数构建
+ Map params = new HashMap() {
+ {
+ put("mchid", wxpayConfig.getMchId());
+ put("appid", wxpayConfig.getAppId());
+ put("notify_url", callbackConfig.getDomain()+ PayConstant.CALLBACK_PATH + PayConstant.NOTIFY +"/"+ Platform.WX );
+ put("out_trade_no", payRequest.getOrderSn());
+ put("amount", new HashMap() {
+ {
+ put("total", payRequest.getTotalFee());//金额,单位:分
+ put("currency", "CNY");//人民币
+ }
+ });
+ put("description", payRequest.getBody());
+ }
+ };
+
+ if("h5".equals(tradeType)){ //h5
+ params.put("scene_info", new HashMap() {
+ {
+ put("payer_client_ip", "127.0.0.1");
+ put("h5_info", new HashMap() {
+ {
+ put("type", "Wap");
+ }
+ });
+ }
+ });
+ }
+ if ("jsapi".equals(tradeType)) { //如果是小程序支付
+ params.put("payer", new HashMap() {
+ {
+ put("openid", payRequest.getOpenid());
+ }
+ });
+ }
+
+
+ String url = WxpayConstant.createOrder + tradeType; //创建订单
+ log.info("elegent-pay 请求参数{}",params);
+ Map map = postApiTemplate(url, params);
+
+ if("SUCCESS".equals( map.get("code") )){
+ payResponse.setOrder_sn(payRequest.getOrderSn());
+ payResponse.setSuccess(true);
+ payResponse.setCode_url(map.get("code_url"));
+ payResponse.setMessage(map.get("message"));
+
+ payResponse.setPrepay_id(map.get("prepay_id"));
+ payResponse.setH5_url( map.get("h5_url") );
+
+ payResponse.setExpand(map); //全部数据
+
+ if("jsapi".equals(tradeType)){//如果是小程序,需要封装到Expand
+ Map data=new HashMap<>();
+ String timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
+ String nonceStr = IdUtil.simpleUUID();
+ String packages = "prepay_id=" + payResponse.getPrepay_id();
+ String privateKey = FileUtil.readToStr("wxpay_private.key");
+ String paySign = this.createPaySign(wxpayConfig.getAppId(), timeStamp, nonceStr, packages, privateKey);
+ data.put("appId", wxpayConfig.getAppId());// appid
+ data.put("timeStamp", timeStamp);// 时间戳
+ data.put("nonceStr", nonceStr);// 随机字符串
+ data.put("package","prepay_id="+payResponse.getPrepay_id());
+ data.put("signType", "RSA");// 签名类型,默认为RSA,仅支持RSA
+ data.put("paySign", paySign);// 签名
+ data.put("orderNo",payRequest.getOrderSn());
+ payResponse.setJsapiData(data);
+ }
+
+
+ log.info("createOrder: {}", payResponse);
+
+ }else{
+ payResponse.setSuccess(false);
+ payResponse.setMessage( map.get("message") );
+ }
+ return payResponse;
+ }catch (Exception e){
+ e.printStackTrace();
+ payResponse.setSuccess(false);
+ }
+ return payResponse;
+ }
+
+
+ /**
+ * 关闭订单
+ * 参考官网代码
+ * https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_7_2.shtml 3.2.5. 【服务端】关闭订单
+ * @return
+ */
+ @Override
+ public Boolean closePay(String orderSn) throws TradeException {
+ // 请求body参数构建
+ Map params = new HashMap();
+ params.put("mchid", wxpayConfig.getMchId());
+ String url = WxpayConstant.closeOrder.replaceAll("\\{out_trade_no\\}",orderSn);
+ Map map = postApiTemplate(url, params);
+ if("SUCCESS".equals( map.get("code"))){
+ return true;
+ }else{
+ return false;
+ }
+ }
+
+
+ /**
+ * 退款
+ * 参考官网代码 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_9.shtml
+ * @param refundRequest
+ * @return
+ */
+ @Override
+ public Boolean refund(RefundRequest refundRequest) {
+ // 请求body参数构建
+ // 请求body参数构建
+ Map params = new HashMap();
+ params.put("notify_url", callbackConfig.getDomain()+ PayConstant.CALLBACK_PATH +PayConstant.REFUND_NOTIFY +"/"+ Platform.WX ); //回调地址
+ params.put("out_trade_no", refundRequest.getOrderSn());//订单编号
+ //out_refund_no
+ params.put("out_refund_no", refundRequest.getRequestNo());//退款申请单编号 (多次退款需要不一样才行)
+ params.put("amount", new HashMap() {
+ {
+ put("refund",refundRequest.getRefundAmount());//退款金额
+ put("total", refundRequest.getTotalFee());//原金额,单位:分
+ put("currency", "CNY");//人民币
+ }
+ });
+ String url = WxpayConstant.refund; //创建订单
+ Map map = postApiTemplate(url, params);
+ if("SUCCESS".equals( map.get("code"))){
+
+ return true;
+ }else{
+ return false;
+ }
+ }
+
+
+
+ /**
+ * 手动查询订单
+ * 参考官网代码: https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_6_2.shtml 3.2.4. 【服务端】查询订单
+ * @param orderSn
+ * @return
+ */
+ @Override
+ public QueryResponse queryTradingOrderNo(String orderSn) throws TradeException {
+ // 请求body参数构建
+ Map params = new HashMap();
+ params.put("mchid", wxpayConfig.getMchId());
+ String url = WxpayConstant.queryOrderNo+orderSn;;
+ try {
+ Map map = getApiTemplate(url, params);
+ QueryResponse queryResponse=new QueryResponse();
+ queryResponse.setOrder_sn((String)map.get("out_trade_no") ); //订单号
+ queryResponse.setTransaction_id((String)map.get("transaction_id") ); //交易单类型
+ queryResponse.setTrade_state( (String) map.get("trade_state") );//交易状态
+ Map amount = (Map)map.get("amount");
+ if(amount!=null){
+ queryResponse.setTotal( (Integer) amount.get("total") ); //总金额
+ }
+ Map payer= (Map)map.get("payer");
+ if(payer!=null){
+ queryResponse.setOpenid( (String)payer.get("openid") );
+ }
+ queryResponse.setExpand(map);//全部数据
+ return queryResponse;
+
+ } catch (URISyntaxException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+
+ /**
+ * 查询退款订单
+ * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_10.shtml
+ * @param out_refund_no
+ * @return
+ * @throws TradeException
+ */
+ @Override
+ public QueryRefundResponse queryRefundTrading(String out_refund_no) throws TradeException {
+
+ // 请求body参数构建
+ Map params = new HashMap();
+ String url = WxpayConstant.queryRufundOrderNo + out_refund_no;
+ try {
+ Map map = getApiTemplate(url, params);
+ QueryRefundResponse queryRefundResponse=new QueryRefundResponse();
+ queryRefundResponse.setOrder_sn( (String) map.get("out_trade_no") );
+ queryRefundResponse.setTransaction_id( (String) map.get("transaction_id") );
+ Map amount = (Map)map.get("amount");
+ queryRefundResponse.setTotal( (Integer) amount.get("total") ); //总金额
+ queryRefundResponse.setRefund((Integer) amount.get("payer_refund") ); //退款金额
+ queryRefundResponse.setRefund_id((String) map.get("refund_id") ); //退款单号
+ queryRefundResponse.setOut_refund_no( (String) map.get("out_refund_no") );//退款订单号
+
+ queryRefundResponse.setChannel( (String) map.get("channel") ); //通道
+ queryRefundResponse.setUser_received_account( (String) map.get("user_received_account") ); //账号
+ queryRefundResponse.setStatus( (String) map.get("status") ); //状态
+ queryRefundResponse.setSuccess_time( (String) map.get("success_time") );
+ queryRefundResponse.setExpand(map);
+ return queryRefundResponse;
+ } catch (URISyntaxException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public String getOpenid(String code) {
+ String getOpenIdUrl = "https://api.weixin.qq.com/sns/jscode2session?" +
+ "appid="+wxpayConfig.getAppId()
+ +"&secret="+wxpayConfig.getAppSecret()
+ +"&js_code="+code+"&grant_type=authorization_code";
+ RestTemplate restTemplate = new RestTemplate();
+ String respResult = restTemplate.getForObject(getOpenIdUrl,String.class);
+ log.info("获取openid的url:{},respResult:{}",getOpenIdUrl,respResult);
+ if( respResult==null || "".equals(respResult) ) return "";
+ try{
+
+ Map map = JSON.parseObject(respResult, Map.class);
+ String errorCode = map.get("errcode") ;
+ if(errorCode!=null && !"".equals(errorCode)){
+ int errorCodeInt = Integer.valueOf(errorCode).intValue();
+
+ log.info("获取openid的errorCode,{}",errorCodeInt);
+ if(errorCodeInt != 0) return "";
+ }
+ return map.get("openid");
+ }catch (Exception ex){
+ ex.printStackTrace();
+ return "";
+ }
+ }
+
+
+ private Map getApiTemplate(String url, Map params) throws URISyntaxException, IOException {
+ URIBuilder uriBuilder = new URIBuilder(url);
+ //添加参数
+ for (String key : params.keySet()) {
+ uriBuilder.addParameter(key, params.get(key));
+ }
+ //完成签名并执行请求
+ HttpGet httpGet = new HttpGet(uriBuilder.build());
+ httpGet.addHeader("Accept", "application/json");
+ CloseableHttpClient httpClient = getWxHttpClient();
+ CloseableHttpResponse response = httpClient.execute(httpGet);
+ return responseTemplate(response);
+ }
+
+
+ private Map responseTemplate(CloseableHttpResponse response) {
+ Map result = null;
+ try {
+ int statusCode = response.getStatusLine().getStatusCode();
+ if (statusCode == 200) { //处理成功
+ // log.info("success,return body = " + EntityUtils.toString(response.getEntity()));
+ result = JSON.parseObject(EntityUtils.toString(response.getEntity()), Map.class);
+ result.put("code", "SUCCESS");
+ } else if (statusCode == 204) { //处理成功,无返回Body
+ log.info("success");
+ result = new HashMap() {
+ {
+ put("code", "SUCCESS");
+ }
+ };
+ } else {
+ String returnBody = EntityUtils.toString(response.getEntity());
+ log.error("failed,resp code = " + statusCode + ",return body = " + returnBody);
+ //throw new TradeException("创建本地支付订单失败!"+payDTO.getOrderSn());
+ Map map = JSON.parseObject(returnBody, Map.class);
+ result = new HashMap() {
+ {
+ put("code", "FAIL");
+ put("message", map.get("message"));
+ }
+ };
+ }
+ } catch (Exception e) {
+ result = new HashMap() {
+ {
+ put("code", "FAIL");
+ put("message", e.getMessage());
+ }
+ };
+ } finally {
+ closeConnect(response);
+ return result;
+ }
+ }
+
+ private Map postApiTemplate(String url, Map params) {
+ try {
+ HttpPost httpPost = new HttpPost(url);
+ StringEntity entity = new StringEntity(JSON.toJSONString(params));
+ entity.setContentType("application/json");
+ httpPost.setEntity(entity);
+ httpPost.setHeader("Accept", "application/json");
+ //完成签名并执行请求
+ CloseableHttpClient httpClient = getWxHttpClient();
+ CloseableHttpResponse response = httpClient.execute(httpPost);
+ return responseTemplate( response );
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+
+ /**
+ * 获取微信HTTP连接
+ *
+ * @return
+ */
+ private CloseableHttpClient getWxHttpClient() {
+ try {
+ //这里对秘钥进行加密使用的完全是官网上的代码
+ //TODO 参考官网代码 https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_6_2.shtml
+ // 加载商户私钥(privateKey:私钥字符串)
+ String key = FileUtil.readToStr("wxpay_private.key");
+
+ PrivateKey merchantPrivateKey = PemUtil
+ .loadPrivateKey(new ByteArrayInputStream(key.getBytes("utf-8")));
+ // 加载平台证书(mchId:商户号,mchSerialNo:商户证书序列号,apiV3Key:V3密钥)
+ //PrivateKey merchantPrivateKey = keyManager.getPrivateKey("wxpay_private.key");//读取私钥
+ PrivateKeySigner privateKeySigner = new PrivateKeySigner(wxpayConfig.getMchSerialNo(), merchantPrivateKey);
+ WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(
+ wxpayConfig.getMchId(), privateKeySigner);
+ // 向证书管理器增加需要自动更新平台证书的商户信息
+ CertificatesManager certificatesManager = CertificatesManager.getInstance();
+ certificatesManager.putMerchant(wxpayConfig.getMchId(), wechatPay2Credentials, wxpayConfig.getApiV3Key().getBytes("utf-8"));
+ // 初始化httpClient
+ return WechatPayHttpClientBuilder.create()
+ .withMerchant(wxpayConfig.getMchId(), wxpayConfig.getMchSerialNo(), merchantPrivateKey)
+ .withValidator(new WechatPay2Validator(certificatesManager.getVerifier(wxpayConfig.getMchId()))).build();
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException("微信支付--初始化,校验系统参数失败");
+ }
+
+ }
+
+
+ /**
+ * 关闭资源
+ */
+ private void closeConnect(CloseableHttpResponse response) {
+ try {
+ response.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException("资源回收出错");
+ }
+ }
+
+
+ /**
+ * 创建支付签名
+ * @param appid
+ * @param timeStamp
+ * @param nonceStr
+ * @param packages
+ * @param privateKey
+ * @return
+ * @throws Exception
+ */
+ private String createPaySign(String appid, String timeStamp, String nonceStr, String packages,String privateKey) throws Exception {
+ Signature sign = Signature.getInstance("SHA256withRSA");
+ // 加载商户私钥
+ PrivateKey key = PemUtil
+ .loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes(CharsetUtil.CHARSET_UTF_8)));
+ sign.initSign(key);
+ String message = StrUtil.format("{}\n{}\n{}\n{}\n",
+ appid,
+ timeStamp,
+ nonceStr,
+ packages);
+ sign.update(message.getBytes());
+ return Base64.getEncoder().encodeToString(sign.sign());
+ }
+
+
+}
diff --git a/pay/src/main/java/com/ruoyi/wx/WxPayElegentValid.java b/pay/src/main/java/com/ruoyi/wx/WxPayElegentValid.java
new file mode 100644
index 0000000..c570b6f
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/wx/WxPayElegentValid.java
@@ -0,0 +1,153 @@
+package com.ruoyi.wx;
+
+
+import com.alibaba.fastjson.JSON;
+import com.ruoyi.annotation.TradePlatform;
+import com.ruoyi.constant.Platform;
+import com.ruoyi.core.ElegentValid;
+import com.ruoyi.dto.ValidResponse;
+import com.ruoyi.exceptions.TradeException;
+import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
+import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
+import com.wechat.pay.contrib.apache.httpclient.notification.Notification;
+import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler;
+import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+
+@Component
+@Slf4j
+@TradePlatform(Platform.WX)
+public class WxPayElegentValid implements ElegentValid {
+
+
+ @Autowired
+ private WxpayConfig wxpayConfig;
+
+ @Override
+ public ValidResponse validPay(HttpEntity httpEntity, HttpServletRequest httpServletRequest) throws TradeException {
+ ValidResponse validResponse=new ValidResponse();
+
+ try {
+ //获取请求头
+ HttpHeaders headers = httpEntity.getHeaders();
+ //构建微信请求数据对象
+ NotificationRequest request = new NotificationRequest.Builder()
+ .withSerialNumber(headers.getFirst("Wechatpay-Serial")) //证书序列号(微信平台)
+ .withNonce(headers.getFirst("Wechatpay-Nonce")) //随机串
+ .withTimestamp(headers.getFirst("Wechatpay-Timestamp")) //时间戳
+ .withSignature(headers.getFirst("Wechatpay-Signature")) //签名字符串
+ .withBody(httpEntity.getBody())
+ .build();
+
+
+ //微信通知的业务处理
+ //验证签名,确保请求来自微信
+ Map jsonData = null;
+ try {
+ //确保在管理器中存在自动更新的商户证书
+ CertificatesManager certificatesManager = CertificatesManager.getInstance();
+ Verifier verifier = certificatesManager.getVerifier(wxpayConfig.getMchId());
+
+ //验签和解析请求数据
+ NotificationHandler notificationHandler = new NotificationHandler(verifier, wxpayConfig.getApiV3Key().getBytes(StandardCharsets.UTF_8));
+ Notification notification = notificationHandler.parse(request);
+
+ if (!"TRANSACTION.SUCCESS".equals(notification.getEventType())) {
+ validResponse.setValid(false);
+ return validResponse;
+ }
+ //获取解密后的数据
+ jsonData = JSON.parseObject(notification.getDecryptData(),Map.class );
+ log.info("解密后的数据为:"+jsonData);
+ } catch (Exception e) {
+ throw new TradeException("验签失败");
+ }
+ if (!"SUCCESS".equals(jsonData.get("trade_state"))) {
+ validResponse.setValid(false);
+ return validResponse;
+ }
+ validResponse.setValid(true);
+ validResponse.setOrderSn( (String) jsonData.get("out_trade_no") ); //订单号
+ return validResponse;
+ } catch (Exception e) {
+ validResponse.setValid(false);
+ return validResponse;
+ }
+ }
+
+ @Override
+ public ValidResponse validRefund(HttpEntity httpEntity, HttpServletRequest httpServletRequest) throws TradeException {
+
+ ValidResponse validResponse=new ValidResponse();
+ try {
+ //获取请求头
+ HttpHeaders headers = httpEntity.getHeaders();
+
+ //构建微信请求数据对象
+ NotificationRequest request = new NotificationRequest.Builder()
+ .withSerialNumber(headers.getFirst("Wechatpay-Serial")) //证书序列号(微信平台)
+ .withNonce(headers.getFirst("Wechatpay-Nonce")) //随机串
+ .withTimestamp(headers.getFirst("Wechatpay-Timestamp")) //时间戳
+ .withSignature(headers.getFirst("Wechatpay-Signature")) //签名字符串
+ .withBody(httpEntity.getBody())
+ .build();
+
+ //微信通知的业务处理
+ Map jsonData = null;
+ //验证签名,确保请求来自微信
+ try {
+ //确保在管理器中存在自动更新的商户证书
+ CertificatesManager certificatesManager = CertificatesManager.getInstance();
+ Verifier verifier = certificatesManager.getVerifier(wxpayConfig.getMchId());
+
+ //验签和解析请求数据
+ NotificationHandler notificationHandler = new NotificationHandler(verifier, wxpayConfig.getApiV3Key().getBytes(StandardCharsets.UTF_8));
+ Notification notification = notificationHandler.parse(request);
+
+ if (!"REFUND.SUCCESS".equals(notification.getEventType())) {
+ //非成功请求直接返回,理论上都是成功的请求
+ validResponse.setValid(false);
+ return validResponse;
+ }
+ //获取解密后的数据
+ jsonData = JSON.parseObject( notification.getDecryptData(),Map.class );
+
+
+ } catch (Exception e) {
+ throw new TradeException("验签失败");
+ }
+ if (!"SUCCESS".equals(jsonData.get("refund_status"))) {
+ //非成功请求直接返回,理论上都是成功的请求
+ validResponse.setValid(false);
+ return validResponse;
+ }
+
+ //交易单号
+ validResponse.setValid(true);
+ validResponse.setOrderSn( (String) jsonData.get("out_trade_no") ); //订单号
+ return validResponse;
+ } catch (Exception e) {
+ //非成功请求直接返回,理论上都是成功的请求
+ validResponse.setValid(false);
+ return validResponse;
+ }
+ }
+
+ @Override
+ public String successResult() {
+ return JSON.toJSONString(WxpayConstant.SUCCESS ) ;
+ }
+
+ @Override
+ public String failResult() {
+ return JSON.toJSONString( WxpayConstant.FAIL);
+ }
+}
diff --git a/pay/src/main/java/com/ruoyi/wx/WxpayConfig.java b/pay/src/main/java/com/ruoyi/wx/WxpayConfig.java
new file mode 100644
index 0000000..c5f139c
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/wx/WxpayConfig.java
@@ -0,0 +1,20 @@
+package com.ruoyi.wx;
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 微信权限对接类
+ */
+@Component
+@ConfigurationProperties("elegent.pay.wxpay")
+@Data
+public class WxpayConfig {
+
+ private String mchId; //商户号
+ private String appId; //APPID
+ private String appSecret;//app密钥
+ private String mchSerialNo; //商户证书序列号
+ private String apiV3Key; //V3密钥
+
+}
\ No newline at end of file
diff --git a/pay/src/main/java/com/ruoyi/wx/WxpayConstant.java b/pay/src/main/java/com/ruoyi/wx/WxpayConstant.java
new file mode 100644
index 0000000..01d3415
--- /dev/null
+++ b/pay/src/main/java/com/ruoyi/wx/WxpayConstant.java
@@ -0,0 +1,48 @@
+package com.ruoyi.wx;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class WxpayConstant {
+
+ public static final Map SUCCESS = new HashMap(){
+ {
+ put("code", "SUCCESS");
+ }
+ };
+
+ public static final Map FAIL = new HashMap(){
+ {
+ put("code", "FAIL");
+ put("message","微信回调错误结果");
+ }
+ };
+
+
+ public final static String domain ="https://api.mch.weixin.qq.com/v3";
+
+ /**
+ * 创建订单
+ */
+ public final static String createOrder = domain +"/pay/transactions/";
+
+ /**
+ * 关闭订单
+ */
+ public final static String closeOrder = domain+"/pay/transactions/out-trade-no/{out_trade_no}/close";
+
+ /**
+ * 查询订单编号
+ */
+ public static String queryOrderNo = domain+"/pay/transactions/out-trade-no/";
+
+ /**
+ * 查询退款订单
+ */
+ public static String queryRufundOrderNo =domain+ "/refund/domestic/refunds/";
+
+ /**
+ * 退款接口
+ */
+ public static String refund = domain+"/refund/domestic/refunds";
+}
diff --git a/pay/src/main/resources/META-INF/spring.factories b/pay/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000..da04c71
--- /dev/null
+++ b/pay/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,14 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+ com.ruoyi.config.CallbackConfig,\
+ com.ruoyi.core.CallbackWatch,\
+ com.ruoyi.core.ElegentPayImpl,\
+ com.ruoyi.core.ElegentLoader,\
+ com.ruoyi.core.ElegentConfig,\
+ com.ruoyi.key.impl.DefaultKeyManager,\
+ com.ruoyi.core.CallbackController,\
+ com.ruoyi.wx.WxpayConfig,\
+ com.ruoyi.wx.WxPayElegentTrade,\
+ com.ruoyi.wx.WxPayElegentValid,\
+ com.ruoyi.ali.AlipayConfig,\
+ com.ruoyi.ali.AlipayElegentTrade,\
+ com.ruoyi.ali.AlipayElegentValid
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 9d5389d..9c62fbb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -180,6 +180,7 @@
ruoyi-quartz
ruoyi-generator
ruoyi-common
+ pay
pom
diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml
index 1436d6d..2186d33 100644
--- a/ruoyi-admin/pom.xml
+++ b/ruoyi-admin/pom.xml
@@ -60,7 +60,11 @@
com.ruoyi
ruoyi-generator
-
+
+ com.ruoyi
+ pay
+ 1.0.0-SNAPSHOT
+
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/ArbitratorController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/ArbitratorController.java
index 183f294..8b9f249 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/ArbitratorController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/ArbitratorController.java
@@ -3,7 +3,6 @@ package com.ruoyi.web.controller.wisdomarbitrate;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.wisdomarbitrate.domain.Arbitrator;
-import com.ruoyi.wisdomarbitrate.domain.CaseApplication;
import com.ruoyi.wisdomarbitrate.service.IArbitratorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseApplicationController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseApplicationController.java
index 4c0ef36..2658de5 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseApplicationController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseApplicationController.java
@@ -3,7 +3,6 @@ package com.ruoyi.web.controller.wisdomarbitrate;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
-import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
@@ -22,7 +21,6 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
-import static com.ruoyi.common.core.domain.AjaxResult.error;
@RestController
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseArbitrateController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseArbitrateController.java
new file mode 100644
index 0000000..069c72e
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseArbitrateController.java
@@ -0,0 +1,41 @@
+package com.ruoyi.web.controller.wisdomarbitrate;
+
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.wisdomarbitrate.domain.CaseApplication;
+import com.ruoyi.wisdomarbitrate.service.ICaseArbitrateService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/arbitrate")
+public class CaseArbitrateController extends BaseController {
+ @Autowired
+ private ICaseArbitrateService caseArbitrateService;
+
+ /**
+ * 确定仲裁方式
+ * @param caseApplication
+ * @param arbitratMethod
+ * @return
+ */
+ @PutMapping("/method")
+ public AjaxResult chooseArbitrateMethod(@Validated @RequestBody CaseApplication caseApplication
+ ,Integer arbitratMethod){
+ return caseArbitrateService.chooseArbitrateMethod(caseApplication,arbitratMethod);
+ }
+
+ /**
+ * 书面审理
+ * @param caseApplication
+ * @param accidentDescription
+ * @param arbitrationResult
+ * @return
+ */
+ @PostMapping("/writtenHear")
+ public AjaxResult writtenHear(@Validated @RequestBody CaseApplication caseApplication
+ ,String accidentDescription , String arbitrationResult){
+ return caseArbitrateService.writtenHear(caseApplication,accidentDescription,arbitrationResult);
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseEvidenceController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseEvidenceController.java
new file mode 100644
index 0000000..037456b
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CaseEvidenceController.java
@@ -0,0 +1,81 @@
+package com.ruoyi.web.controller.wisdomarbitrate;
+
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.wisdomarbitrate.domain.CaseApplication;
+import com.ruoyi.wisdomarbitrate.domain.vo.CaseEvidenceVO;
+import com.ruoyi.wisdomarbitrate.service.ICaseEvidenceService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 案件证据
+ */
+@RestController
+@RequestMapping("/evidence")
+public class CaseEvidenceController extends BaseController {
+ private final ICaseEvidenceService caseEvidenceService;
+
+ @Autowired
+ public CaseEvidenceController(ICaseEvidenceService caseEvidenceService) {
+ this.caseEvidenceService = caseEvidenceService;
+ }
+
+ /**
+ * 根据案件id查询案件详情
+ *
+ * @param id
+ * @return
+ */
+ @GetMapping("/{id}")
+ public AjaxResult getCaseDetailsById(@PathVariable Long id) {
+ String username = this.getUsername();
+ return caseEvidenceService.getCaseDetailsById(id,username);
+ }
+
+ /**
+ * 案件证据上传
+ *
+ * @param file 附件
+ * @param annexType 附件类型,立案申请书(1)、证据材料(2)、仲裁文书(3)、案件视频(4)、身份证件(5)
+ * @param id 案件申请id
+ * @return
+ */
+ @PostMapping("/upload")
+ public AjaxResult uploadEvidence(@RequestParam("file") MultipartFile file, Integer annexType, Long id) {
+ String username = this.getUsername();
+ Long userId = this.getUserId();
+ return caseEvidenceService.uploadEvidence(file, annexType, id,username,userId);
+ }
+
+ /**
+ * 查询当前用户案件列表
+ * @param identityNum
+ * @return
+ */
+ @GetMapping("/all")
+ public TableDataInfo getCaseListAll(@RequestParam String identityNum) {
+ startPage();
+ List list = caseEvidenceService.getCaseListAll(identityNum);
+ if (list != null) {
+ return getDataTable(list);
+ }
+ return getDataTable(new ArrayList<>());
+ }
+
+ /**
+ * 证据确认
+ * @param caseApplication 案件对象
+ * @return 统一返回结果
+ */
+ @PutMapping("/confirm")
+ public AjaxResult evidenceConfirmation(@Validated @RequestBody CaseApplication caseApplication){
+ return caseEvidenceService.evidenceConfirmation(caseApplication);
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CasePaymentController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CasePaymentController.java
new file mode 100644
index 0000000..712ac1f
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/CasePaymentController.java
@@ -0,0 +1,41 @@
+package com.ruoyi.web.controller.wisdomarbitrate;
+
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.wisdomarbitrate.domain.CaseApplication;
+import com.ruoyi.wisdomarbitrate.service.ICasePaymentService;
+import com.ruoyi.wisdomarbitrate.domain.dto.CasePayDTO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 缴费支付
+ */
+@RestController
+@RequestMapping("/pay")
+public class CasePaymentController {
+ private final ICasePaymentService paymentService;
+ @Autowired
+ public CasePaymentController(ICasePaymentService paymentService){
+ this.paymentService=paymentService;
+ }
+ /**
+ * 案件缴费
+ * @param casePayDTO 缴费传入参数
+ * @return 统一响应结果
+ */
+ @PostMapping("/casePay")
+ public AjaxResult casePay(@Validated @RequestBody CasePayDTO casePayDTO) {
+ return paymentService.casePay(casePayDTO);
+ }
+
+ /**
+ * 缴费确认
+ * @param caseApplication
+ * @return
+ */
+ @PutMapping("/confirm")
+ public AjaxResult confirmPayment(@Validated @RequestBody CaseApplication caseApplication) {
+ return paymentService.confirmPayment(caseApplication);
+ }
+}
diff --git a/ruoyi-admin/src/main/resources/alipay_private.key b/ruoyi-admin/src/main/resources/alipay_private.key
new file mode 100644
index 0000000..6a4759b
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/alipay_private.key
@@ -0,0 +1 @@
+MIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAQC12YM9mR+HFQYTx/fHKHZbgszVtDHDB0B/ysWl3MbcPpGtjcZlDr5aynRMRLaoduRHT++A98IaNVIVGj9RHdXrX2j9I/Uz6fYDH63cdu6FZ6Pk82yPwNZW7pebprbVHInR/7gzsKQWSWEST70BgjCRqlbfAE6xzUZFTeYxciCjptm0rUQ2MC24xRdkvZByIDIYFnQ/AdmSFqNtKDR2WpEV/M8aBjyuPPomRJZ1X8oudWuJIU4ySdas04fCbDxD10TY/wyQcDHXuG1IrQpXme4DOGQeJZ0/aOFphBkDFUyPGfYMmLshOPNdBKi2IqWHPPs4XsV4Rv6+tvTSnMF2uGqHAgMBAAECggEAPa1sifPpcZN74DGupGng2uDeQI1BY3iOM8m+h6b9+61tE4RGifgaMAkCsOuNWE4a1uURwphFyUXUdTvVxdlsuMw/e7w6akUsH5sbCO99rtmcCQdXBtrM1+dMnIpK8LUhOYyWGVIMFVMGDYPmAyD5AC7aEAC2sC+DafYl4RdoYpidq1YxeE7DVw1aQHCI2mKhYjZG+3RDDGDfNFvdyH61MgdYjoGkeXNvARzEXgfWvfiTrHZ3H1SYgvOEHofzKDTrWsQL2dvaEsc55Jiw0AgNUVcgby7al8PUekTJoK3ZvrE3pSWaUirBcqsqWISHjeR7Xx501CHIha8EnZwlnDoM4QKBgQDtnYzwQ5mHg7cRHD8Z6QdTpvBvYSEPesiUT/HeI+AKQKDCVJxKiLvJagc6zZkOzV9bZDS/WLgzXWMyxUb+OTjht0jLWAMcf7NfFp3tPKq9wkmQQ/vQSBQ1lFmO6A4Zq1eoGKeUCB4pKBG6cSM+t8+ruhm7s1ZUt+6EBwCVN/izrQKBgQDD62jIm+6NFErdidUaIrGiFUrzqdR13w6JOexfk+O6Aau3wRqsr7Wz4nqQvVVxGMRpXbOH06zpeiS+vMmjwgO973VoLAmH+hJ0GZz8qj3zA2GEOFWjD2V7tqeRvGkQvz0v46pl+8sBJkrRHLN7DWNYY5NDI+b7exwqcTc/LL19gwJ/a6r4MeZvqvgD+7zQ2uy8ZSs/xzg7wsfgG1QeRIn8+qhOL8AnEZ7jeGCS5hJDSHHGw6KkRA/vZ1bpnBfIE2naXGywj3NR9Zfnry6QYO8cbt+adcRYVghTH/QYoKiFuxvonEKPrIQBJqUBY3ngforLjwTEpEie1cSCT1Dc8sBp8QKBgQCaz8fqzRyBKknGKQXVMxj+JKknRUl3IpzP3o9jLu9BqdRQzSwQzH9d91Y2TQXY6mM5hys35xG5JCUo+vCyj7p5OWCiwjl90yMFzr93/+YXwtIpsoIo6R+d1EUxKZoz+4mT7+hT0dUlwWZZOr6wO3IHBBf3c8UvbqZg+zlWmDnblQKBgEs6jwMkb5zaG2fyBJ7PJUN/8nIz8V+X0SxQfcEqIX0J+EC+7MAgFjcdZFp+lca3Vd9z+8Ksd4rMzMa5y856ositL2NZ+K0fs8i8EBaQPny61OgCFUuXEuv5keB2YuGMSns5FYRWuByrtDXl4PxzKXvq05iKWLKCaCq9v4momvKZ
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/alipay_public.key b/ruoyi-admin/src/main/resources/alipay_public.key
new file mode 100644
index 0000000..21236fb
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/alipay_public.key
@@ -0,0 +1 @@
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhUnjdAKwZApwZEcfq+5L0pa77Vg3mqcoXv+th8RR0SYotkPsH1f2JkbS48ySaSCM6YNWSMNfqp5qdOla2zUJOBnJ/yaBg7s7fVD6V3M2mEog8kCDYGKt/3P4VII3xYl8lFYMQ3IcFRELkxCBBCA8JDKmf5z2R4F/Z/jFFEuOwxaJvp+7Ke9OzZHYdWGNnU6QP8YYLYUeX7VNZLHEuly34ExAw6A+yJkNDsYEho2Lu31QjT2pLh9g+88MlRfiI92iN25O9NVdeM4f5RcpvBPrBQZQs9tlFmALYSFS3prIf3FAobWM+W7iwxT6J25nFIhst1DdJQfIBpaeRUJVTkn99QIDAQAB
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/application-druid.yml b/ruoyi-admin/src/main/resources/application-druid.yml
index 06872aa..763fe7e 100644
--- a/ruoyi-admin/src/main/resources/application-druid.yml
+++ b/ruoyi-admin/src/main/resources/application-druid.yml
@@ -6,9 +6,9 @@ spring:
druid:
# 主库数据源
master:
- url: jdbc:mysql://localhost:3306/ruyivue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
- username: ruyivue
- password: rybackproje13689
+ url: jdbc:mysql://121.40.189.20:3306/arbitrate?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&useSSL=false
+ username: root
+ password: root123456
# 从库数据源
slave:
# 从数据源开关/默认关闭
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index cfe0d50..2ace626 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -9,7 +9,7 @@ ruoyi:
# 实例演示开关
demoEnabled: true
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
- profile: D:/ruoyi/uploadPath
+ profile: /home/ruoyi/uploadPath
# 获取ip地址开关
addressEnabled: false
# 验证码类型 math 数字计算 char 字符验证
@@ -18,7 +18,7 @@ ruoyi:
# 开发环境配置
server:
# 服务器的HTTP端口,默认为8080
- port: 8080
+ port: 9001
servlet:
# 应用的访问路径
context-path: /
@@ -70,9 +70,9 @@ spring:
# redis 配置
redis:
# 地址
- host: localhost
+ host: 121.40.189.20
# 端口,默认为6379
- port: 6379
+ port: 6389
# 数据库索引
database: 0
# 密码
@@ -129,3 +129,21 @@ xss:
excludes: /system/notice
# 匹配链接
urlPatterns: /system/*,/monitor/*,/tool/*
+#支付相关配置
+elegent:
+ pay:
+ wxpay:
+ mchId: 1561414331
+ appId: wx6592a2db3f85ed25
+ appSecret: d9a9ff00a633cd7353a8925119063b01
+ mchSerialNo: 25FBDE3EFD31B03A4377EB9A4A47C517969E6620
+ apiV3Key: CZBK51236435wxpay435434323FFDuv3
+ alipay:
+ appId: 2021003141676135
+ callback:
+ domain: http://121.40.189.20:9000/
+ watch: false
+ cycle: 10
+identityAuthentication:
+ credentialSecretId: 123
+ credentialSecretKey: 367
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/wxpay_private.key b/ruoyi-admin/src/main/resources/wxpay_private.key
new file mode 100644
index 0000000..d4be12f
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/wxpay_private.key
@@ -0,0 +1 @@
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDBHGgIh80193GhdpD1LtMZfTRpcWI0fImyuBCyrd3gYb3rrsARebGcHdJsQA3mVjVqVp5ybhEZDPa4ecoK4Ye1hTppNpI/lmLt4/uUV/zhF5ahli7hi+116Ty6svHSbuMQBuUZeTFOwGrxjvofU/4pGIwh8ZvkcSnyOp9uX2177UVxDBkhgbZbJp9XF2b83vUa5eHo93CziPzn3hFdAlBCdTXB7DH+m0nN3Jou0szGukvq7cIgGpHku4ycKSTkIhhl9WRhN6OoSEJxq88MXzjkzTruc85PHN52aUTUifwg3T8Y4XqFQ61dTnEmgxeD2O6/pLdB9gLsp6yCGqN5Lqk7AgMBAAECggEBAL4X+WzUSbSjFS9NKNrCMjm4H1zgqTxjj6TnPkC1mGEltjAHwLgzJBw62wWGdGhWWpSIGccpBBm1wjTMZpAZfF66fEpP1t1Ta6UjtGZNyvfFIZmE3jdWZ/WXGBnsxtFQKKKBNwrBW0Fbdqq9BQjLxLitmlxbmwrgPttcy855j6vZqq4MBT1v8CtUT/gz4UWW2xWovVnmWOrRSScv7Nh0pMbRpPLkNHXrBwSSNz/keORzXB9JSm85wlkafa7n5/IJbdTml3A/uAgW3q3JZZQotHxQsYvD4Zb5Cnc9CPAXE5L2Yk877kVXZMGt5QPIVcPMj/72AMtaJT67Y0fN0RYHEGkCgYEA38BIGDY6pePgPbxB7N/l6Df0/OKPP0u8mqR4Q0aQD3VxeGiZUN1uWXEFKsKwlOxLfIFIFk1/6zQeC0xetNTKk0gTL8hpMUTNkE7vI9gFWws2LY6DE86Lm0bdFEIwh6d7Fr7zZtyQKPzMsesC3XV9sdSUExEi5o/VwAyf+xZlOXcCgYEA3PGZYlILjg3esPNkhDz2wxFw432i8l/BCPD8ZtqIV9eguu4fVtFYcUVfawBb0T11RamJkc4eiSOqayC+2ehgb+GyRLJNK4FqbFcsIT+CK0HlscZw51jrMR0MxTc4RzuOIMoYDeZqeGB6/YnNyG4pw2sD8bIwHm8406gtJsX/v10CgYAo8g3/aEUZQHcztPS3fU2cTkkl0ev24Ew2XGypmwsX2R0XtMSBuNPNyFHyvkgEKK2zrhDcC/ihuRraZHJcUyhzBViFgP5HBtk7VEaM36YzP/z9Hzw7bqu7kZ85atdoq6xpwC3Yn/o9le17jY8rqamD1mv2hUdGvAGYsHbCQxnpBwKBgHTkeaMUBzr7yZLS4p435tHje1dQVBJpaKaDYPZFrhbTZR0g+IGlNmaPLmFdCjbUjiPyA2+Znnwt227cHz0IfWUUAo3ny3419QkmwZlBkWuzbIO2mms7lwsf9G6uvV6qepKMeVd5TWEsokVbT/03k27pQmfwPxcK/wS0GFdIL/udAoGAOYdDqY5/aadWCyhzTGI6qXPLvC+fsJBPhK2RXyc+jYV0KmrEv4ewxlK5NksuFsNkyB7wlI1oMCa/xB3T/2vTBALgGFPi8BJqceUjtnTYtI4R2JIVEl08RtEJwyU5JZ2rvWcilsotVZYwfuLZ9KfdhkTrgNxlp/KKkr+UuKce4Vs=
\ No newline at end of file
diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml
index c427ae5..35fdb8c 100644
--- a/ruoyi-common/pom.xml
+++ b/ruoyi-common/pom.xml
@@ -126,6 +126,19 @@
javax.servlet-api
+
+ org.projectlombok
+ lombok
+ 1.18.22
+
+
+
+
+ com.tencentcloudapi
+ tencentcloud-sdk-java
+ 3.1.270
+
+
com.tencentcloudapi
tencentcloud-sdk-java-ocr
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtils.java
new file mode 100644
index 0000000..cfc9e84
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtils.java
@@ -0,0 +1,85 @@
+package com.ruoyi.common.utils;
+
+import com.tencentcloudapi.common.Credential;
+import com.tencentcloudapi.common.exception.TencentCloudSDKException;
+import com.tencentcloudapi.common.profile.ClientProfile;
+import com.tencentcloudapi.common.profile.HttpProfile;
+import com.tencentcloudapi.cvm.v20170312.CvmClient;
+import com.tencentcloudapi.cvm.v20170312.models.DescribeRegionsRequest;
+import com.tencentcloudapi.cvm.v20170312.models.DescribeRegionsResponse;
+import com.tencentcloudapi.sms.v20210111.SmsClient;
+import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
+import com.tencentcloudapi.sms.v20210111.models.SendStatus;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import lombok.var;
+
+import java.util.Objects;
+
+@Slf4j
+public class SmsUtils {
+ //应用id
+ private static final String SDK_APP_ID = "1400854852";
+ //API的SecretId
+ private static final String SECRET_ID = "AKIDeEf2A8uX1HSainvvnXAc3X9ZlhtyvkMp";
+ //API的SecretKey
+ private static final String SECRET_KEY = "QjphKo8zkHZigT8j9PVtFPJyfIvO3d6V";
+ //签名内容
+ private static final String SIGN_NAME = "西安云美电子科技有限公司";
+
+ public static Boolean sendSms(SendSmsRequest request) {
+ Credential cred = new Credential(SECRET_ID, SECRET_KEY );
+
+ SmsClient client = new SmsClient(cred, "ap-guangzhou");
+
+ final var req = new com.tencentcloudapi.sms.v20210111.models.SendSmsRequest();
+ req.setPhoneNumberSet(new String[]{"+86" + request.getPhone()});
+ req.setSmsSdkAppId(SDK_APP_ID );
+ req.setSignName(SIGN_NAME);
+ req.setTemplateId(request.getTemplateId());
+ req.setTemplateParamSet(request.getTemplateParamSet());
+ SendSmsResponse res = null;
+ try {
+ res = client.SendSms(req);
+ } catch (TencentCloudSDKException e) {
+ log.error("发送短信出错:", e);
+ return Boolean.FALSE;
+ }
+ SendStatus sendStatus = res.getSendStatusSet()[0];
+ log.info("发送短信结果:Code={}, Message={}", sendStatus.getCode(), sendStatus.getMessage());
+
+ if (Objects.nonNull(res.getSendStatusSet()) && res.getSendStatusSet().length > 0 && "Ok".equals(res.getSendStatusSet()[0].getCode())){
+ return Boolean.TRUE;
+ }
+ return Boolean.FALSE;
+ }
+ /**
+ * 参数对象
+ */
+ @Data
+ public static class SendSmsRequest {
+ /**
+ * 电话
+ */
+ private String phone;
+
+ /**
+ * 模板 ID: 必须填写已审核通过的模板 ID
+ */
+ private String templateId;
+
+ /**
+ * 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致,若无模板参数,则设置为空
+ */
+ private String[] templateParamSet;
+
+ }
+
+ public static void main(String[] args) {
+ SendSmsRequest sendSmsRequest = new SendSmsRequest();
+ sendSmsRequest.setPhone("18792613219");
+ sendSmsRequest.setTemplateId("1928003");
+ sendSmsRequest.setTemplateParamSet(new String[]{"xxx","仲裁","编号"});
+ SmsUtils.sendSms(sendSmsRequest);
+ }
+}
diff --git a/ruoyi-system/pom.xml b/ruoyi-system/pom.xml
index 85d4f3c..435e8f1 100644
--- a/ruoyi-system/pom.xml
+++ b/ruoyi-system/pom.xml
@@ -22,7 +22,11 @@
com.ruoyi
ruoyi-common
-
+
+ com.ruoyi
+ pay
+ 1.0.0-SNAPSHOT
+
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseApplication.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseApplication.java
index 7fa1206..2090c65 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseApplication.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseApplication.java
@@ -2,7 +2,6 @@ package com.ruoyi.wisdomarbitrate.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
-import com.ruoyi.common.annotation.Excels;
import com.ruoyi.common.core.domain.BaseEntity;
import java.math.BigDecimal;
import java.util.Date;
@@ -25,7 +24,7 @@ public class CaseApplication extends BaseEntity {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date registerDate;
/** 仲裁方式 */
- private String arbitratMethod;
+ private int arbitratMethod;
/** 案件状态 */
private int caseStatus;
/** 开庭日期 */
@@ -313,11 +312,11 @@ public class CaseApplication extends BaseEntity {
this.registerDate = registerDate;
}
- public String getArbitratMethod() {
+ public int getArbitratMethod() {
return arbitratMethod;
}
- public void setArbitratMethod(String arbitratMethod) {
+ public void setArbitratMethod(int arbitratMethod) {
this.arbitratMethod = arbitratMethod;
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseAttach.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseAttach.java
new file mode 100644
index 0000000..bce1776
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseAttach.java
@@ -0,0 +1,46 @@
+package com.ruoyi.wisdomarbitrate.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class CaseAttach {
+ /**
+ * 附件id
+ */
+ private Integer annexId;
+ /**
+ * 案件申请id
+ */
+ private Long caseAppliId;
+ /**
+ * 附件名称
+ */
+ private String annexName;
+ /**
+ * 附件路径
+ */
+ private String annexPath;
+ /**
+ * 附件类型,立案申请书(1)、证据材料(2)、仲裁文书(3)、案件视频(4)、身份证件(5)
+ */
+ private Integer annexType;
+ /**
+ * 备注
+ */
+ private String note;
+ /**
+ * 用户id
+ */
+ private Long userId;
+ /**
+ * 用户账户
+ */
+ private String userName;
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseLogRecord.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseLogRecord.java
index 7de2670..4a47bd4 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseLogRecord.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CaseLogRecord.java
@@ -14,7 +14,7 @@ public class CaseLogRecord extends BaseEntity {
/** 案件申请id */
private Long caseAppliId;
/** 案件节点 */
- private String caseNode;
+ private Integer caseNode;
/** 案件节点时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@@ -50,11 +50,11 @@ public class CaseLogRecord extends BaseEntity {
this.caseAppliId = caseAppliId;
}
- public String getCaseNode() {
+ public int getCaseNode() {
return caseNode;
}
- public void setCaseNode(String caseNode) {
+ public void setCaseNode(int caseNode) {
this.caseNode = caseNode;
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CasePaymentRecord.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CasePaymentRecord.java
new file mode 100644
index 0000000..4bae1db
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/CasePaymentRecord.java
@@ -0,0 +1,41 @@
+package com.ruoyi.wisdomarbitrate.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.common.core.domain.BaseEntity;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class CasePaymentRecord {
+ private static final long serialVersionUID = 1L;
+ /**
+ * 主键
+ */
+ private Integer id;
+ /**
+ * 案件id
+ */
+ private Long caseId;
+ /**
+ * 订单号
+ */
+ private String orderNumber;
+ /**
+ * 支付状态(0未支付,1已支付)
+ */
+ private Integer paymentStatus;
+ /**
+ * 支付时间
+ */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date paymentTime;
+
+ /** 创建时间 */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date createTime;
+
+ /** 更新时间 */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date updateTime;
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/dto/CasePayDTO.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/dto/CasePayDTO.java
new file mode 100644
index 0000000..933f300
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/dto/CasePayDTO.java
@@ -0,0 +1,26 @@
+package com.ruoyi.wisdomarbitrate.domain.dto;
+
+import lombok.Data;
+/**
+ * 案件缴费传入参数
+ */
+@Data
+public class CasePayDTO {
+ /**
+ * 案件id
+ */
+ private Long caseId;
+
+ /**
+ * 订单金额 单位:分
+ */
+ private int totalFee;
+ /**
+ * 交易类型 native(扫码) / jsapi(小程序) / app / h5
+ */
+ private String tradeType;
+ /**
+ * 支付方式 wxpay(微信) alipay(支付宝)
+ */
+ private String platform;
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CaseDetailVO.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CaseDetailVO.java
new file mode 100644
index 0000000..b67c73f
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CaseDetailVO.java
@@ -0,0 +1,67 @@
+package com.ruoyi.wisdomarbitrate.domain.vo;
+
+import com.ruoyi.wisdomarbitrate.domain.CaseAttach;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class CaseDetailVO {
+ /**
+ * ID
+ */
+ private Long id;
+ /**
+ * 案件编号
+ */
+ private String caseNum;
+ /**
+ * 申请人姓名
+ */
+ private String applicantName;
+ /**
+ * 被申请人姓名
+ */
+ private String respondentName;
+ /**
+ * 借款开始日期
+ */
+ private Date loanStartDate;
+ /**
+ * 借款结束日期
+ */
+ private Date loanEndDate;
+ /**
+ * 案件标的
+ */
+ private BigDecimal caseSubjectAmount;
+ /**
+ * 申请人主张欠本金
+ */
+ private BigDecimal claimPrinciOwed;
+ /**
+ * 申请人主张欠利息
+ */
+ private BigDecimal claimInterestOwed;
+ /**
+ * 申请人主张违约金
+ */
+ private BigDecimal claimLiquidDamag;
+
+ /**
+ * 证据材料
+ */
+ private List evidenceMaterialList;
+ /**
+ * 当前登录人身份类型
+ */
+ private Integer identityType;
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CaseEvidenceVO.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CaseEvidenceVO.java
new file mode 100644
index 0000000..7dca799
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/domain/vo/CaseEvidenceVO.java
@@ -0,0 +1,28 @@
+package com.ruoyi.wisdomarbitrate.domain.vo;
+
+
+import lombok.Data;
+
+@Data
+public class CaseEvidenceVO {
+ /**
+ * 案件id
+ */
+ private Long id;
+ /**
+ * 案件编号
+ */
+ private String caseNum;
+ /**
+ * 申请人姓名
+ */
+ private String applicantName;
+ /**
+ * 被申请人姓名
+ */
+ private String respondentName;
+ /**
+ * 案件状态
+ */
+ private Integer caseStatus;
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseAttachMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseAttachMapper.java
new file mode 100644
index 0000000..03ea3b2
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseAttachMapper.java
@@ -0,0 +1,11 @@
+package com.ruoyi.wisdomarbitrate.mapper;
+
+import com.ruoyi.wisdomarbitrate.domain.CaseAttach;
+
+import java.util.List;
+
+public interface CaseAttachMapper {
+ int save(CaseAttach caseAttach);
+
+ List queryAnnexPathByCaseId(Long id);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseEvidenceMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseEvidenceMapper.java
new file mode 100644
index 0000000..12a0459
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CaseEvidenceMapper.java
@@ -0,0 +1,15 @@
+package com.ruoyi.wisdomarbitrate.mapper;
+
+import com.ruoyi.wisdomarbitrate.domain.CaseApplication;
+import com.ruoyi.wisdomarbitrate.domain.vo.CaseEvidenceVO;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+@Mapper
+public interface CaseEvidenceMapper {
+ List getCaseListByRespondent(@Param(value = "identityNum" ) String identityNum
+ , @Param(value = "caseStatusList") List caseStatusList
+ , @Param(value = "identityType" ) Integer identityType);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CasePaymentRecordMapper.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CasePaymentRecordMapper.java
new file mode 100644
index 0000000..596abf5
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/mapper/CasePaymentRecordMapper.java
@@ -0,0 +1,11 @@
+package com.ruoyi.wisdomarbitrate.mapper;
+
+import com.ruoyi.wisdomarbitrate.domain.CasePaymentRecord;
+
+public interface CasePaymentRecordMapper {
+ int saveRecord(CasePaymentRecord casePaymentRecord);
+
+ CasePaymentRecord queryRecord(String orderNumber);
+
+ void update(CasePaymentRecord casePaymentRecord);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseArbitrateService.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseArbitrateService.java
new file mode 100644
index 0000000..231ae50
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseArbitrateService.java
@@ -0,0 +1,10 @@
+package com.ruoyi.wisdomarbitrate.service;
+
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.wisdomarbitrate.domain.CaseApplication;
+
+public interface ICaseArbitrateService {
+ AjaxResult chooseArbitrateMethod(CaseApplication caseApplication,Integer arbitratMethod);
+
+ AjaxResult writtenHear(CaseApplication caseApplication, String accidentDescription, String arbitrationResult);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseEvidenceService.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseEvidenceService.java
new file mode 100644
index 0000000..5e801ea
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICaseEvidenceService.java
@@ -0,0 +1,21 @@
+package com.ruoyi.wisdomarbitrate.service;
+
+
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.wisdomarbitrate.domain.CaseApplication;
+import com.ruoyi.wisdomarbitrate.domain.vo.CaseEvidenceVO;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+
+public interface ICaseEvidenceService {
+
+ AjaxResult getCaseDetailsById(Long id,String userName);
+
+ AjaxResult uploadEvidence(MultipartFile file, Integer annexType, Long id,String userName,Long userId);
+
+ List getCaseListAll(String identityNum);
+
+ AjaxResult evidenceConfirmation(CaseApplication caseApplication);
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICasePaymentService.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICasePaymentService.java
new file mode 100644
index 0000000..fc2e24a
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/ICasePaymentService.java
@@ -0,0 +1,15 @@
+package com.ruoyi.wisdomarbitrate.service;
+
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.dto.PayRequest;
+import com.ruoyi.wisdomarbitrate.domain.CaseApplication;
+import com.ruoyi.wisdomarbitrate.domain.dto.CasePayDTO;
+
+public interface ICasePaymentService {
+ /**
+ * 案件缴费
+ */
+ AjaxResult casePay(CasePayDTO casePayDTO);
+
+ AjaxResult confirmPayment(CaseApplication caseApplication);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CallBackHandleServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CallBackHandleServiceImpl.java
new file mode 100644
index 0000000..4812468
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CallBackHandleServiceImpl.java
@@ -0,0 +1,35 @@
+package com.ruoyi.wisdomarbitrate.service.impl;
+
+import com.ruoyi.CallBackService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * 业务回调处理
+ */
+@Component
+@Slf4j
+public class CallBackHandleServiceImpl implements CallBackService {
+ @Autowired
+ private CasePaymentServiceImpl casePaymentService;
+ @Override
+ public void successPay(String orderSn) {
+ casePaymentService.callback(orderSn);
+ }
+
+ @Override
+ public void failPay(String orderSn) {
+ log.info("支付失败回调!"+orderSn);
+ }
+
+ @Override
+ public void successRefund(String orderSn) {
+ log.info("退款成功回调!"+orderSn);
+ }
+
+ @Override
+ public void failRefund(String orderSn) {
+ log.info("退款失败回调!"+orderSn);
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseArbitrateServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseArbitrateServiceImpl.java
new file mode 100644
index 0000000..2a5c68b
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseArbitrateServiceImpl.java
@@ -0,0 +1,102 @@
+package com.ruoyi.wisdomarbitrate.service.impl;
+
+import com.ruoyi.common.constant.CaseApplicationConstants;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.SmsUtils;
+import com.ruoyi.wisdomarbitrate.domain.CaseAffiliate;
+import com.ruoyi.wisdomarbitrate.domain.CaseApplication;
+import com.ruoyi.wisdomarbitrate.domain.CaseLogRecord;
+import com.ruoyi.wisdomarbitrate.mapper.CaseAffiliateMapper;
+import com.ruoyi.wisdomarbitrate.mapper.CaseApplicationMapper;
+import com.ruoyi.wisdomarbitrate.mapper.CaseLogRecordMapper;
+import com.ruoyi.wisdomarbitrate.service.ICaseArbitrateService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+@Service
+public class CaseArbitrateServiceImpl implements ICaseArbitrateService {
+ @Autowired
+ private CaseApplicationMapper caseApplicationMapper;
+ @Autowired
+ private CaseAffiliateMapper caseAffiliateMapper;
+ @Autowired
+ private CaseLogRecordMapper caseLogRecordMapper;
+
+ @Override
+ @Transactional
+ public AjaxResult chooseArbitrateMethod(CaseApplication caseApplication, Integer arbitratMethod) {
+ if (arbitratMethod != null) {
+ String arbitratMethodStr = arbitratMethod == 1 ? "开庭审理" : "书面审理";
+ //查询案件详细信息
+ CaseApplication caseApplication1 = caseApplicationMapper.selectCaseApplication(caseApplication);
+ if (caseApplication1 == null) {
+ return AjaxResult.error();
+ }
+ String caseNum = caseApplication1.getCaseNum();
+ //选择仲裁方式
+ caseApplication.setArbitratMethod(arbitratMethod);
+ //修改案件状态为待开庭
+ caseApplication.setCaseStatus(CaseApplicationConstants.PENDING_OPENCOURT);
+ int i = caseApplicationMapper.submitCaseApplication(caseApplication);
+ if (i > 0) {
+ //发送短信通知
+ SmsUtils.SendSmsRequest request = new SmsUtils.SendSmsRequest();
+ request.setTemplateId("1931000");
+ CaseAffiliate caseAffiliate = new CaseAffiliate();
+ caseAffiliate.setCaseAppliId(caseApplication1.getId());
+ List caseAffiliates = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate); //获取案件关联人信息
+ if (caseAffiliates != null && caseAffiliates.size() > 0) {
+ for (CaseAffiliate affiliate : caseAffiliates) {
+ //获取身份类型
+ int identityType = affiliate.getIdentityType();
+ if (identityType == 1) { //申请人
+ request.setPhone(affiliate.getContactTelphone());
+ // 这个值,要看你的模板中是否预留了占位符,如果没有则不需要设置
+ // 1931000 普通短信 确定仲裁方式通知 尊敬的{1}用户,您的{2}仲裁案件,仲裁方式已确定为{3},请知晓,如非本人操作,请忽略本短信。
+ String name = affiliate.getName();
+ request.setTemplateParamSet(new String[]{name, caseNum, arbitratMethodStr});
+ SmsUtils.sendSms(request);
+ } else { //被申请人
+ request.setPhone(affiliate.getContactTelphone());
+ // 模板id1928006 普通短信 案件应诉通知 尊敬的{1}用户,您的{2}案件{3}已成功受理,请点击https://phmapp.xayunmei.com选择是否应诉。
+ String name = affiliate.getName();
+ request.setTemplateParamSet(new String[]{name, caseNum, arbitratMethodStr});
+ SmsUtils.sendSms(request);
+ }
+ }
+ }
+ return AjaxResult.success("选择成功");
+ }
+
+ }
+ return AjaxResult.error("请选择开庭方式");
+ }
+
+ @Override
+ public AjaxResult writtenHear(CaseApplication caseApplication, String accidentDescription, String arbitrationResult) {
+ //提交仲裁结果
+ CaseApplication caseApplication1 = caseApplicationMapper.selectCaseApplication(caseApplication);
+ caseApplication1.setCaseDescribe(accidentDescription); //案情描述
+ caseApplication1.setCaseResult(arbitrationResult); //仲裁结果
+ int i = caseApplicationMapper.updataCaseApplication(caseApplication1);
+ if (i>0){
+ //案件日志表里添加数据
+ CaseLogRecord caseLogRecord = new CaseLogRecord();
+ caseLogRecord.setCaseAppliId(caseApplication1.getId());
+ caseLogRecord.setCaseNode(caseApplication1.getCaseStatus());
+ String createBy = caseApplication1.getCreateBy();
+ if (createBy!=null){
+ caseLogRecord.setCreateBy(createBy);
+ }
+ caseLogRecordMapper.insertCaseLogRecord(caseLogRecord);
+ //修改案件状态
+ caseApplication.setCaseStatus(CaseApplicationConstants.GENERATED_ARBITRATION);
+ caseApplicationMapper.submitCaseApplication(caseApplication);
+ return AjaxResult.success("提交成功");
+ }
+ return AjaxResult.error("暂无需要提交仲裁结果的案件");
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseEvidenceServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseEvidenceServiceImpl.java
new file mode 100644
index 0000000..40df38d
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseEvidenceServiceImpl.java
@@ -0,0 +1,145 @@
+package com.ruoyi.wisdomarbitrate.service.impl;
+
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.constant.CaseApplicationConstants;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.file.FileUploadUtils;
+import com.ruoyi.wisdomarbitrate.domain.CaseAffiliate;
+import com.ruoyi.wisdomarbitrate.domain.CaseApplication;
+import com.ruoyi.wisdomarbitrate.domain.CaseAttach;
+import com.ruoyi.wisdomarbitrate.domain.vo.CaseDetailVO;
+import com.ruoyi.wisdomarbitrate.domain.vo.CaseEvidenceVO;
+import com.ruoyi.wisdomarbitrate.mapper.CaseAffiliateMapper;
+import com.ruoyi.wisdomarbitrate.mapper.CaseApplicationMapper;
+import com.ruoyi.wisdomarbitrate.mapper.CaseAttachMapper;
+import com.ruoyi.wisdomarbitrate.mapper.CaseEvidenceMapper;
+import com.ruoyi.wisdomarbitrate.service.ICaseEvidenceService;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Arrays;
+import java.util.List;
+
+@Service
+public class CaseEvidenceServiceImpl implements ICaseEvidenceService {
+ @Autowired
+ private CaseEvidenceMapper caseEvidenceMapper;
+ @Autowired
+ private CaseAffiliateMapper caseAffiliateMapper;
+ @Autowired
+ private CaseApplicationMapper caseApplicationMapper;
+ @Autowired
+ private CaseAttachMapper caseAttachMapper;
+
+ @Override
+ @Transactional
+ public AjaxResult getCaseDetailsById(Long id,String userName) {
+ CaseApplication caseApplication = new CaseApplication();
+ caseApplication.setId(id);
+ CaseApplication caseApplication1 = caseApplicationMapper.selectCaseApplication(caseApplication);
+ if (caseApplication1 != null) {
+ CaseDetailVO caseDetailVO = new CaseDetailVO();
+ BeanUtils.copyProperties(caseApplication1, caseDetailVO);
+ CaseAffiliate caseAffiliate = new CaseAffiliate();
+ caseAffiliate.setCaseAppliId(id);
+ List caseAffiliates = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate);
+ for (CaseAffiliate affiliate : caseAffiliates) {
+ String name = affiliate.getName();
+ //判断当前登录人和案件关联人姓名是否一致
+ if (name.equals(userName)) { //一致,将案件关联人的身份类型赋给当前登录人
+ caseDetailVO.setIdentityType(affiliate.getIdentityType());
+ }
+ if (affiliate.getIdentityType() == 1) { //申请人
+ caseDetailVO.setApplicantName(affiliate.getName());
+ } else {
+ caseDetailVO.setRespondentName(affiliate.getName());
+ }
+ //根据案件id查询案件证据材料
+ List evidenceMaterialList = caseAttachMapper.queryAnnexPathByCaseId(id);
+ caseDetailVO.setEvidenceMaterialList(evidenceMaterialList);
+ }
+ return AjaxResult.success(caseDetailVO);
+ }
+ return null;
+ }
+
+ @Override
+ @Transactional
+ public AjaxResult uploadEvidence(MultipartFile file, Integer annexType, Long id, String userName, Long userId) {
+
+ if (file.isEmpty()) {
+ return AjaxResult.error("请选择要上传的文件");
+ }
+ try {
+ String filePath = RuoYiConfig.getUploadPath();
+ // 上传
+ String fileName = FileUploadUtils.upload(filePath, file);
+ CaseAttach caseAttach = CaseAttach.builder().caseAppliId(id)
+ .annexName(fileName)
+ .annexPath(filePath)
+ .annexType(annexType)
+ .userId(userId)
+ .userName(userName)
+ .build();
+ int count = caseAttachMapper.save(caseAttach);
+ if (count > 0) {
+ //修改案件状态
+ CaseApplication caseApplication = new CaseApplication();
+ caseApplication.setId(id);
+ caseApplication.setCaseStatus(4);
+ caseApplicationMapper.submitCaseApplication(caseApplication);
+ return AjaxResult.success("上传成功");
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ return AjaxResult.error("上传失败");
+ }
+
+
+
+ @Override
+ public List getCaseListAll(String identityNum) {
+ List caseStatusList = Arrays.asList(3, 4, 5, 9);
+ return getCaseEvidenceVOList(identityNum, caseStatusList, null);
+ }
+
+ @Override
+ public AjaxResult evidenceConfirmation(CaseApplication caseApplication) {
+ caseApplication.setCaseStatus(CaseApplicationConstants.PENDING_APPOINT_ARBOTRATAR);
+ int i = caseApplicationMapper.submitCaseApplication(caseApplication);
+ if (i>0){
+ return AjaxResult.success("证据确认成功");
+ }
+ return AjaxResult.error("暂无需要确认的证据");
+ }
+
+ private List getCaseEvidenceVOList(String identityNum, List caseStatusList, Integer identityType) {
+ List caseListByRespondent = caseEvidenceMapper.getCaseListByRespondent(identityNum, caseStatusList, identityType);
+ if (caseListByRespondent != null && caseListByRespondent.size() > 0) {
+ for (CaseEvidenceVO caseEvidenceVO : caseListByRespondent) {
+ //根据案件id查询姓名
+ CaseAffiliate caseAffiliate = new CaseAffiliate();
+ caseAffiliate.setCaseAppliId(caseEvidenceVO.getId());
+ List caseAffiliates = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate);
+ for (CaseAffiliate affiliate : caseAffiliates) {
+ if (affiliate.getIdentityType() == 1) { //申请人
+ caseEvidenceVO.setApplicantName(affiliate.getName());
+ } else {
+ caseEvidenceVO.setRespondentName(affiliate.getName());
+ }
+ }
+ }
+ return caseListByRespondent;
+ }
+ return null;
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseLogRecordServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseLogRecordServiceImpl.java
index 6d07ec5..de484db 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseLogRecordServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseLogRecordServiceImpl.java
@@ -17,7 +17,6 @@ public class CaseLogRecordServiceImpl implements ICaseLogRecordService {
@Override
public List selectCaseLogRecordList(CaseLogRecord caseLogRecord) {
return caseLogRecordMapper.selectCaseLogRecordList(caseLogRecord);
-
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CasePaymentServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CasePaymentServiceImpl.java
new file mode 100644
index 0000000..d375246
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CasePaymentServiceImpl.java
@@ -0,0 +1,135 @@
+package com.ruoyi.wisdomarbitrate.service.impl;
+
+
+import com.ruoyi.ElegentPay;
+import com.ruoyi.common.constant.CaseApplicationConstants;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.SmsUtils;
+import com.ruoyi.dto.PayRequest;
+import com.ruoyi.dto.PayResponse;
+import com.ruoyi.wisdomarbitrate.domain.CaseAffiliate;
+import com.ruoyi.wisdomarbitrate.domain.CaseApplication;
+import com.ruoyi.wisdomarbitrate.domain.CasePaymentRecord;
+import com.ruoyi.wisdomarbitrate.domain.dto.CasePayDTO;
+import com.ruoyi.wisdomarbitrate.mapper.CaseAffiliateMapper;
+import com.ruoyi.wisdomarbitrate.mapper.CaseApplicationMapper;
+import com.ruoyi.wisdomarbitrate.mapper.CasePaymentRecordMapper;
+import com.ruoyi.wisdomarbitrate.service.ICasePaymentService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.List;
+
+@Service
+public class CasePaymentServiceImpl implements ICasePaymentService {
+ private final ElegentPay elegentPay;
+ private final CaseApplicationMapper caseApplicationMapper;
+ private final CasePaymentRecordMapper casePaymentRecordMapper;
+ private final CaseAffiliateMapper caseAffiliateMapper;
+
+ @Autowired
+ public CasePaymentServiceImpl(ElegentPay elegentPay
+ , CaseApplicationMapper caseApplicationMapper
+ , CasePaymentRecordMapper casePaymentRecordMapper
+ , CaseAffiliateMapper caseAffiliateMapper) {
+ this.elegentPay = elegentPay;
+ this.caseApplicationMapper = caseApplicationMapper;
+ this.casePaymentRecordMapper = casePaymentRecordMapper;
+ this.caseAffiliateMapper = caseAffiliateMapper;
+ }
+
+ @Override
+ @Transactional
+ public AjaxResult casePay(CasePayDTO casePayDTO) {
+ PayRequest payRequest = new PayRequest();
+ payRequest.setBody("案件缴费");
+ payRequest.setOrderSn(System.currentTimeMillis() + "");
+ payRequest.setTotalFee(casePayDTO.getTotalFee());
+ PayResponse response = elegentPay.requestPay(payRequest, casePayDTO.getTradeType(), casePayDTO.getPlatform());
+ if (response.getCode_url() == null) {
+ return AjaxResult.error();
+ }
+ //缴费记录表里新增数据
+ CasePaymentRecord casePaymentRecord = new CasePaymentRecord();
+ casePaymentRecord.setCaseId(casePayDTO.getCaseId());
+ casePaymentRecord.setOrderNumber(payRequest.getOrderSn());
+ casePaymentRecord.setPaymentStatus(0);
+ casePaymentRecord.setCreateTime(new Date());
+ int count = casePaymentRecordMapper.saveRecord(casePaymentRecord);
+ if (count < 1) {
+ return AjaxResult.error("请检查参数是否有误");
+ }
+ return AjaxResult.success(response);
+ }
+
+ @Transactional
+ public AjaxResult callback(String orderNumber) {
+ //查询记录
+ CasePaymentRecord casePaymentRecord = casePaymentRecordMapper.queryRecord(orderNumber);
+ if (casePaymentRecord == null) {
+ return AjaxResult.error("未查询到相关记录");
+ }
+ Long caseId = casePaymentRecord.getCaseId();
+ //更改记录表里的支付状态和支付时间
+ casePaymentRecord.setPaymentStatus(1);
+ casePaymentRecord.setPaymentTime(new Date());
+ casePaymentRecord.setUpdateTime(new Date());
+ casePaymentRecordMapper.update(casePaymentRecord);
+ //根据案件id查询案件信息
+ CaseApplication caseApplication = new CaseApplication();
+ caseApplication.setId(caseId);
+ CaseApplication caseApplication1 = caseApplicationMapper.selectCaseApplication(caseApplication);
+ caseApplication1.setCaseStatus(CaseApplicationConstants.PENDING_PAYMENT_CONFIRM);
+ //修改案件状态
+ caseApplicationMapper.submitCaseApplication(caseApplication1);
+ return AjaxResult.success();
+ }
+
+ @Override
+ @Transactional
+ public AjaxResult confirmPayment(CaseApplication caseApplication) {
+ caseApplication.setCaseStatus(CaseApplicationConstants.CONFIRMDED_RESPOND);
+ int i = caseApplicationMapper.submitCaseApplication(caseApplication);
+ if (i > 0) {
+ //发送短信通知
+ SmsUtils.SendSmsRequest request = new SmsUtils.SendSmsRequest();
+ CaseAffiliate caseAffiliate = new CaseAffiliate();
+ caseAffiliate.setCaseAppliId(caseApplication.getId());
+ List caseAffiliates = caseAffiliateMapper.selectCaseAffiliate(caseAffiliate); //获取案件关联人信息
+ if (caseAffiliates != null && caseAffiliates.size() > 0) {
+ for (CaseAffiliate affiliate : caseAffiliates) {
+ //获取身份类型
+ int identityType = affiliate.getIdentityType();
+ //查询案件详细信息
+ CaseApplication caseApplication1 = caseApplicationMapper.selectCaseApplication(caseApplication);
+ if (caseApplication1 == null) {
+ return AjaxResult.error();
+ }
+ String caseName = "仲裁"; //这里案件名称表里未定义,暂时写死
+ String caseNum = caseApplication1.getCaseNum();
+ if (identityType == 1) { //申请人
+ request.setPhone(affiliate.getContactTelphone());
+ request.setTemplateId("1928003"); //传入申请人模板id
+ // 这个值,要看你的模板中是否预留了占位符,如果没有则不需要设置
+ // 模板id:1928003 普通短信 案件受理通知 尊敬的{1}用户,您的{2}案件{3}已成功受理。
+ String name = affiliate.getName();
+ request.setTemplateParamSet(new String[]{name, caseName, caseNum});
+ SmsUtils.sendSms(request);
+ } else { //被申请人
+ request.setPhone(affiliate.getContactTelphone());
+ request.setTemplateId("1928006");
+ // 模板id1928006 普通短信 案件应诉通知 尊敬的{1}用户,您的{2}案件{3}已成功受理,请点击https://phmapp.xayunmei.com选择是否应诉。
+ String name = affiliate.getName();
+ request.setTemplateParamSet(new String[]{name, caseName, caseNum});
+ SmsUtils.sendSms(request);
+ }
+ }
+ return AjaxResult.success();
+ }
+ }
+ return AjaxResult.error("暂无需要确认的缴费清单");
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/IdentityAuthenticationServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/IdentityAuthenticationServiceImpl.java
index c01a3e1..3940c49 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/IdentityAuthenticationServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/IdentityAuthenticationServiceImpl.java
@@ -40,7 +40,7 @@ public class IdentityAuthenticationServiceImpl implements IdentityAuthenticatio
@Override
public IdentityAuthentication selectIdentityInformation() {
- IdentityAuthentication identityAuthentication = new IdentityAuthentication();
+ /* IdentityAuthentication identityAuthentication = new IdentityAuthentication();
try{
Credential credIdentityAuthentication = new Credential(credentialSecretId, credentialSecretKey);
HttpProfile httpProfileIdentityAuthentication = new HttpProfile();
@@ -92,7 +92,8 @@ public class IdentityAuthenticationServiceImpl implements IdentityAuthenticatio
log.error("身份认证失败", e);
}
- return identityAuthentication;
-
+ return identityAuthentication;*/
+ return null;
}
+
}
diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseApplicationMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseApplicationMapper.xml
index e215199..5a13565 100644
--- a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseApplicationMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseApplicationMapper.xml
@@ -145,6 +145,7 @@
arbitrator_id = #{arbitratorId},
arbitrator_name = #{arbitratorName},
pending_appoint_arbotrar = #{pendingAppointArbotrar},
+ arbitrat_method = #{arbitratMethod},
case_name = #{caseName},
case_describe = #{caseDescribe},
case_result = #{caseResult},
diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseAttachMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseAttachMapper.xml
new file mode 100644
index 0000000..5d7714d
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseAttachMapper.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ INSERT INTO case_attach (case_appli_id, annex_name, annex_path , annex_type,note,use_id,use_account)
+ VALUES (#{caseAppliId}, #{annexName}, #{annexPath},#{annexType},#{note},#{userId},#{userName})
+
+
+
\ No newline at end of file
diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseEvidenceMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseEvidenceMapper.xml
new file mode 100644
index 0000000..3d925a6
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseEvidenceMapper.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CasePaymentRecordMapper.xml b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CasePaymentRecordMapper.xml
new file mode 100644
index 0000000..a50bb99
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CasePaymentRecordMapper.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ INSERT INTO case_payment_record (case_id, order_number, payment_status , create_time)
+ VALUES (#{caseId}, #{orderNumber}, #{paymentStatus},#{createTime})
+
+
+ update case_payment_record
+
+ case_id= #{caseId},
+ order_number = #{orderNumber},
+ payment_time = #{paymentTime},
+ payment_status = #{paymentStatus},
+ update_time = #{updateTime},
+
+ where id = #{id}
+
+
+
\ No newline at end of file