This commit is contained in:
77
2024-11-25 18:09:52 +08:00
parent ab685878b7
commit fa1d6df347
16 changed files with 542 additions and 111 deletions

View File

@@ -1,2 +1,19 @@
ALTER TABLE `cai_account` ALTER TABLE `cai_account`
ADD COLUMN `total_trd_money` decimal(20, 2) NOT NULL DEFAULT 0 COMMENT '三方充值总额' AFTER `total_buy_coin`; ADD COLUMN `total_trd_money` decimal(20, 2) NOT NULL DEFAULT 0 COMMENT '三方充值总额' AFTER `total_buy_coin`;
CREATE TABLE `cai_pay_trd_config`
(
`id` bigint NOT NULL AUTO_INCREMENT,
`type` varchar(100) NOT NULL COMMENT '第三方支付类型',
`name` varchar(100) NOT NULL COMMENT '第三方支付名称',
`gateway_url` varchar(100) DEFAULT NULL COMMENT '请求域名',
`notify_url` varchar(100) NOT NULL COMMENT '回调域名',
`mch_id` varchar(100) NOT NULL COMMENT '商户ID',
`sign` varchar(200) NOT NULL COMMENT '秘钥',
`delete_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB
AUTO_INCREMENT = 1;

View File

@@ -2,15 +2,15 @@ package com.ruoyi.web.controller.cai.admin.init;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.dtflys.forest.annotation.JSONBody;
import com.ruoyi.cai.pay.PayOrderInfoDTO;
import com.ruoyi.cai.service.CitysService; import com.ruoyi.cai.service.CitysService;
import com.ruoyi.cai.trdpay.TrdPayManager; import com.ruoyi.cai.service.PayTrdConfigService;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Validated @Validated
@RequiredArgsConstructor @RequiredArgsConstructor
@@ -21,7 +21,7 @@ public class CityController {
@Autowired @Autowired
private CitysService citysService; private CitysService citysService;
@Autowired @Autowired
private TrdPayManager trdPayManager; private PayTrdConfigService payTrdConfigService;
@GetMapping("/resetRedis") @GetMapping("/resetRedis")
public R<Void> resetRedis(){ public R<Void> resetRedis(){
@@ -30,14 +30,21 @@ public class CityController {
} }
@GetMapping("/resetOrder") @GetMapping("/resetOrder")
public R<JSONObject> resetOrder(String orderNo){ public R<JSONObject> resetOrder(String orderNo,String payType){
JSONObject jsonObject = trdPayManager.resetOrder(orderNo); JSONObject jsonObject = payTrdConfigService.resetOrder(orderNo,payType);
return R.ok(jsonObject); return R.ok(jsonObject);
} }
@PostMapping("/createOrder")
public R<String> createOrder(@RequestBody PayOrderInfoDTO dto){
String orderAli = payTrdConfigService.createOrderAli(dto);
return R.ok(orderAli);
}
@GetMapping("/queryOrder") @GetMapping("/queryOrder")
public R<JSONObject> queryOrder(String orderNo){ public R<JSONObject> queryOrder(String orderNo,String payType){
JSONObject jsonObject = trdPayManager.queryOrder(orderNo); JSONObject jsonObject = payTrdConfigService.queryOrder(orderNo,payType);
return R.ok(jsonObject); return R.ok(jsonObject);
} }
} }

View File

@@ -19,6 +19,7 @@ import com.ruoyi.cai.dto.app.vo.pay.OrderPayStatusResp;
import com.ruoyi.cai.enums.SystemConfigEnum; import com.ruoyi.cai.enums.SystemConfigEnum;
import com.ruoyi.cai.manager.SystemConfigManager; import com.ruoyi.cai.manager.SystemConfigManager;
import com.ruoyi.cai.pay.*; import com.ruoyi.cai.pay.*;
import com.ruoyi.cai.service.PayTrdConfigService;
import com.ruoyi.cai.trdpay.TrdPayManager; import com.ruoyi.cai.trdpay.TrdPayManager;
import com.ruoyi.cai.trdpay.TrdPayProperties; import com.ruoyi.cai.trdpay.TrdPayProperties;
import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.Log;
@@ -49,11 +50,9 @@ public class PayController {
@Autowired @Autowired
private PayManager payManager; private PayManager payManager;
@Autowired @Autowired
private TrdPayProperties trdPayProperties;
@Autowired
private TrdPayManager trdPayManager; private TrdPayManager trdPayManager;
@Autowired @Autowired
private SystemConfigManager systemConfigManager; private PayTrdConfigService payTrdConfigService;
private static final String NOTIFY_WX_URL = "/api/pay/wx/notify"; private static final String NOTIFY_WX_URL = "/api/pay/wx/notify";
private static final String NOTIFY_ALI_URL = "/api/pay/ali/notify"; private static final String NOTIFY_ALI_URL = "/api/pay/ali/notify";
@@ -86,14 +85,9 @@ public class PayController {
return R.fail(600,"支付失败,未找到订单"); return R.fail(600,"支付失败,未找到订单");
} }
try { try {
JSONObject wx = trdPayManager.createOrderWx(payOrderInfo); String ali = payTrdConfigService.createOrderAli(payOrderInfo);
String code = wx.getString("retCode");
if(!"SUCCESS".equals(code)){
return R.fail(600,"支付失败!微信支付通道失败!");
}
String payUrl = wx.getJSONObject("payParams").getString("payUrl");
PayReturnResp payTrdReturnResp = new PayReturnResp(); PayReturnResp payTrdReturnResp = new PayReturnResp();
payTrdReturnResp.setData(payUrl); payTrdReturnResp.setData(ali);
return R.ok(payTrdReturnResp); return R.ok(payTrdReturnResp);
}catch (Exception e){ }catch (Exception e){
log.error("第三方微信支付失败!",e); log.error("第三方微信支付失败!",e);
@@ -251,18 +245,38 @@ public class PayController {
} }
@PostMapping(value = "/trd/notify") @PostMapping(value = "/trd/notify/v1")
@Operation(hidden = true) @Operation(hidden = true)
@Log(title = "第三方支付回调", businessType = BusinessType.OTHER, isSaveDb = false) @Log(title = "第三方支付回调V1", businessType = BusinessType.OTHER, isSaveDb = false)
@SaIgnore @SaIgnore
public String trdNotifyUrl(HttpServletRequest request) { public String trdNotifyUrlV1(HttpServletRequest request) {
try { try {
Map<String, String> params = AliPayApi.toMap(request); Map<String, String> params = AliPayApi.toMap(request);
log.info("第三方支付回调:{}",JSON.toJSONString(params)); log.info("第三方支付回调:{}",JSON.toJSONString(params));
String mchOrderNo = params.get("mchOrderNo"); String mchOrderNo = params.get("mchOrderNo");
String payOrderId = params.get("payOrderId"); String payOrderId = params.get("payOrderId");
String productId = params.get("productId"); String productId = params.get("productId");
payManager.callBack(mchOrderNo,payOrderId,params,productId, PayTypeEnum.TRD); payManager.callBack(mchOrderNo,payOrderId,params,"V1", PayTypeEnum.TRD);
return "success";
} catch (Exception e) {
log.error("第三方支付回调失败!",e);
return "failure";
}
}
@PostMapping(value = "/trd/notify/v2")
@Operation(hidden = true)
@Log(title = "第三方支付回调V2", businessType = BusinessType.OTHER, isSaveDb = false)
@SaIgnore
public String trdNotifyUrlV2(HttpServletRequest request) {
try {
Map<String, String> params = AliPayApi.toMap(request);
log.info("第三方支付回调:{}",JSON.toJSONString(params));
String mchOrderNo = params.get("mchOrderNo");
String payOrderId = params.get("payOrderId");
String productId = params.get("productId");
payManager.callBack(mchOrderNo,payOrderId,params,"V2", PayTypeEnum.TRD);
return "success"; return "success";
} catch (Exception e) { } catch (Exception e) {
log.error("第三方支付回调失败!",e); log.error("第三方支付回调失败!",e);

View File

@@ -109,9 +109,3 @@ springdoc:
enabled: false enabled: false
knife4j: knife4j:
enable: false enable: false
trd:
pay:
mch-id: 10418
wx-product-id: 8000
ali-product-id: 8000
notify-url-domain: "http://1.12.220.225:9889"

View File

@@ -1,17 +1,43 @@
package com.ruoyi.test.business; package com.ruoyi.test.business;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayApiException;
import com.ruoyi.cai.pay.PayManager; import com.ruoyi.cai.pay.PayManager;
import com.ruoyi.cai.pay.PayOrderInfoDTO;
import com.ruoyi.cai.service.PayTrdConfigService;
import jdk.nashorn.internal.runtime.regexp.JoniRegExp;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import java.math.BigDecimal;
@SpringBootTest @SpringBootTest
@Slf4j @Slf4j
public class PayTest { public class PayTest {
@Autowired @Autowired
private PayManager payManager; private PayManager payManager;
@Autowired
private PayTrdConfigService payTrdConfigService;
@Test
public void createOrder(){
PayOrderInfoDTO dto = new PayOrderInfoDTO();
dto.setBody("body");
dto.setSubject("subject");
dto.setPrice(new BigDecimal("10"));
dto.setOrderNo("ORSKALKLASJDKLAS");
String orderAli = payTrdConfigService.createOrderAli(dto);
log.info(orderAli);
}
@Test
public void queryOrder(){
JSONObject jsonObject = payTrdConfigService.queryOrder("ORSKALKLASJDKLAS", "V1");
log.info(JSON.toJSONString(jsonObject));
}
@Test @Test
public void test() throws AlipayApiException { public void test() throws AlipayApiException {

View File

@@ -0,0 +1,95 @@
package com.ruoyi.cai.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.cai.domain.PayTrdConfig;
import com.ruoyi.cai.service.PayTrdConfigService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.enums.BusinessType;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Arrays;
/**
* 四方支付配置
*
* @author ruoyi
* @date 2024-11-25
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/cai/payTrdConfig")
public class PayTrdConfigController extends BaseController {
private final PayTrdConfigService payTrdConfigService;
/**
* 查询四方支付配置列表
*/
@SaCheckPermission("cai:payTrdConfig:list")
@GetMapping("/list")
public TableDataInfo<PayTrdConfig> list(PayTrdConfig bo, PageQuery pageQuery) {
Page<PayTrdConfig> page = payTrdConfigService.page(pageQuery.build(), Wrappers.lambdaQuery(bo));
return TableDataInfo.build(page);
}
/**
* 获取四方支付配置详细信息
*
* @param id 主键
*/
@SaCheckPermission("cai:payTrdConfig:query")
@GetMapping("/{id}")
public R<PayTrdConfig> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(payTrdConfigService.getById(id));
}
/**
* 新增四方支付配置
*/
@SaCheckPermission("cai:payTrdConfig:add")
@Log(title = "四方支付配置", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody PayTrdConfig bo) {
return toAjax(payTrdConfigService.save(bo));
}
/**
* 修改四方支付配置
*/
@SaCheckPermission("cai:payTrdConfig:edit")
@Log(title = "四方支付配置", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody PayTrdConfig bo) {
return toAjax(payTrdConfigService.updateById(bo));
}
/**
* 删除四方支付配置
*
* @param ids 主键串
*/
@SaCheckPermission("cai:payTrdConfig:remove")
@Log(title = "四方支付配置", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(payTrdConfigService.removeBatchByIds(Arrays.asList(ids)));
}
}

View File

@@ -0,0 +1,62 @@
package com.ruoyi.cai.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 四方支付配置对象 cai_pay_trd_config
*
* @author ruoyi
* @date 2024-11-25
*/
@Data
@TableName("cai_pay_trd_config")
public class PayTrdConfig implements Serializable {
private static final long serialVersionUID=1L;
/**
*
*/
@TableId(value = "id")
private Long id;
/**
* 第三方支付类型
*/
private String type;
/**
* 第三方支付名称
*/
private String name;
/**
* 请求域名
*/
private String gatewayUrl;
/**
* 回调域名
*/
private String notifyUrl;
/**
* 商户ID
*/
private String mchId;
/**
* 秘钥
*/
private String sign;
private String aliProductId;
private Integer enableStatus;
/**
* 是否删除
*/
private Integer deleteFlag;
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,14 @@
package com.ruoyi.cai.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.cai.domain.PayTrdConfig;
/**
* 四方支付配置Mapper接口
*
* @author ruoyi
* @date 2024-11-25
*/
public interface PayTrdConfigMapper extends BaseMapper<PayTrdConfig> {
}

View File

@@ -182,6 +182,8 @@ public class PayManager {
dto.setSubject(vipOrder.getVipName()); dto.setSubject(vipOrder.getVipName());
dto.setPrice(vipOrder.getPrice()); dto.setPrice(vipOrder.getPrice());
dto.setOrderNo(vipOrder.getOrderNo()); dto.setOrderNo(vipOrder.getOrderNo());
dto.setAppid(vipOrder.getAppid());
dto.setPlatformType(vipOrder.getPlatformType());
break; break;
case RECHARGE_ORDER_SUB: case RECHARGE_ORDER_SUB:
RechargeOrder rechargeOrder = rechargeOrderService.getByOrderNo(orderNo); RechargeOrder rechargeOrder = rechargeOrderService.getByOrderNo(orderNo);
@@ -196,6 +198,8 @@ public class PayManager {
dto.setSubject(rechargeOrder.getRechargeName()); dto.setSubject(rechargeOrder.getRechargeName());
dto.setPrice(rechargeOrder.getPrice()); dto.setPrice(rechargeOrder.getPrice());
dto.setOrderNo(rechargeOrder.getOrderNo()); dto.setOrderNo(rechargeOrder.getOrderNo());
dto.setAppid(rechargeOrder.getAppid());
dto.setPlatformType(rechargeOrder.getPlatformType());
break; break;
default: default:
break; break;

View File

@@ -11,6 +11,8 @@ public class PayOrderInfoDTO {
private String subject; private String subject;
private BigDecimal price; private BigDecimal price;
private String orderNo; private String orderNo;
private String appid;
private String platformType;
public String getPriceFenStr(){ public String getPriceFenStr(){
return NumberUtil.mul(price,100).longValue()+""; return NumberUtil.mul(price,100).longValue()+"";

View File

@@ -1,5 +1,8 @@
package com.ruoyi.cai.pay; package com.ruoyi.cai.pay;
import lombok.Getter;
@Getter
public enum PayTypeEnum { public enum PayTypeEnum {
ALI(1), ALI(1),
WX(2), WX(2),
@@ -11,7 +14,4 @@ public enum PayTypeEnum {
this.code = code; this.code = code;
} }
public Integer getCode() {
return code;
}
} }

View File

@@ -0,0 +1,20 @@
package com.ruoyi.cai.service;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.cai.domain.PayTrdConfig;
import com.ruoyi.cai.pay.PayOrderInfoDTO;
/**
* 四方支付配置Service接口
*
* @author ruoyi
* @date 2024-11-25
*/
public interface PayTrdConfigService extends IService<PayTrdConfig> {
String createOrderAli(PayOrderInfoDTO dto);
JSONObject queryOrder(String orderNo, String trdPayType);
JSONObject resetOrder(String orderNo, String trdPayType);
}

View File

@@ -0,0 +1,155 @@
package com.ruoyi.cai.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.cai.domain.PayTrdConfig;
import com.ruoyi.cai.mapper.PayTrdConfigMapper;
import com.ruoyi.cai.pay.PayManager;
import com.ruoyi.cai.pay.PayOrderInfoDTO;
import com.ruoyi.cai.pay.PayTypeEnum;
import com.ruoyi.cai.service.PayTrdConfigService;
import com.ruoyi.cai.trdpay.TrdPayManager;
import com.ruoyi.cai.trdpay.TrdPayTypeEnum;
import com.ruoyi.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
/**
* 四方支付配置Service业务层处理
*
* @author ruoyi
* @date 2024-11-25
*/
@Service
@Slf4j
public class PayTrdConfigServiceImpl extends ServiceImpl<PayTrdConfigMapper, PayTrdConfig> implements PayTrdConfigService {
@Autowired
private TrdPayManager trdPayManager;
@Autowired
private PayManager payManager;
@Override
public String createOrderAli(PayOrderInfoDTO dto){
PayTrdConfig payTrdConfig = getEnableStatus();
if(payTrdConfig == null){
throw new ServiceException("未开启支付,请联系客服");
}
TrdPayTypeEnum typeEnum = TrdPayTypeEnum.getByCode(payTrdConfig.getType());
if(typeEnum == null){
throw new ServiceException("未开启支付,请联系客服");
}
JSONObject jsonObject = trdPayManager.createOrderAli(dto, payTrdConfig, typeEnum);
if(jsonObject == null){
log.error("第三方支付失败 返回数据为空");
throw new ServiceException("调用支付失败");
}
if(typeEnum == TrdPayTypeEnum.V1){ // V1
if(!"SUCCESS".equals(jsonObject.getString("retCode"))){
log.info("第三方支付失败 V1统一支付失败失败 dto={}, payTrdConfig={}, typeEnum={}", JSON.toJSONString(dto), JSON.toJSONString(payTrdConfig),JSON.toJSONString(typeEnum));
throw new ServiceException("调用支付失败");
}
return jsonObject.getJSONObject("payParams").getString("payUrl");
}else if(typeEnum == TrdPayTypeEnum.V2){
if(!"0".equals(jsonObject.getString("retCode"))){
log.info("第三方支付失败 V2统一支付失败失败 dto={}, payTrdConfig={}, typeEnum={}", JSON.toJSONString(dto), JSON.toJSONString(payTrdConfig),JSON.toJSONString(typeEnum));
throw new ServiceException("调用支付失败");
}
return JSON.toJSONString(jsonObject);
}
return null;
}
private PayTrdConfig getEnableStatus(){
return this.getOne(Wrappers.lambdaQuery(PayTrdConfig.class).eq(PayTrdConfig::getEnableStatus, 1)
.eq(PayTrdConfig::getDeleteFlag, 0).last("limit 1"));
}
private PayTrdConfig getConfigByPay(String type){
PayTrdConfig one = this.getOne(Wrappers.lambdaQuery(PayTrdConfig.class).eq(PayTrdConfig::getEnableStatus, 1)
.eq(PayTrdConfig::getType, type).eq(PayTrdConfig::getDeleteFlag, 0).last("limit 1"));
if(one != null){
return one;
}
one = this.getOne(Wrappers.lambdaQuery(PayTrdConfig.class)
.eq(PayTrdConfig::getType, type).eq(PayTrdConfig::getDeleteFlag, 0).last("limit 1"));
if(one != null){
return one;
}
one = this.getOne(Wrappers.lambdaQuery(PayTrdConfig.class)
.eq(PayTrdConfig::getType, type).last("limit 1"));
return one;
}
@Override
public JSONObject queryOrder(String orderNo, String trdPayType){
TrdPayTypeEnum typeEnum = TrdPayTypeEnum.getByCode(trdPayType);
PayTrdConfig payTrdConfig = getConfigByPay(trdPayType);
if(typeEnum == null || payTrdConfig == null){
throw new ServiceException("配置数据为空");
}
return trdPayManager.queryOrder(orderNo,payTrdConfig,typeEnum);
}
@Override
public JSONObject resetOrder(String orderNo, String trdPayType){
// PayOrderInfoDTO orderInfo = payManager.getOrderInfo(orderNo);
// if(orderInfo == null){
// throw new ServiceException("订单不存在");
// }
// if(!PayTypeEnum.TRD.getCode().toString().equals(orderInfo.getPlatformType())){
// throw new ServiceException("订单不属于第三方支付");
// }
// String appid = orderInfo.getAppid();
TrdPayTypeEnum typeEnum = TrdPayTypeEnum.getByCode(trdPayType);
PayTrdConfig payTrdConfig = getConfigByPay(trdPayType);
if(typeEnum == null || payTrdConfig == null){
throw new ServiceException("配置数据为空");
}
JSONObject jsonObject = trdPayManager.queryOrder(orderNo,payTrdConfig,typeEnum);
if(typeEnum == TrdPayTypeEnum.V1){ // V1
if(!"SUCCESS".equals(jsonObject.getString("retCode"))){
log.info("第三方支付失败 V1统一支付失败失败 orderNo={}, payTrdConfig={}, typeEnum={}", orderNo, JSON.toJSONString(payTrdConfig),JSON.toJSONString(typeEnum));
throw new ServiceException("调用支付失败");
}
Integer status = jsonObject.getInteger("status");
if(status != null && status.equals(2)){
String mchOrderNo = jsonObject.getString("mchOrderNo");
String payOrderId = jsonObject.getString("payOrderId");
String productId = jsonObject.getString("productId");
Map<String,String> objectJson = new HashMap<>();
for (String key : jsonObject.keySet()) {
objectJson.put(key, jsonObject.getString(key));
}
payManager.callBack(mchOrderNo,payOrderId,objectJson,productId, PayTypeEnum.TRD);
}
return jsonObject;
}else if(typeEnum == TrdPayTypeEnum.V2){
if(!"0".equals(jsonObject.getString("retCode"))){
log.info("第三方支付失败 V2统一支付失败失败 orderNo={}, payTrdConfig={}, typeEnum={}", orderNo, JSON.toJSONString(payTrdConfig),JSON.toJSONString(typeEnum));
throw new ServiceException("调用支付失败");
}
Integer status = jsonObject.getInteger("status");
if(status != null && (status.equals(2) || status.equals(3))){
String mchOrderNo = jsonObject.getString("mchOrderNo");
String payOrderId = jsonObject.getString("payOrderId");
String productId = jsonObject.getString("productId");
Map<String,String> objectJson = new HashMap<>();
for (String key : jsonObject.keySet()) {
objectJson.put(key, jsonObject.getString(key));
}
payManager.callBack(mchOrderNo,payOrderId,objectJson,productId, PayTypeEnum.TRD);
}
return jsonObject;
}
return jsonObject;
}
}

View File

@@ -5,13 +5,13 @@ import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.cai.domain.Account; import com.ruoyi.cai.domain.Account;
import com.ruoyi.cai.domain.PayTrdConfig;
import com.ruoyi.cai.enums.SystemConfigEnum; import com.ruoyi.cai.enums.SystemConfigEnum;
import com.ruoyi.cai.manager.SystemConfigManager; import com.ruoyi.cai.manager.SystemConfigManager;
import com.ruoyi.cai.pay.PayManager;
import com.ruoyi.cai.pay.PayOrderInfoDTO; import com.ruoyi.cai.pay.PayOrderInfoDTO;
import com.ruoyi.cai.pay.PayTypeEnum;
import com.ruoyi.cai.service.AccountService; import com.ruoyi.cai.service.AccountService;
import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.ServletUtils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -24,6 +24,8 @@ import org.springframework.web.client.RestTemplate;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -34,14 +36,6 @@ import java.util.stream.Collectors;
@Slf4j @Slf4j
public class TrdPayManager { public class TrdPayManager {
private final String CREATE_ORDER_URL = "http://pay.jpay.one/api/pay/create_order";
private final String QUERY_ORDER_URL = "http://pay.jpay.one/api/pay/query_order";
private static final String NOTIFY_ALI_URL = "/api/pay/trd/notify";
@Autowired
private TrdPayProperties trdPayProperties;
public static RestTemplate restTemplate; public static RestTemplate restTemplate;
static { static {
@@ -59,12 +53,37 @@ public class TrdPayManager {
} }
} }
public JSONObject createOrderWx(PayOrderInfoDTO payOrderInfoDTO){ public JSONObject createOrderAli(PayOrderInfoDTO payOrderInfoDTO, PayTrdConfig payTrdConfig,TrdPayTypeEnum typeEnum){
return createOrder(payOrderInfoDTO,trdPayProperties.getWxProductId()); Map<String, String> params = new HashMap<>();
params.put("mchId", payTrdConfig.getMchId());
params.put("productId", payTrdConfig.getAliProductId());
params.put("mchOrderNo", payOrderInfoDTO.getOrderNo());
params.put("amount", payOrderInfoDTO.getPriceFenStr());
if(typeEnum == TrdPayTypeEnum.V2){
params.put("reqTime", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
params.put("version","1.0");
params.put("clientIp", ServletUtils.getClientIP());
params.put("subject",payOrderInfoDTO.getSubject());
params.put("body",payOrderInfoDTO.getBody());
params.put("currency","cny");
} }
String notifyUrl = payTrdConfig.getNotifyUrl() + typeEnum.getNotifyPath();
public JSONObject createOrderAli(PayOrderInfoDTO payOrderInfoDTO){ params.put("notifyUrl", notifyUrl);
return createOrder(payOrderInfoDTO,trdPayProperties.getAliProductId()); String para = createParams(params,payTrdConfig.getSign());
String gatewayUrl = typeEnum.getGatewayUrl();
if(StringUtils.isNotBlank(payTrdConfig.getGatewayUrl())){
gatewayUrl = payTrdConfig.getGatewayUrl();
}
String createOrderUrl = gatewayUrl + typeEnum.getCreateOrderUrl();
String url = createOrderUrl + "?" + para;
String body = restTemplate.getForEntity(url, String.class).getBody();
JSONObject jsonObject = JSON.parseObject(body);
if(jsonObject == null){
log.error("第三方支付失败 返回数据为空");
throw new ServiceException("调用支付失败");
}
log.info("第三方支付成功 URL={}, body={}",url, body);
return jsonObject;
} }
@Autowired @Autowired
@@ -87,76 +106,35 @@ public class TrdPayManager {
return true; return true;
} }
@Autowired public JSONObject queryOrder(String orderNo, PayTrdConfig payTrdConfig,TrdPayTypeEnum typeEnum){
private PayManager payManager;
public JSONObject resetOrder(String orderNo){
JSONObject jsonObject = queryOrder(orderNo);
Integer status = jsonObject.getInteger("status");
if(status != null && status.equals(2)){
String mchOrderNo = jsonObject.getString("mchOrderNo");
String payOrderId = jsonObject.getString("payOrderId");
String productId = jsonObject.getString("productId");
Map<String,String> objectJson = new HashMap<>();
for (String key : jsonObject.keySet()) {
objectJson.put(key, jsonObject.getString(key));
}
payManager.callBack(mchOrderNo,payOrderId,objectJson,productId, PayTypeEnum.TRD);
}
return jsonObject;
}
public JSONObject queryOrder(String orderNo){
Map<String, String> params = new HashMap<>(); Map<String, String> params = new HashMap<>();
params.put("mchId", trdPayProperties.getMchId()); params.put("mchId", payTrdConfig.getMchId());
params.put("mchOrderNo", orderNo); params.put("mchOrderNo", orderNo);
String para = createParams(params); String para = createParams(params,payTrdConfig.getSign());
String url = QUERY_ORDER_URL + "?" + para; String gatewayUrl = typeEnum.getGatewayUrl();
if(StringUtils.isNotBlank(payTrdConfig.getGatewayUrl())){
gatewayUrl = payTrdConfig.getGatewayUrl();
}
String queryOrderUrl = gatewayUrl + typeEnum.getQueryOrderUrl();
String url = queryOrderUrl + "?" + para;
String body = restTemplate.getForEntity(url, String.class).getBody(); String body = restTemplate.getForEntity(url, String.class).getBody();
JSONObject jsonObject = JSON.parseObject(body); JSONObject jsonObject = JSON.parseObject(body);
if(jsonObject == null){ if(jsonObject == null){
log.error("第三方支付查询失败 返回数据为空"); log.error("第三方支付查询失败 返回数据为空");
throw new ServiceException("调用支付失败"); throw new ServiceException("调用支付失败");
} }
if(!"SUCCESS".equals(jsonObject.getString("retCode"))){
log.info("第三方支付查询失败 第三方支付查询失败 url={}, body={}",url, body);
throw new ServiceException("调用支付失败");
}
log.info("第三方支付成功 URL={}, body={}",url, body); log.info("第三方支付成功 URL={}, body={}",url, body);
return jsonObject; return jsonObject;
} }
public JSONObject createOrder(PayOrderInfoDTO payOrderInfoDTO,String productId){ private String createParams(Map<String, String> params,String key){
Map<String, String> params = new HashMap<>();
params.put("mchId", trdPayProperties.getMchId());
params.put("productId", productId);
params.put("mchOrderNo", payOrderInfoDTO.getOrderNo());
params.put("amount", payOrderInfoDTO.getPriceFenStr());
String notifyUrl = trdPayProperties.getNotifyUrlDomain() + NOTIFY_ALI_URL;
params.put("notifyUrl", notifyUrl);
String para = createParams(params);
String url = CREATE_ORDER_URL + "?" + para;
String body = restTemplate.getForEntity(url, String.class).getBody();
JSONObject jsonObject = JSON.parseObject(body);
if(jsonObject == null){
log.error("第三方支付失败 返回数据为空");
throw new ServiceException("调用支付失败");
}
if(!"SUCCESS".equals(jsonObject.getString("retCode"))){
log.info("第三方支付失败 统一支付失败失败 url={}, body={}",url, body);
throw new ServiceException("调用支付失败");
}
log.info("第三方支付成功 URL={}, body={}",url, body);
return jsonObject;
}
private String createParams(Map<String, String> params){
List<String> url = new ArrayList<>(); List<String> url = new ArrayList<>();
for (Map.Entry<String, String> entry : params.entrySet()) { for (Map.Entry<String, String> entry : params.entrySet()) {
url.add(entry.getKey()+"="+entry.getValue()); url.add(entry.getKey()+"="+entry.getValue());
} }
url = url.stream().sorted().collect(Collectors.toList()); url = url.stream().sorted().collect(Collectors.toList());
String stringSignTemp = StringUtils.join(url, "&") + "&key=" + trdPayProperties.getSignKey(); String stringSignTemp = StringUtils.join(url, "&") + "&key=" + key;
String sign = DigestUtil.md5Hex(stringSignTemp).toUpperCase(); String sign = DigestUtil.md5Hex(stringSignTemp).toUpperCase();
url.add("sign="+sign); url.add("sign="+sign);
return StringUtils.join(url, "&"); return StringUtils.join(url, "&");
@@ -164,16 +142,6 @@ public class TrdPayManager {
public static void main(String[] args) { public static void main(String[] args) {
TrdPayProperties payProperties = new TrdPayProperties();
payProperties.setMchId("10418");
payProperties.setNotifyUrlDomain("https://api.ssss.com");
PayOrderInfoDTO payOrderInfo = new PayOrderInfoDTO();
payOrderInfo.setPrice(new BigDecimal("10"));
payOrderInfo.setOrderNo("DSKsdasklddshjkasdka");
TrdPayManager trdPayManager = new TrdPayManager();
// trdPayManager.(payProperties);
trdPayManager.createOrder(payOrderInfo,"8000");
} }

View File

@@ -0,0 +1,33 @@
package com.ruoyi.cai.trdpay;
import com.ruoyi.cai.pay.PayTypeEnum;
import lombok.Getter;
@Getter
public enum TrdPayTypeEnum {
V1("http://pay.jpay.one/api","/pay/create_order","/pay/query_order","/api/pay/trd/notify/v1"),
V2("http://121.40.24.67:56700/api","/pay/create_order","/pay/query_order","/api/pay/trd/notify/v2"),
;
private final String gatewayUrl;
private final String createOrderUrl;
private final String queryOrderUrl;
private final String notifyPath;
TrdPayTypeEnum(String gatewayUrl, String createOrderUrl, String queryOrderUrl, String notifyPath) {
this.gatewayUrl = gatewayUrl;
this.createOrderUrl = createOrderUrl;
this.queryOrderUrl = queryOrderUrl;
this.notifyPath = notifyPath;
}
public static TrdPayTypeEnum getByCode(String type) {
TrdPayTypeEnum[] values = TrdPayTypeEnum.values();
for (TrdPayTypeEnum value : values) {
if(value.name().equals(type)){
return value;
}
}
return null;
}
}

View File

@@ -0,0 +1,20 @@
<?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.cai.mapper.PayTrdConfigMapper">
<resultMap type="com.ruoyi.cai.domain.PayTrdConfig" id="PayTrdConfigResult">
<result property="id" column="id"/>
<result property="type" column="type"/>
<result property="name" column="name"/>
<result property="gatewayUrl" column="gateway_url"/>
<result property="notifyUrl" column="notify_url"/>
<result property="mchId" column="mch_id"/>
<result property="sign" column="sign"/>
<result property="deleteFlag" column="delete_flag"/>
<result property="createTime" column="create_time"/>
</resultMap>
</mapper>