1. 迁移创建支付交易单接口

pull/4/MERGE
YunaiV 2020-11-28 22:52:52 +08:00
parent fdc83d4550
commit 0a14b530b6
33 changed files with 284 additions and 467 deletions

View File

@ -99,22 +99,7 @@ public class OrderServiceImpl implements OrderService {
return CommonResult.success(orderInfoBO); return CommonResult.success(orderInfoBO);
} }
private PayTransactionBO createPayTransaction(OrderDO order, List<OrderItemDO> orderItems, String ip) {
// TODO sin 支付订单 orderSubject 暂时取第一个子订单商品信息
String orderSubject = orderItems.get(0).getSkuName();
Date expireTime = DateUtil.addDate(Calendar.MINUTE, PAY_EXPIRE_TIME);
return payTransactionService.createTransaction(
new PayTransactionCreateDTO()
.setCreateIp(ip)
.setAppId(PayAppId.APP_ID_SHOP_ORDER)
.setOrderId(order.getId().toString())
.setExpireTime(expireTime)
.setPrice(order.getPresentPrice())
.setOrderSubject(orderSubject)
.setOrderMemo("测试备注") // TODO 芋艿,后面补充
.setOrderDescription("测试描述") // TODO 芋艿,后面补充
);
}
@Override // TODO 芋艿,需要确认下这个方法的用途。因为涉及修改价格和数量。 @Override // TODO 芋艿,需要确认下这个方法的用途。因为涉及修改价格和数量。
public CommonResult updateOrderItem(OrderItemUpdateDTO orderUpdateDTO) { public CommonResult updateOrderItem(OrderItemUpdateDTO orderUpdateDTO) {

View File

@ -1,24 +0,0 @@
<?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>product</artifactId>
<groupId>cn.iocoder.mall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>order-biz-api</artifactId>
<dependencies>
<!-- Mall 相关 -->
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>common-framework</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

View File

@ -1,16 +0,0 @@
package cn.iocoder.mall.order.biz.enums.order;
/**
* AppId
*
* @author Sin
* @time 2019-04-08 19:54
*/
public class PayAppId {
/**
*
*/
public static final String APP_ID_SHOP_ORDER = "POd4RC6a";
}

View File

@ -1,67 +0,0 @@
package cn.iocoder.mall.order.api.constant;
/**
*
*
* [1-008-000-000 ~ 1-008-000-000]
*
* @author Sin
* @time 2019-03-23 11:23
*/
public enum OrderErrorCodeEnum {
// order
ORDER_NOT_EXISTENT(1008000000, "获取订单不存在!"),
ORDER_GET_SKU_FAIL(1008000001, "获取商品失败!"),
ORDER_GET_SKU_NOT_EXISTENT(1008000002, "获取的商品不存在!"),
ORDER_PAY_AMOUNT_NOT_NEGATIVE(1008000003, "支付金额不能为负数!"),
ORDER_STATUS_NOT_CANCEL(1008000004, "订单状态不能取消!"),
ORDER_DELIVERY_INCORRECT_DATA(1008000005, "订单发货数据不正确!"),
ORDER_INSUFFICIENT_INVENTORY(1008000006, "库存不足!"),
ORDER_GOODS_AMOUNT_INCORRECT(1008000007, "商品金额非法!"),
ORDER_GET_GOODS_INFO_INCORRECT(1008000008, "获取额商品信息不正确!"),
ORDER_GET_USER_ADDRESS_FAIL(1008000009, "获取用户地址失败!"),
ORDER_GET_PAY_FAIL(1008000010, "调用pay失败!"),
ORDER_NOT_USER_ORDER(1008000011, "不是该用户的订单!"),
ORDER_UNABLE_CONFIRM_ORDER(1008000012, "状态不对不能确认订单!"),
ORDER_CREATE_CART_IS_EMPTY(1008000013, "购物车无选中的商品,无法创建订单"),
ORDER_STATUS_NOT_WAITING_PAYMENT(1008000014, "订单不处于等待支付状态"),
ORDER_PAY_AMOUNT_ERROR(1008000015, "订单金额不正确"),
// order item
ORDER_ITEM_ONLY_ONE(1008000200, "订单Item只有一个!"),
// 订单退货
ORDER_RETURN_NO_RETURN_APPLY(1008000400, "未退货申请"),
ORDER_RETURN_NOT_EXISTENT(1008000401, "退货订单不存在"),
ORDER_RETURN_REFUND_FAILED(1008000402, "退款失败"),
// ========== 购物车 ==========
CARD_ITEM_NOT_FOUND(1008003000, "购物车项不存在"),
CARD_ITEM_SKU_NOT_FOUND(1008003001, "商品不存在"),
CARD_ITEM_SKU_QUANTITY_NOT_ENOUGH(1008003002, "商品库存不足"),
// 工具类服务 1008004000
DICT_SERVER_INVOKING_FAIL(1008004000, "字典服务调用失败!"),
ORDER_LOGISTICS_INVOKING_FAIL(1008004001, "订单物流调用失败!"),
;
private final int code;
private final String message;
OrderErrorCodeEnum(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}

View File

@ -1,16 +0,0 @@
package cn.iocoder.mall.order.api.constant;
/**
* AppId
*
* @author Sin
* @time 2019-04-08 19:54
*/
public class PayAppId {
/**
*
*/
public static final String APP_ID_SHOP_ORDER = "POd4RC6a";
}

View File

@ -0,0 +1,31 @@
package cn.iocoder.mall.payservice.enums;
import cn.iocoder.common.framework.exception.ErrorCode;
/**
*
*
* 使 1-004-000-000
*/
public interface PayErrorCodeConstants {
// ========== APP 模块 ==========
ErrorCode PAY_APP_NOT_FOUND = new ErrorCode(1004000000, "App 不存在");
ErrorCode PAY_APP_IS_DISABLE = new ErrorCode(1004000001, "App 已经被禁用");
// ========== TRANSACTION PAY 模块 ==========
ErrorCode PAY_TRANSACTION_NOT_FOUND = new ErrorCode(100401000, "支付交易单不存在");
ErrorCode PAY_TRANSACTION_STATUS_IS_NOT_WAITING = new ErrorCode(100401001, "支付交易单不处于待支付");
ErrorCode PAY_TRANSACTION_STATUS_IS_NOT_SUCCESS = new ErrorCode(100401002, "支付交易单不处于已支付");
ErrorCode PAY_TRANSACTION_ERROR_USER = new ErrorCode(100401003, "支付交易单用户不正确");
ErrorCode PAY_TRANSACTION_EXTENSION_NOT_FOUND = new ErrorCode(100401050, "支付交易拓展单不存在");
ErrorCode PAY_TRANSACTION_EXTENSION_STATUS_IS_NOT_WAITING = new ErrorCode(100401051, "支付交易拓展单不处于待支付");
ErrorCode PAY_TRANSACTION_EXTENSION_STATUS_IS_NOT_SUCCESS = new ErrorCode(100401052, "支付交易单不处于已支付");
// ========== TRANSACTION REFUND 模块 ==========
ErrorCode PAY_REFUND_PRICE_EXCEED = new ErrorCode(100402000, "退款金额超过支付交易单可退金额");
ErrorCode PAY_REFUND_NOT_FOUND = new ErrorCode(100402001, "退款单不存在");
ErrorCode PAY_REFUND_STATUS_NOT_WAITING = new ErrorCode(100402002, "退款单不处于待处理");
}

View File

@ -1,4 +1,4 @@
package cn.iocoder.mall.pay.api.constant; package cn.iocoder.mall.payservice.enums.transaction;
/** /**
* *

View File

@ -1 +0,0 @@
package cn.iocoder.mall.payservice.rpc;

View File

@ -1,10 +1,19 @@
package cn.iocoder.mall.payservice.rpc.transaction; package cn.iocoder.mall.payservice.rpc.transaction;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.payservice.rpc.transaction.dto.PayTransactionCreateReqDTO;
/** /**
* RPC * RPC
*/ */
public interface PayTransactionRpc { public interface PayTransactionRpc {
/**
*
*
* @param createReqDTO
* @return
*/
CommonResult<Integer> createPayTransaction(PayTransactionCreateReqDTO createReqDTO);
} }

View File

@ -21,7 +21,7 @@
<dependency> <dependency>
<!-- 支付服务 --> <!-- 支付服务 -->
<groupId>cn.iocoder.mall</groupId> <groupId>cn.iocoder.mall</groupId>
<artifactId>product-service-api</artifactId> <artifactId>pay-service-api</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</dependency> </dependency>

View File

@ -0,0 +1,16 @@
package cn.iocoder.mall.payservice.convert.app;
import cn.iocoder.mall.payservice.dal.mysql.dataobject.app.PayAppDO;
import cn.iocoder.mall.payservice.rpc.app.dto.PayAppRespDTO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface PayAppConvert {
PayAppConvert INSTANCE = Mappers.getMapper(PayAppConvert.class);
PayAppRespDTO convert(PayAppDO bean);
}

View File

@ -0,0 +1,15 @@
package cn.iocoder.mall.payservice.convert.transaction;
import cn.iocoder.mall.payservice.dal.mysql.dataobject.transaction.PayTransactionDO;
import cn.iocoder.mall.payservice.rpc.transaction.dto.PayTransactionCreateReqDTO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface PayTransactionConvert {
PayTransactionConvert INSTANCE = Mappers.getMapper(PayTransactionConvert.class);
PayTransactionDO convert(PayTransactionCreateReqDTO bean);
}

View File

@ -1,12 +0,0 @@
package cn.iocoder.mall.payservice.convert.transaction;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface TransactionConvert {
TransactionConvert INSTANCE = Mappers.getMapper(TransactionConvert.class);
}

View File

@ -1,6 +1,7 @@
package cn.iocoder.mall.payservice.dal.mysql.dataobject.app; package cn.iocoder.mall.payservice.dal.mysql.dataobject.app;
import cn.iocoder.mall.mybatis.core.dataobject.DeletableDO; import cn.iocoder.mall.mybatis.core.dataobject.DeletableDO;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
@ -10,6 +11,7 @@ import lombok.experimental.Accessors;
* *
* *
*/ */
@TableName("pay_app")
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Accessors(chain = true) @Accessors(chain = true)

View File

@ -0,0 +1,9 @@
package cn.iocoder.mall.payservice.dal.mysql.mapper.app;
import cn.iocoder.mall.payservice.dal.mysql.dataobject.app.PayAppDO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
@Repository
public interface PayAppMapper extends BaseMapper<PayAppDO> {
}

View File

@ -1,6 +1,7 @@
package cn.iocoder.mall.payservice.dal.mysql.mapper.transaction; package cn.iocoder.mall.payservice.dal.mysql.mapper.transaction;
import cn.iocoder.mall.payservice.dal.mysql.dataobject.transaction.PayTransactionDO; import cn.iocoder.mall.payservice.dal.mysql.dataobject.transaction.PayTransactionDO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
@ -12,4 +13,9 @@ public interface PayTransactionMapper extends BaseMapper<PayTransactionDO> {
// new QueryWrapperX<PayTransactionDO>()); // new QueryWrapperX<PayTransactionDO>());
// } // }
default PayTransactionDO selectByAppIdAndOrderId(String appId, String orderId) {
return selectOne(new QueryWrapper<PayTransactionDO>().eq("app_id", appId)
.eq("order_id", orderId));
}
} }

View File

@ -1,4 +1,22 @@
package cn.iocoder.mall.payservice.rpc.transaction; package cn.iocoder.mall.payservice.rpc.transaction;
public class PayTransactionRpcImpl { import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.payservice.rpc.transaction.dto.PayTransactionCreateReqDTO;
import cn.iocoder.mall.payservice.service.transaction.PayTransactionService;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import static cn.iocoder.common.framework.vo.CommonResult.success;
@DubboService
public class PayTransactionRpcImpl implements PayTransactionRpc {
@Autowired
private PayTransactionService payTransactionService;
@Override
public CommonResult<Integer> createPayTransaction(PayTransactionCreateReqDTO createReqDTO) {
return success(payTransactionService.createPayTransaction(createReqDTO));
}
} }

View File

@ -1,10 +1,20 @@
package cn.iocoder.mall.payservice.service.app; package cn.iocoder.mall.payservice.service.app;
import cn.iocoder.mall.payservice.rpc.app.dto.PayAppRespDTO;
/** /**
* Service * Service
*/ */
public interface PayAppService { public interface PayAppService {
/**
*
*
* {@link cn.iocoder.common.framework.exception.ServiceException}
*
* @param payAppId
* @return
*/
PayAppRespDTO validPayApp(String payAppId);
} }

View File

@ -1,25 +1,38 @@
package cn.iocoder.mall.payservice.service.app.impl; package cn.iocoder.mall.payservice.service.app.impl;
import cn.iocoder.common.framework.enums.CommonStatusEnum;
import cn.iocoder.common.framework.exception.util.ServiceExceptionUtil;
import cn.iocoder.mall.payservice.convert.app.PayAppConvert;
import cn.iocoder.mall.payservice.dal.mysql.dataobject.app.PayAppDO;
import cn.iocoder.mall.payservice.dal.mysql.mapper.app.PayAppMapper;
import cn.iocoder.mall.payservice.rpc.app.dto.PayAppRespDTO;
import cn.iocoder.mall.payservice.service.app.PayAppService; import cn.iocoder.mall.payservice.service.app.PayAppService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import static cn.iocoder.mall.payservice.enums.PayErrorCodeConstants.*;
/** /**
* Service * Service
*/ */
@Service
public class PayAppServiceImpl implements PayAppService { public class PayAppServiceImpl implements PayAppService {
@Autowired
private PayAppMapper payAppMapper;
@Override
// public PayAppDO validPayApp(String appId) { public PayAppRespDTO validPayApp(String payAppId) {
// PayAppDO payAppDO = payAppMapper.selectById(appId); PayAppDO payAppDO = payAppMapper.selectById(payAppId);
// // 校验是否存在 // 校验是否存在
// if (payAppDO == null) { if (payAppDO == null) {
// throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_APP_NOT_FOUND.getCode()); throw ServiceExceptionUtil.exception(PAY_APP_NOT_FOUND);
// } }
// // 校验是否禁用 // 校验是否禁用
// if (CommonStatusEnum.DISABLE.getValue().equals(payAppDO.getStatus())) { if (CommonStatusEnum.DISABLE.getValue().equals(payAppDO.getStatus())) {
// throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_APP_IS_DISABLE.getCode()); throw ServiceExceptionUtil.exception(PAY_APP_IS_DISABLE);
// } }
// return payAppDO; return PayAppConvert.INSTANCE.convert(payAppDO);
// } }
} }

View File

@ -1,10 +1,18 @@
package cn.iocoder.mall.payservice.service.transaction; package cn.iocoder.mall.payservice.service.transaction;
import cn.iocoder.mall.payservice.rpc.transaction.dto.PayTransactionCreateReqDTO;
/** /**
* Service * Service
*/ */
public interface PayTransactionService { public interface PayTransactionService {
/**
*
*
* @param createReqDTO
* @return
*/
Integer createPayTransaction(PayTransactionCreateReqDTO createReqDTO);
} }

View File

@ -1,7 +1,14 @@
package cn.iocoder.mall.payservice.service.transaction.impl; package cn.iocoder.mall.payservice.service.transaction.impl;
import cn.iocoder.mall.payservice.convert.transaction.PayTransactionConvert;
import cn.iocoder.mall.payservice.dal.mysql.dataobject.transaction.PayTransactionDO;
import cn.iocoder.mall.payservice.dal.mysql.mapper.transaction.PayTransactionMapper; import cn.iocoder.mall.payservice.dal.mysql.mapper.transaction.PayTransactionMapper;
import cn.iocoder.mall.payservice.enums.transaction.PayTransactionStatusEnum;
import cn.iocoder.mall.payservice.rpc.app.dto.PayAppRespDTO;
import cn.iocoder.mall.payservice.rpc.transaction.dto.PayTransactionCreateReqDTO;
import cn.iocoder.mall.payservice.service.app.PayAppService;
import cn.iocoder.mall.payservice.service.transaction.PayTransactionService; import cn.iocoder.mall.payservice.service.transaction.PayTransactionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -11,87 +18,36 @@ import org.springframework.validation.annotation.Validated;
*/ */
@Service @Service
@Validated @Validated
@Slf4j
public class PayTransactionServiceImpl implements PayTransactionService { public class PayTransactionServiceImpl implements PayTransactionService {
@Autowired @Autowired
private PayTransactionMapper transactionMapper; private PayTransactionMapper payTransactionMapper;
@Autowired
private PayAppService payAppService;
@Override
public Integer createPayTransaction(PayTransactionCreateReqDTO createReqDTO) {
// 校验 App
PayAppRespDTO payAppRespDTO = payAppService.validPayApp(createReqDTO.getAppId());
// /** // 查询对应的支付交易单是否已经存在。如果是,则直接返回
// * 创建pay_transaction PayTransactionDO payTransaction = payTransactionMapper.selectByAppIdAndOrderId(
// * createReqDTO.getAppId(), createReqDTO.getOrderId());
// * @param createBO 创建pay_transaction BO if (payTransaction != null) {
// * @return pay_transaction log.warn("[createTransaction][appId({}) orderId({}) 已经存在对应的支付交易单({})]", createReqDTO.getAppId(),
// */ createReqDTO.getOrderId(), payTransaction.toString()); // 理论来说,不会出现这个情况
// public TransactionBO createTransaction(@Valid TransactionCreateBO createBO) { return payTransaction.getId();
// // 插入到数据库 }
// PayTransactionDO transactionDO = TransactionConvert.INSTANCE.convert(createBO);
// transactionMapper.insert(transactionDO); // 创建支付交易单
// // 返回 payTransaction = PayTransactionConvert.INSTANCE.convert(createReqDTO)
// return TransactionConvert.INSTANCE.convert(transactionDO); .setStatus(PayTransactionStatusEnum.WAITING.getValue())
// } .setNotifyUrl(payAppRespDTO.getPayNotifyUrl());
// payTransactionMapper.insert(payTransaction);
// /** // 最终返回
// * 更新pay_transaction return payTransaction.getId();
// * }
// * @param updateBO 更新pay_transaction BO
// */
// public void updateTransaction(@Valid TransactionUpdateBO updateBO) {
// // 校验更新的pay_transaction是否存在
// if (transactionMapper.selectById(updateBO.getId()) == null) {
// throw ServiceExceptionUtil.exception(AuthErrorCodeConstants.TRANSACTION_NOT_FOUND);
// }
// // 更新到数据库
// PayTransactionDO updateObject = TransactionConvert.INSTANCE.convert(updateBO);
// transactionMapper.updateById(updateObject);
// }
//
// /**
// * 删除pay_transaction
// *
// * @param transactionId pay_transaction编号
// */
// public void deleteTransaction(Integer transactionId) {
// // 校验删除的pay_transaction是否存在
// if (transactionMapper.selectById(transactionId) == null) {
// throw ServiceExceptionHelper.exception(AuthErrorCodeConstants.TRANSACTION_NOT_FOUND);
// }
// // 标记删除
// transactionMapper.deleteById(transactionId);
// }
//
// /**
// * 获得pay_transaction
// *
// * @param transactionId pay_transaction编号
// * @return pay_transaction
// */
// public TransactionBO getTransaction(Integer transactionId) {
// PayTransactionDO transactionDO = transactionMapper.selectById(transactionId);
// return TransactionConvert.INSTANCE.convert(transactionDO);
// }
//
// /**
// * 获得pay_transaction列表
// *
// * @param transactionIds pay_transaction编号列表
// * @return pay_transaction列表
// */
// public List<TransactionBO> listTransactions(List<Integer> transactionIds) {
// List<PayTransactionDO> transactionDOs = transactionMapper.selectBatchIds(transactionIds);
// return TransactionConvert.INSTANCE.convertList(transactionDOs);
// }
//
// /**
// * 获得pay_transaction分页
// *
// * @param pageBO pay_transaction分页查询
// * @return pay_transaction分页结果
// */
// public PageResult<TransactionBO> pageTransaction(TransactionPageBO pageBO) {
// IPage<PayTransactionDO> transactionDOPage = transactionMapper.selectPage(pageBO);
// return TransactionConvert.INSTANCE.convertPage(transactionDOPage);
// }
} }

View File

@ -1,46 +0,0 @@
package cn.iocoder.mall.pay.api.constant;
/**
*
*
* 使 1-004-000-000
*/
public enum PayErrorCodeEnum {
// ========== APP 模块 ==========
PAY_APP_NOT_FOUND(1004000000, "App 不存在"),
PAY_APP_IS_DISABLE(1004000001, "App 已经被禁用"),
// ========== TRANSACTION PAY 模块 ==========
PAY_TRANSACTION_NOT_FOUND(100401000, "支付交易单不存在"),
PAY_TRANSACTION_STATUS_IS_NOT_WAITING(100401001, "支付交易单不处于待支付"),
PAY_TRANSACTION_STATUS_IS_NOT_SUCCESS(100401002, "支付交易单不处于已支付"),
PAY_TRANSACTION_ERROR_USER(100401003, "支付交易单用户不正确"),
PAY_TRANSACTION_EXTENSION_NOT_FOUND(100401050, "支付交易拓展单不存在"),
PAY_TRANSACTION_EXTENSION_STATUS_IS_NOT_WAITING(100401051, "支付交易拓展单不处于待支付"),
PAY_TRANSACTION_EXTENSION_STATUS_IS_NOT_SUCCESS(100401052, "支付交易单不处于已支付"),
// ========== TRANSACTION REFUND 模块 ==========
PAY_REFUND_PRICE_EXCEED(100402000, "退款金额超过支付交易单可退金额"),
PAY_REFUND_NOT_FOUND(100402001, "退款单不存在"),
PAY_REFUND_STATUS_NOT_WAITING(100402002, "退款单不处于待处理"),
;
private final int code;
private final String message;
PayErrorCodeEnum(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}

View File

@ -1,31 +0,0 @@
package cn.iocoder.mall.pay.biz.convert;
import cn.iocoder.mall.pay.api.bo.transaction.PayTransactionBO;
import cn.iocoder.mall.pay.api.dto.transaction.PayTransactionCreateDTO;
import cn.iocoder.mall.pay.api.dto.transaction.PayTransactionSubmitDTO;
import cn.iocoder.mall.pay.biz.dataobject.PayTransactionDO;
import cn.iocoder.mall.pay.biz.dataobject.PayTransactionExtensionDO;
import org.mapstruct.Mapper;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
import java.util.List;
@Mapper
public interface PayTransactionConvert {
PayTransactionConvert INSTANCE = Mappers.getMapper(PayTransactionConvert.class);
@Mappings({})
PayTransactionDO convert(PayTransactionCreateDTO payTransactionCreateDTO);
@Mappings({})
PayTransactionBO convert(PayTransactionDO payTransactionDO);
@Mappings({})
List<PayTransactionBO> convertList(List<PayTransactionDO> list);
@Mappings({})
PayTransactionExtensionDO convert(PayTransactionSubmitDTO payTransactionSubmitDTO);
}

View File

@ -11,20 +11,12 @@ import java.util.List;
@Repository @Repository
public interface PayTransactionMapper { public interface PayTransactionMapper {
void insert(PayTransactionDO entity);
int update(@Param("entity") PayTransactionDO entity, int update(@Param("entity") PayTransactionDO entity,
@Param("whereStatus") Integer whereStatus); @Param("whereStatus") Integer whereStatus);
int updateForRefundTotal(@Param("id") Integer id, int updateForRefundTotal(@Param("id") Integer id,
@Param("refundTotalIncr") Integer refundTotalIncr); @Param("refundTotalIncr") Integer refundTotalIncr);
PayTransactionDO selectByAppIdAndOrderId(@Param("appId") String appId,
@Param("orderId") String orderId);
PayTransactionDO selectById(@Param("id") Integer id);
List<PayTransactionDO> selectListByIds(@Param("ids") Collection<Integer> ids);
List<PayTransactionDO> selectListByPage(@Param("createBeginTime") Date createBeginTime, List<PayTransactionDO> selectListByPage(@Param("createBeginTime") Date createBeginTime,
@Param("createEndTime") Date createEndTime, @Param("createEndTime") Date createEndTime,

View File

@ -79,29 +79,6 @@ public class PayTransactionServiceImpl implements PayTransactionService {
return PayTransactionConvert.INSTANCE.convert(payTransaction); return PayTransactionConvert.INSTANCE.convert(payTransaction);
} }
@Override
@SuppressWarnings("Duplicates")
public PayTransactionBO createTransaction(PayTransactionCreateDTO payTransactionCreateDTO) {
// 校验 App
PayAppDO payAppDO = payAppService.validPayApp(payTransactionCreateDTO.getAppId());
// 插入 PayTransactionDO
PayTransactionDO payTransaction = payTransactionMapper.selectByAppIdAndOrderId(
payTransactionCreateDTO.getAppId(), payTransactionCreateDTO.getOrderId());
if (payTransaction != null) {
logger.warn("[createTransaction][appId({}) orderId({}) exists]", payTransactionCreateDTO.getAppId(),
payTransactionCreateDTO.getOrderId()); // 理论来说,不会出现这个情况
// TODO 芋艿 可能要考虑,更新订单。例如说,业务线订单可以修改价格
} else {
payTransaction = PayTransactionConvert.INSTANCE.convert(payTransactionCreateDTO);
payTransaction.setStatus(PayTransactionStatusEnum.WAITING.getValue())
.setNotifyUrl(payAppDO.getNotifyUrl());
payTransaction.setCreateTime(new Date());
payTransactionMapper.insert(payTransaction);
}
// 返回成功
return PayTransactionConvert.INSTANCE.convert(payTransaction);
}
@Override @Override
@SuppressWarnings("Duplicates") @SuppressWarnings("Duplicates")
public PayTransactionSubmitBO submitTransaction(PayTransactionSubmitDTO payTransactionSubmitDTO) { public PayTransactionSubmitBO submitTransaction(PayTransactionSubmitDTO payTransactionSubmitDTO) {

View File

@ -1 +0,0 @@
##################### 业务模块 #####################

View File

@ -1,65 +0,0 @@
spring:
# datasource
datasource:
url: jdbc:mysql://s1.iocoder.cn:3306/mall_pay?useSSL=false&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 3WLiVUBEwTbvAfsh
# Spring Cloud 配置项
cloud:
nacos:
# Spring Cloud Nacos Discovery 配置项
discovery:
server-addr: s1.iocoder.cn:8848 # Nacos 服务器地址
# mybatis
mybatis-plus:
config-location: classpath:mybatis-config.xml
mapper-locations: classpath:mapper/*.xml
type-aliases-package: cn.iocoder.mall.pay.biz.dataobject
# Dubbo 配置项
dubbo:
# Dubbo 注册中心
registry:
address: spring-cloud://s1.iocoder.cn:8848 # 指定 Dubbo 服务注册中心的地址
# Spring Cloud Alibaba Dubbo 专属配置
cloud:
subscribed-services: admin-application # 设置订阅的应用列表,默认为 * 订阅所有应用
# Dubbo 提供者的协议
protocol:
name: dubbo
port: -1
# Dubbo 提供服务的扫描基础包
scan:
base-packages: cn.iocoder.mall.pay.biz.service
# Dubbo 服务提供者的配置
provider:
filter: -exception
PayTransactionService:
version: 1.0.0
PayRefundService:
version: 1.0.0
# rocketmq
rocketmq:
name-server: s1.iocoder.cn:9876
producer:
group: pay-producer-group
# Seata 配置项
seata:
tx-service-group: default # Seata 事务组编号,用于 TC 集群名
# 服务配置项,对应 ServiceProperties 类
service:
# 虚拟组和分组的映射
vgroup-mapping:
default: default
# Seata 注册中心配置项
registry:
type: nacos # 注册中心类型
nacos:
serverAddr: ${spring.cloud.nacos.discovery.server-addr} # Nacos 服务地址
namespace: # Nacos 命名空间
cluster: default # 使用的 Seata 分组

View File

@ -1,37 +0,0 @@
<?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="cn.iocoder.mall.pay.biz.dao.PayAppMapper">
<sql id="FIELDS">
id, name, notify_url, refund_notify_url, status, create_time
</sql>
<!--<insert id="insert" parameterType="RoleDO" useGeneratedKeys="true" keyColumn="id" keyProperty="id">-->
<!--INSERT INTO role (-->
<!--name, create_time, deleted-->
<!--) VALUES (-->
<!--#{name}, #{createTime}, #{deleted}-->
<!--)-->
<!--</insert>-->
<!--<update id="update" parameterType="RoleDO">-->
<!--UPDATE role-->
<!--<set>-->
<!--<if test="name != null">-->
<!--, name = #{name}-->
<!--</if>-->
<!--<if test="deleted != null">-->
<!--, deleted = #{deleted}-->
<!--</if>-->
<!--</set>-->
<!--WHERE id = #{id}-->
<!--</update>-->
<select id="selectById" parameterType="String" resultType="PayAppDO">
SELECT
<include refid="FIELDS"/>
FROM app
WHERE id = #{id}
</select>
</mapper>

View File

@ -17,11 +17,17 @@
<artifactId>mall-spring-boot-starter-dubbo</artifactId> <artifactId>mall-spring-boot-starter-dubbo</artifactId>
</dependency> </dependency>
<dependency>
<!-- 订单服务 -->
<groupId>cn.iocoder.mall</groupId>
<artifactId>trade-service-api</artifactId>
</dependency>
<dependency> <dependency>
<!-- 系统服务 --> <!-- 系统服务 -->
<groupId>cn.iocoder.mall</groupId> <groupId>cn.iocoder.mall</groupId>
<artifactId>system-service-api</artifactId> <artifactId>system-service-api</artifactId>
<version>${project.version}</version> <version>1.0-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
@ -39,9 +45,10 @@
</dependency> </dependency>
<dependency> <dependency>
<!-- 订单服务 --> <!-- 支付服务 -->
<groupId>cn.iocoder.mall</groupId> <groupId>cn.iocoder.mall</groupId>
<artifactId>trade-service-api</artifactId> <artifactId>pay-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -0,0 +1,21 @@
package cn.iocoder.mall.tradeservice.client.pay;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.payservice.rpc.transaction.PayTransactionRpc;
import cn.iocoder.mall.payservice.rpc.transaction.dto.PayTransactionCreateReqDTO;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
@Service
public class PayTransactionClient {
@DubboReference(version = "${dubbo.consumer.PayTransactionRpc.version}")
private PayTransactionRpc payTransactionRpc;
public Integer createPayTransaction(PayTransactionCreateReqDTO createReqDTO) {
CommonResult<Integer> createPayTransactionResult = payTransactionRpc.createPayTransaction(createReqDTO);
createPayTransactionResult.checkError();
return createPayTransactionResult.getData();
}
}

View File

@ -0,0 +1,30 @@
package cn.iocoder.mall.tradeservice.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotNull;
@Component
@ConfigurationProperties("biz")
@Validated
@Data
public class TradeBizProperties {
/**
*
*
* pay-service
*/
@NotNull(message = "支付应用编号不能为空")
private String payAppId;
/**
*
*/
@NotNull(message = "支付超时时间不能为空")
private Integer payExpireTime;
}

View File

@ -5,14 +5,17 @@ import cn.iocoder.common.framework.util.CollectionUtils;
import cn.iocoder.common.framework.util.DateUtil; import cn.iocoder.common.framework.util.DateUtil;
import cn.iocoder.common.framework.util.MathUtil; import cn.iocoder.common.framework.util.MathUtil;
import cn.iocoder.common.framework.vo.PageResult; import cn.iocoder.common.framework.vo.PageResult;
import cn.iocoder.mall.payservice.rpc.transaction.dto.PayTransactionCreateReqDTO;
import cn.iocoder.mall.productservice.enums.sku.ProductSkuDetailFieldEnum; import cn.iocoder.mall.productservice.enums.sku.ProductSkuDetailFieldEnum;
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuRespDTO; import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuRespDTO;
import cn.iocoder.mall.promotion.api.rpc.price.dto.PriceProductCalcReqDTO; import cn.iocoder.mall.promotion.api.rpc.price.dto.PriceProductCalcReqDTO;
import cn.iocoder.mall.promotion.api.rpc.price.dto.PriceProductCalcRespDTO; import cn.iocoder.mall.promotion.api.rpc.price.dto.PriceProductCalcRespDTO;
import cn.iocoder.mall.tradeservice.client.pay.PayTransactionClient;
import cn.iocoder.mall.tradeservice.client.product.ProductSkuClient; import cn.iocoder.mall.tradeservice.client.product.ProductSkuClient;
import cn.iocoder.mall.tradeservice.client.promotion.CouponCardClient; import cn.iocoder.mall.tradeservice.client.promotion.CouponCardClient;
import cn.iocoder.mall.tradeservice.client.promotion.PriceClient; import cn.iocoder.mall.tradeservice.client.promotion.PriceClient;
import cn.iocoder.mall.tradeservice.client.user.UserAddressClient; import cn.iocoder.mall.tradeservice.client.user.UserAddressClient;
import cn.iocoder.mall.tradeservice.config.TradeBizProperties;
import cn.iocoder.mall.tradeservice.convert.order.TradeOrderConvert; import cn.iocoder.mall.tradeservice.convert.order.TradeOrderConvert;
import cn.iocoder.mall.tradeservice.dal.mysql.dataobject.order.TradeOrderDO; import cn.iocoder.mall.tradeservice.dal.mysql.dataobject.order.TradeOrderDO;
import cn.iocoder.mall.tradeservice.dal.mysql.dataobject.order.TradeOrderItemDO; import cn.iocoder.mall.tradeservice.dal.mysql.dataobject.order.TradeOrderItemDO;
@ -61,6 +64,11 @@ public class TradeOrderServiceImpl implements TradeOrderService {
private PriceClient priceClient; private PriceClient priceClient;
@Autowired @Autowired
private CouponCardClient couponCardClient; private CouponCardClient couponCardClient;
@Autowired
private PayTransactionClient payTransactionClient;
@Autowired
private TradeBizProperties tradeBizProperties;
@Override @Override
// @GlobalTransactional TODO 芋艿,使用 seata 实现分布式事务 // @GlobalTransactional TODO 芋艿,使用 seata 实现分布式事务
@ -92,15 +100,15 @@ public class TradeOrderServiceImpl implements TradeOrderService {
} }
// 创建交易订单(本地事务) // 创建交易订单(本地事务)
Integer tradeOrderId = self.createTradeOrder0(createReqDTO, listProductSkus, priceProductCalcRespDTO, userAddressRespDTO); TradeOrderDO tradeOrderDO = self.createTradeOrder0(createReqDTO, listProductSkus, priceProductCalcRespDTO, userAddressRespDTO);
// 创建支付订单,对接支付服务 // 创建支付订单,对接支付服务
createPayTransaction(); createPayTransaction(tradeOrderDO, createReqDTO, listProductSkus);
return tradeOrderId; return tradeOrderDO.getId();
} }
@Transactional @Transactional
public Integer createTradeOrder0(TradeOrderCreateReqDTO createReqDTO, List<ProductSkuRespDTO> listProductSkus, public TradeOrderDO createTradeOrder0(TradeOrderCreateReqDTO createReqDTO, List<ProductSkuRespDTO> listProductSkus,
PriceProductCalcRespDTO priceProductCalcRespDTO, UserAddressRespDTO userAddressRespDTO) { PriceProductCalcRespDTO priceProductCalcRespDTO, UserAddressRespDTO userAddressRespDTO) {
// 构建 TradeOrderDO 对象,并进行保存 // 构建 TradeOrderDO 对象,并进行保存
TradeOrderDO tradeOrderDO = new TradeOrderDO(); TradeOrderDO tradeOrderDO = new TradeOrderDO();
@ -154,11 +162,24 @@ public class TradeOrderServiceImpl implements TradeOrderService {
// 最终保存 // 最终保存
tradeOrderItemMapper.insertList(tradeOrderItemDOs); tradeOrderItemMapper.insertList(tradeOrderItemDOs);
return tradeOrderDO.getId(); return tradeOrderDO;
} }
private void createPayTransaction() { private void createPayTransaction(TradeOrderDO tradeOrderDO, TradeOrderCreateReqDTO createReqDTO,
List<ProductSkuRespDTO> listProductSkus) {
// 创建支付单
String orderSubject = listProductSkus.get(0).getSpu().getName();
Date expireTime = DateUtil.addDate(Calendar.MINUTE, tradeBizProperties.getPayExpireTime());
Integer payTransactionId = payTransactionClient.createPayTransaction(
new PayTransactionCreateReqDTO().setCreateIp(createReqDTO.getIp()).setAppId(tradeBizProperties.getPayAppId())
.setOrderId(tradeOrderDO.getId().toString()).setExpireTime(expireTime)
.setPrice(tradeOrderDO.getPresentPrice()).setOrderSubject(orderSubject)
.setOrderMemo("测试备注") // TODO 芋艿,后面补充
.setOrderDescription("测试描述") // TODO 芋艿,后面补充
);
// 更新
tradeOrderMapper.updateById(new TradeOrderDO().setId(tradeOrderDO.getId()).setPayTransactionId(payTransactionId));
} }
private String generateTradeOrderNo() { private String generateTradeOrderNo() {

View File

@ -47,6 +47,8 @@ dubbo:
version: 1.0.0 version: 1.0.0
CouponCardRpc: CouponCardRpc:
version: 1.0.0 version: 1.0.0
PayTransactionRpc:
version: 1.0.0
# RocketMQ 配置项 # RocketMQ 配置项
rocketmq: rocketmq:
@ -66,3 +68,8 @@ mall:
error-code: error-code:
group: ${spring.application.name} group: ${spring.application.name}
constants-class: cn.iocoder.mall.tradeservice.enums.OrderErrorCodeConstants constants-class: cn.iocoder.mall.tradeservice.enums.OrderErrorCodeConstants
# 业务配置
biz:
pay-app-id: POd4RC6a
pay-expire-time: 120