@ -1,25 +1,33 @@
package cn.iocoder.mall.pay.service ;
package cn.iocoder.mall.pay.service ;
import cn.iocoder.common.framework.util.DateUtil ;
import cn.iocoder.common.framework.util.MathUtil ;
import cn.iocoder.common.framework.util.ServiceExceptionUtil ;
import cn.iocoder.common.framework.util.ServiceExceptionUtil ;
import cn.iocoder.common.framework.vo.CommonResult ;
import cn.iocoder.common.framework.vo.CommonResult ;
import cn.iocoder.mall.pay.api.PayTransactionService ;
import cn.iocoder.mall.pay.api.PayTransactionService ;
import cn.iocoder.mall.pay.api.bo.PayTransactionBO ;
import cn.iocoder.mall.pay.api.bo.PayTransactionBO ;
import cn.iocoder.mall.pay.api.bo.PayTransactionSubmitBO ;
import cn.iocoder.mall.pay.api.bo.PayTransactionSubmitBO ;
import cn.iocoder.mall.pay.api.constant.PayErrorCodeEnum ;
import cn.iocoder.mall.pay.api.constant.PayErrorCodeEnum ;
import cn.iocoder.mall.pay.api.constant.PayTransactionNotifyStatusEnum ;
import cn.iocoder.mall.pay.api.constant.PayTransactionStatusEnum ;
import cn.iocoder.mall.pay.api.constant.PayTransactionStatusEnum ;
import cn.iocoder.mall.pay.api.dto.PayTransactionCreateDTO ;
import cn.iocoder.mall.pay.api.dto.PayTransactionCreateDTO ;
import cn.iocoder.mall.pay.api.dto.PayTransactionSubmitDTO ;
import cn.iocoder.mall.pay.api.dto.PayTransactionSubmitDTO ;
import cn.iocoder.mall.pay.client.AbstractPaySDK ;
import cn.iocoder.mall.pay.client.PaySDKFactory ;
import cn.iocoder.mall.pay.client.PaySDKFactory ;
import cn.iocoder.mall.pay.client.TransactionPaySuccessBO ;
import cn.iocoder.mall.pay.convert.PayTransactionConvert ;
import cn.iocoder.mall.pay.convert.PayTransactionConvert ;
import cn.iocoder.mall.pay.dao.PayTransactionExtensionMapper ;
import cn.iocoder.mall.pay.dao.PayTransactionExtensionMapper ;
import cn.iocoder.mall.pay.dao.PayTransactionMapper ;
import cn.iocoder.mall.pay.dao.PayTransactionMapper ;
import cn.iocoder.mall.pay.dao.PayTransactionNotifyTaskMapper ;
import cn.iocoder.mall.pay.dataobject.PayAppDO ;
import cn.iocoder.mall.pay.dataobject.PayAppDO ;
import cn.iocoder.mall.pay.dataobject.PayTransactionDO ;
import cn.iocoder.mall.pay.dataobject.PayTransactionDO ;
import cn.iocoder.mall.pay.dataobject.PayTransactionExtensionDO ;
import cn.iocoder.mall.pay.dataobject.PayTransactionExtensionDO ;
import cn.iocoder.mall.pay.dataobject.PayTransactionNotifyTaskDO ;
import org.slf4j.Logger ;
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
import org.slf4j.LoggerFactory ;
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.transaction.annotation.Transactional ;
import java.util.Date ;
import java.util.Date ;
@ -34,6 +42,8 @@ public class PayServiceImpl implements PayTransactionService {
@Autowired
@Autowired
private PayTransactionExtensionMapper payTransactionExtensionMapper ;
private PayTransactionExtensionMapper payTransactionExtensionMapper ;
@Autowired
@Autowired
private PayTransactionNotifyTaskMapper payTransactionNotifyTaskMapper ;
@Autowired
private PayAppServiceImpl payAppService ;
private PayAppServiceImpl payAppService ;
@Override
@Override
@ -77,17 +87,18 @@ public class PayServiceImpl implements PayTransactionService {
if ( payTransaction = = null ) { // 是否存在
if ( payTransaction = = null ) { // 是否存在
return ServiceExceptionUtil . error ( PayErrorCodeEnum . PAY_TRANSACTION_NOT_FOUND . getCode ( ) ) ;
return ServiceExceptionUtil . error ( PayErrorCodeEnum . PAY_TRANSACTION_NOT_FOUND . getCode ( ) ) ;
}
}
if ( PayTransactionStatusEnum . WAITTING . getValue ( ) . equals ( payTransaction . getStatus ( ) ) ) { // 校验状态
if ( ! PayTransactionStatusEnum . WAITTING . getValue ( ) . equals ( payTransaction . getStatus ( ) ) ) { // 校验状态 ,必须是待支付
return ServiceExceptionUtil . error ( PayErrorCodeEnum . PAY_TRANSACTION_STATUS_IS_NOT_WAITING . getCode ( ) ) ;
return ServiceExceptionUtil . error ( PayErrorCodeEnum . PAY_TRANSACTION_STATUS_IS_NOT_WAITING . getCode ( ) ) ;
}
}
// 插入 PayTransactionExtensionDO
// 插入 PayTransactionExtensionDO
PayTransactionExtensionDO payTransactionExtensionDO = PayTransactionConvert . INSTANCE . convert ( payTransactionSubmitDTO )
PayTransactionExtensionDO payTransactionExtensionDO = PayTransactionConvert . INSTANCE . convert ( payTransactionSubmitDTO )
. setTransactionId ( payTransaction . getId ( ) )
. setTransactionId ( payTransaction . getId ( ) )
. setTransactionCode ( "TODO" )
. setTransactionCode ( generateTransactionCode ( ) )
. setStatus ( PayTransactionStatusEnum . WAITTING . getValue ( ) ) ;
. setStatus ( PayTransactionStatusEnum . WAITTING . getValue ( ) ) ;
payTransactionExtensionMapper . insert ( payTransactionExtensionDO ) ;
payTransactionExtensionMapper . insert ( payTransactionExtensionDO ) ;
// 调用三方接口
// 调用三方接口
CommonResult < String > invokeResult = PaySDKFactory . getSDK ( payTransactionSubmitDTO . getPayChannel ( ) ) . submitTransaction ( payTransaction , payTransactionExtensionDO , null ) ; // TODO 暂时传入 extra = null
AbstractPaySDK paySDK = PaySDKFactory . getSDK ( payTransactionSubmitDTO . getPayChannel ( ) ) ;
CommonResult < String > invokeResult = paySDK . submitTransaction ( payTransaction , payTransactionExtensionDO , null ) ; // TODO 暂时传入 extra = null
if ( invokeResult . isError ( ) ) {
if ( invokeResult . isError ( ) ) {
return CommonResult . error ( invokeResult ) ;
return CommonResult . error ( invokeResult ) ;
}
}
@ -99,8 +110,88 @@ public class PayServiceImpl implements PayTransactionService {
}
}
@Override
@Override
@Transactional
public CommonResult < Boolean > updateTransactionPaySuccess ( Integer payChannel , String params ) {
// TODO 芋艿,记录回调日志
// 解析传入的参数,成 TransactionPaySuccessBO 对象
AbstractPaySDK paySDK = PaySDKFactory . getSDK ( payChannel ) ;
CommonResult < TransactionPaySuccessBO > paySuccessResult = paySDK . parseTransactionPaySuccessParams ( params ) ;
if ( paySuccessResult . isError ( ) ) {
return CommonResult . error ( paySuccessResult ) ;
}
// TODO 芋艿,先最严格的校验。即使调用方重复调用,实际哪个订单已经被重复回调的支付,也返回 false 。也没问题,因为实际已经回调成功了。
// 1.1 查询 PayTransactionExtensionDO
PayTransactionExtensionDO payTransactionExtension = payTransactionExtensionMapper . selectByTransactionCode ( paySuccessResult . getData ( ) . getTransactionCode ( ) ) ;
if ( payTransactionExtension = = null ) {
return ServiceExceptionUtil . error ( PayErrorCodeEnum . PAY_TRANSACTION_EXTENSION_NOT_FOUND . getCode ( ) ) ;
}
if ( ! PayTransactionStatusEnum . WAITTING . getValue ( ) . equals ( payTransactionExtension . getStatus ( ) ) ) { // 校验状态,必须是待支付
return ServiceExceptionUtil . error ( PayErrorCodeEnum . PAY_TRANSACTION_EXTENSION_STATUS_IS_NOT_WAITING . getCode ( ) ) ;
}
// 1.2 更新 PayTransactionExtensionDO
PayTransactionExtensionDO updatePayTransactionExtension = new PayTransactionExtensionDO ( )
. setId ( payTransactionExtension . getId ( ) )
. setStatus ( PayTransactionStatusEnum . SUCCESS . getValue ( ) )
. setExtensionData ( params ) ;
int updateCounts = payTransactionExtensionMapper . update ( updatePayTransactionExtension , PayTransactionStatusEnum . WAITTING . getValue ( ) ) ;
if ( updateCounts = = 0 ) { // 校验状态,必须是待支付
throw ServiceExceptionUtil . exception ( PayErrorCodeEnum . PAY_TRANSACTION_EXTENSION_STATUS_IS_NOT_WAITING . getCode ( ) ) ;
}
// 2.1
PayTransactionDO payTransactionDO = payTransactionMapper . selectById ( payTransactionExtension . getTransactionId ( ) ) ;
if ( payTransactionDO = = null ) {
return ServiceExceptionUtil . error ( PayErrorCodeEnum . PAY_TRANSACTION_NOT_FOUND . getCode ( ) ) ;
}
if ( ! PayTransactionStatusEnum . WAITTING . getValue ( ) . equals ( payTransactionDO . getStatus ( ) ) ) { // 校验状态,必须是待支付
throw ServiceExceptionUtil . exception ( PayErrorCodeEnum . PAY_TRANSACTION_STATUS_IS_NOT_WAITING . getCode ( ) ) ;
}
// 2.2 更新 PayTransactionDO
PayTransactionDO updatePayTransaction = new PayTransactionDO ( )
. setId ( payTransactionDO . getId ( ) )
. setStatus ( PayTransactionStatusEnum . SUCCESS . getValue ( ) )
. setExtensionId ( payTransactionExtension . getId ( ) )
. setPayChannel ( payChannel )
. setPaymentTime ( paySuccessResult . getData ( ) . getPaymentTime ( ) )
. setNotifyTime ( new Date ( ) )
. setTradeNo ( paySuccessResult . getData ( ) . getTradeNo ( ) ) ;
updateCounts = payTransactionMapper . update ( updatePayTransaction , PayTransactionStatusEnum . WAITTING . getValue ( ) ) ;
if ( updateCounts = = 0 ) { // 校验状态,必须是待支付 TODO 这种类型,需要思考下。需要返回错误,但是又要保证事务回滚
throw ServiceExceptionUtil . exception ( PayErrorCodeEnum . PAY_TRANSACTION_STATUS_IS_NOT_WAITING . getCode ( ) ) ;
}
// 3. 插入
PayTransactionNotifyTaskDO payTransactionNotifyTask = new PayTransactionNotifyTaskDO ( )
. setTransactionId ( payTransactionExtension . getTransactionId ( ) ) . setTransactionExtensionId ( payTransactionExtension . getId ( ) )
. setAppId ( payTransactionDO . getAppId ( ) ) . setOrderId ( payTransactionDO . getOrderId ( ) )
. setStatus ( PayTransactionNotifyStatusEnum . WAITING . getValue ( ) )
. setNotifyTimes ( 0 ) . setMaxNotifyTimes ( 5 )
. setNotifyUrl ( payTransactionDO . getNotifyUrl ( ) ) ;
payTransactionNotifyTaskMapper . insert ( payTransactionNotifyTask ) ;
// 返回结果
return CommonResult . success ( true ) ;
}
@Override // TODO 芋艿,后面去实现
public CommonResult cancelTransaction ( ) {
public CommonResult cancelTransaction ( ) {
return null ;
return null ;
}
}
private String generateTransactionCode ( ) {
// wx
// 2014
// 10
// 27
// 20
// 09
// 39
// 5522657
// a690389285100
// 目前的算法
// 时间序列,年月日时分秒 14 位
// 纯随机, 6 位 TODO 此处估计是会有问题的,后续在调整
return DateUtil . format ( new Date ( ) , "yyyyMMddHHmmss" ) + // 时间序列
MathUtil . random ( 100000 , 999999 ) // 随机。为什么是这个范围,因为偷懒
;
}
}
}