Merge branch 'hjb' of SH-Arbitrate/Arbitrate-Backend into dev

This commit was merged in pull request #9.
This commit is contained in:
2023-09-18 19:54:39 +08:00
committed by Gitea
75 changed files with 3522 additions and 23 deletions
+59
View File
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>3.8.6</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>pay</artifactId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.7.10</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.72</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.12</version>
</dependency>
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.4.7</version>
</dependency>
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.34.8.ALL</version>
</dependency>
</dependencies>
</project>
@@ -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);
}
@@ -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);
}
@@ -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");
}
}
@@ -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<String,String> TRADE_STATE = new HashMap<String,String>(){
{
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";
}
@@ -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();
}
}
@@ -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<String> httpEntity, HttpServletRequest httpRequest) throws TradeException {
ValidResponse validResponse=new ValidResponse();
try {
Map<String, String> 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<String> httpEntity, HttpServletRequest httpRequest) throws TradeException {
ValidResponse validResponse=new ValidResponse();
try {
//获取支付宝POST过来反馈信息,将异步通知中收到的待验证所有参数都存放到map中
Map<String, String> 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<String,String> getParams(HttpServletRequest httpServletRequest){
Map<String,String> 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;
}
}
@@ -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();
}
@@ -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;//检查周期
}
@@ -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";
}
@@ -0,0 +1,16 @@
package com.ruoyi.constant;
/**
* Platform
* 支付方式
*/
public class Platform {
/**
* 微信
*/
public final static String WX = "wxpay";
/**
* 支付宝
*/
public final static String ALI = "alipay";
}
@@ -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";
}
@@ -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);
}
}
@@ -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<String> 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<String> 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();
}
}
}
@@ -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);
}
}
@@ -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();
}
}
@@ -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<String, ElegentTrade> elegentTradeMap = new HashMap<>();
private static Map<String, ElegentValid> elegentValidMap = new HashMap<>();
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//加载所有的交易实现类
Collection<ElegentTrade> 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<ElegentValid> 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);
}
}
}
@@ -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);
}
}
@@ -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);
}
@@ -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<String> httpEntity, HttpServletRequest request) throws TradeException;
/**
* 退款结果通知校验
* 该接口基于设计模式实现,对接了微信V3版支付代码和支付宝支付sdk
* 业务编写人员在接收到微信或支付宝回调的时候可以使用该方法验证回调是否成功,是否是伪回调
*/
ValidResponse validRefund(HttpEntity<String> httpEntity, HttpServletRequest request) throws TradeException;
/**
* 成功返回结构
* @return
*/
String successResult();
/**
* 失败返回内容
* @return
*/
String failResult();
}
@@ -0,0 +1,20 @@
package com.ruoyi.core;
import com.ruoyi.dto.WatchDTO;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* 监听列表
*/
public class WatchList {
public static CopyOnWriteArraySet<WatchDTO> payList=new CopyOnWriteArraySet<>(); //支付中列表
public static CopyOnWriteArraySet<WatchDTO> refundList=new CopyOnWriteArraySet<>(); //退款中列表
}
@@ -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
}
@@ -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<String,String> expand;//扩展属性
private String code_url;//二维码连接(native返回)
private String prepay_id;//预支付Id(小程序返回)
private String h5_url;//支付跳转链接
private Map<String,String> jsapiData;//小程序返回
}
@@ -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;//退款金额
}
@@ -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;//扩展(全部的返回数据)
}
@@ -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; //退款请求号,做退款幂等性校验,当部分退款时必须给出
}
@@ -0,0 +1,15 @@
package com.ruoyi.dto;
import lombok.Data;
/**
* 验证签名
*/
@Data
public class ValidResponse {
private boolean isValid;// 是否通过验签
private String orderSn;// 订单号
}
@@ -0,0 +1,12 @@
package com.ruoyi.dto;
import lombok.Data;
@Data
public class WatchDTO {
private String orderSn; //订单号
private String platform;//平台
}
@@ -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);
}
}
@@ -0,0 +1,16 @@
package com.ruoyi.key;
/**
* 密钥管理器接口
*/
public interface KeyManager {
/**
* 根据名字获取key字符串
* @param name
* @return
*/
String getKey(String name);
}
@@ -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);
}
}
@@ -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;
}
}
@@ -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<String, Object> params = new HashMap<String, Object>() {
{
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<String, Object>() {
{
put("total", payRequest.getTotalFee());//金额,单位:分
put("currency", "CNY");//人民币
}
});
put("description", payRequest.getBody());
}
};
if("h5".equals(tradeType)){ //h5
params.put("scene_info", new HashMap<String, Object>() {
{
put("payer_client_ip", "127.0.0.1");
put("h5_info", new HashMap<String, Object>() {
{
put("type", "Wap");
}
});
}
});
}
if ("jsapi".equals(tradeType)) { //如果是小程序支付
params.put("payer", new HashMap<String, Object>() {
{
put("openid", payRequest.getOpenid());
}
});
}
String url = WxpayConstant.createOrder + tradeType; //创建订单
log.info("elegent-pay 请求参数{}",params);
Map<String, String> 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<String, String> 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<String, Object> params = new HashMap<String, Object>();
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<String, Object> params = new HashMap<String, Object>();
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<String, Object>() {
{
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<String, String> params = new HashMap<String, String>();
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<String, String> params = new HashMap<String, String>();
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<String,String> 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<String, String> 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<String, Object>() {
{
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<String, String> map = JSON.parseObject(returnBody, Map.class);
result = new HashMap<String, Object>() {
{
put("code", "FAIL");
put("message", map.get("message"));
}
};
}
} catch (Exception e) {
result = new HashMap<String, Object>() {
{
put("code", "FAIL");
put("message", e.getMessage());
}
};
} finally {
closeConnect(response);
return result;
}
}
private Map postApiTemplate(String url, Map<String, Object> 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());
}
}
@@ -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<String> 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<String> 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);
}
}
@@ -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密钥
}
@@ -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<String,Object>(){
{
put("code", "SUCCESS");
}
};
public static final Map FAIL = new HashMap<String,Object>(){
{
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";
}
@@ -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
+1
View File
@@ -180,6 +180,7 @@
<module>ruoyi-quartz</module>
<module>ruoyi-generator</module>
<module>ruoyi-common</module>
<module>pay</module>
</modules>
<packaging>pom</packaging>
+5 -1
View File
@@ -60,7 +60,11 @@
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-generator</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>pay</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
@@ -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;
@@ -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
@@ -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);
}
}
@@ -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<CaseEvidenceVO> 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);
}
}
@@ -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);
}
}
@@ -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
@@ -0,0 +1 @@
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhUnjdAKwZApwZEcfq+5L0pa77Vg3mqcoXv+th8RR0SYotkPsH1f2JkbS48ySaSCM6YNWSMNfqp5qdOla2zUJOBnJ/yaBg7s7fVD6V3M2mEog8kCDYGKt/3P4VII3xYl8lFYMQ3IcFRELkxCBBCA8JDKmf5z2R4F/Z/jFFEuOwxaJvp+7Ke9OzZHYdWGNnU6QP8YYLYUeX7VNZLHEuly34ExAw6A+yJkNDsYEho2Lu31QjT2pLh9g+88MlRfiI92iN25O9NVdeM4f5RcpvBPrBQZQs9tlFmALYSFS3prIf3FAobWM+W7iwxT6J25nFIhst1DdJQfIBpaeRUJVTkn99QIDAQAB
@@ -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:
# 从数据源开关/默认关闭
+22 -4
View File
@@ -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
@@ -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=
+13
View File
@@ -126,6 +126,19 @@
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
<!-- 腾讯短信sdk -->
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java</artifactId>
<version>3.1.270</version>
</dependency>
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java-ocr</artifactId>
@@ -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);
}
}
+5 -1
View File
@@ -22,7 +22,11 @@
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>pay</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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<CaseAttach> evidenceMaterialList;
/**
* 当前登录人身份类型
*/
private Integer identityType;
}
@@ -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;
}
@@ -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<CaseAttach> queryAnnexPathByCaseId(Long id);
}
@@ -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<CaseEvidenceVO> getCaseListByRespondent(@Param(value = "identityNum" ) String identityNum
, @Param(value = "caseStatusList") List<Integer> caseStatusList
, @Param(value = "identityType" ) Integer identityType);
}
@@ -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);
}
@@ -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);
}
@@ -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<CaseEvidenceVO> getCaseListAll(String identityNum);
AjaxResult evidenceConfirmation(CaseApplication caseApplication);
}
@@ -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);
}
@@ -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);
}
}
@@ -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<CaseAffiliate> 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("暂无需要提交仲裁结果的案件");
}
}
@@ -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<CaseAffiliate> 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<CaseAttach> 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<CaseEvidenceVO> getCaseListAll(String identityNum) {
List<Integer> 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<CaseEvidenceVO> getCaseEvidenceVOList(String identityNum, List<Integer> caseStatusList, Integer identityType) {
List<CaseEvidenceVO> 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<CaseAffiliate> 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;
}
}
@@ -17,7 +17,6 @@ public class CaseLogRecordServiceImpl implements ICaseLogRecordService {
@Override
public List<CaseLogRecord> selectCaseLogRecordList(CaseLogRecord caseLogRecord) {
return caseLogRecordMapper.selectCaseLogRecordList(caseLogRecord);
}
@@ -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<CaseAffiliate> 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("暂无需要确认的缴费清单");
}
}
@@ -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;
}
}
@@ -145,6 +145,7 @@
<if test="arbitratorId != null and arbitratorId != ''">arbitrator_id = #{arbitratorId},</if>
<if test="arbitratorName != null and arbitratorName != ''">arbitrator_name = #{arbitratorName},</if>
<if test="pendingAppointArbotrar != null ">pending_appoint_arbotrar = #{pendingAppointArbotrar},</if>
<if test="arbitratMethod != null ">arbitrat_method = #{arbitratMethod},</if>
<if test="caseName != null and caseName != ''">case_name = #{caseName},</if>
<if test="caseDescribe != null and caseDescribe != ''">case_describe = #{caseDescribe},</if>
<if test="caseResult != null and caseResult != ''">case_result = #{caseResult},</if>
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.wisdomarbitrate.mapper.CaseAttachMapper">
<resultMap type="CaseAttach" id="CaseAttachResult">
<id property="annexId" column="annex_id" />
<result property="caseAppliId" column="case_appli_id" />
<result property="annexName" column="annex_name" />
<result property="annexPath" column="annex_path" />
<result property="annexType" column="annex_type" />
<result property="note" column="note" />
<result property="userId" column="use_id" />
<result property="userName" column="use_account" />
</resultMap>
<insert id="save">
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})
</insert>
<select id="queryAnnexPathByCaseId" resultType="com.ruoyi.wisdomarbitrate.domain.CaseAttach" resultMap="CaseAttachResult">
select annex_id,case_appli_id,annex_name,annex_path,annex_type,note,use_id,use_account
from case_attach
where case_appli_id =#{id}
</select>
</mapper>
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.wisdomarbitrate.mapper.CaseEvidenceMapper">
<resultMap type="CaseEvidenceVO" id="CaseEvidenceVOResult">
<id property="id" column="id" />
<result property="caseNum" column="case_num" />
<result property="caseStatus" column="case_status" />
</resultMap>
<select id="getCaseListByRespondent" resultType="CaseEvidenceVO" resultMap="CaseEvidenceVOResult">
select c.id, c.case_num,c.case_status
from case_application as c ,case_affiliate as d
where c.id = d.case_appli_id
<if test="identityNum != null and identityNum != ''">
and d.identity_num = #{identityNum}
</if>
<if test="identityType != null ">
and identity_type = #{identityType}
</if>
<if test="caseStatusList != null and caseStatusList.size() > 0">
and c.case_status in
<foreach item="caseStatus" collection="caseStatusList" open="(" separator="," close=")">
#{caseStatus}
</foreach>
</if>
</select>
</mapper>
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.wisdomarbitrate.mapper.CasePaymentRecordMapper">
<resultMap type="CasePaymentRecord" id="CasePaymentRecordResult">
<id property="id" column="id" />
<result property="caseId" column="case_id" />
<result property="orderNumber" column="order_number" />
<result property="paymentStatus" column="payment_status" />
<result property="paymentTime" column="payment_time" />
<result property="createTime" column="create_time" />
<result property="updateTime" column="update_time" />
</resultMap>
<insert id="saveRecord">
INSERT INTO case_payment_record (case_id, order_number, payment_status , create_time)
VALUES (#{caseId}, #{orderNumber}, #{paymentStatus},#{createTime})
</insert>
<update id="update">
update case_payment_record
<set>
<if test="caseId != null">case_id= #{caseId},</if>
<if test="orderNumber != null and orderNumber != ''">order_number = #{orderNumber},</if>
<if test="paymentTime != null ">payment_time = #{paymentTime},</if>
<if test="paymentStatus != null ">payment_status = #{paymentStatus},</if>
<if test="updateTime != null ">update_time = #{updateTime},</if>
</set>
where id = #{id}
</update>
<select id="queryRecord" resultType="com.ruoyi.wisdomarbitrate.domain.CasePaymentRecord" resultMap="CasePaymentRecordResult">
select c.id ,c.case_id ,c.order_number ,c.payment_time ,c.create_time ,c.update_time ,c.payment_status
from case_payment_record c
<where>
<if test="orderNumber != null ">
AND c.order_number = #{orderNumber}
</if>
</where>
</select>
</mapper>