32 changed files with 1279 additions and 337 deletions
@ -0,0 +1,30 @@ |
|||
package com.bnyer.pay.bo; |
|||
|
|||
import lombok.Getter; |
|||
import lombok.NoArgsConstructor; |
|||
import lombok.Setter; |
|||
|
|||
/** |
|||
* @author :WXC |
|||
* @Date :2023/05/05 |
|||
* @description : |
|||
*/ |
|||
@Getter |
|||
@Setter |
|||
@NoArgsConstructor |
|||
public class QueryOrderBo { |
|||
|
|||
/** |
|||
* 支付类型:wxpay/alipay/kspay/dypay |
|||
*/ |
|||
private String payType; |
|||
/** |
|||
* 交易类型 1--JSAPI支付(小程序appId支付)、2--Native支付、3--app支付,4--JSAPI支付(公众号appId支付)5--H5支付,微信支付必填 |
|||
*/ |
|||
private String tradeType; |
|||
/** |
|||
* 支付单号 |
|||
*/ |
|||
private String payId; |
|||
|
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
package com.bnyer.pay.controller; |
|||
|
|||
import com.bnyer.common.core.domain.R; |
|||
import com.bnyer.pay.dto.InOrderDto; |
|||
import com.bnyer.pay.dto.QueryOrderDto; |
|||
import com.bnyer.pay.service.UnifiedPayService; |
|||
import com.bnyer.pay.vo.QueryOrderVo; |
|||
import com.bnyer.pay.vo.ThirdInOrderVo; |
|||
import io.swagger.annotations.Api; |
|||
import io.swagger.v3.oas.annotations.Operation; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.web.bind.annotation.PostMapping; |
|||
import org.springframework.web.bind.annotation.RequestBody; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
|
|||
import javax.servlet.http.HttpServletRequest; |
|||
import javax.validation.Valid; |
|||
|
|||
/** |
|||
* @author :WXC |
|||
* @Date :2023/05/05 |
|||
* @description : |
|||
*/ |
|||
@Api(value = "统一支付相关接口",tags = "统一支付相关接口") |
|||
@RestController |
|||
@RequestMapping("/unified") |
|||
@Slf4j |
|||
public class UnifiedPayController { |
|||
|
|||
@Autowired |
|||
private UnifiedPayService unifiedPayService; |
|||
|
|||
@PostMapping("/inOrder") |
|||
@Operation(summary = "统一下单,并生成支付订单" , description = "生成支付订单,返回前端支付所需参数") |
|||
public R<ThirdInOrderVo> inOrder(@Valid @RequestBody InOrderDto dto, HttpServletRequest request){ |
|||
ThirdInOrderVo thirdInOrderVo = unifiedPayService.inOrder(dto,request); |
|||
return R.ok(thirdInOrderVo); |
|||
} |
|||
|
|||
@PostMapping("/queryOrder") |
|||
@Operation(summary = "统一订单查询" , description = "订单查询,查询支付结果") |
|||
public R<QueryOrderVo> queryOrder(@Valid @RequestBody QueryOrderDto dto){ |
|||
QueryOrderVo queryOrderVo = unifiedPayService.queryOrder(dto); |
|||
return R.ok(queryOrderVo); |
|||
} |
|||
|
|||
} |
|||
@ -1,39 +1,87 @@ |
|||
package com.bnyer.pay.dto; |
|||
|
|||
import com.bnyer.common.core.annotation.CustomParamsValidation; |
|||
import com.baomidou.mybatisplus.annotation.TableField; |
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.AllArgsConstructor; |
|||
import lombok.Getter; |
|||
import lombok.NoArgsConstructor; |
|||
import lombok.Setter; |
|||
|
|||
import javax.validation.constraints.NotBlank; |
|||
import java.math.BigDecimal; |
|||
import java.util.Date; |
|||
|
|||
/** |
|||
* @author :WXC |
|||
* @Date :2023/04/03 |
|||
* @Date :2023/05/05 |
|||
* @description : |
|||
*/ |
|||
@Getter |
|||
@Setter |
|||
@NoArgsConstructor |
|||
@AllArgsConstructor |
|||
public class AddPayInfoDto { |
|||
|
|||
@NotBlank(message = "业务主订单号不能为空") |
|||
@ApiModelProperty(value="业务主订单号:关联内部业务订单表",required = true) |
|||
@ApiModelProperty(value="支付单号(内部生成)") |
|||
private String payId; |
|||
|
|||
@ApiModelProperty(value="业务主订单号:关联内部业务订单表") |
|||
private String orderNo; |
|||
|
|||
@NotBlank(message = "支付场景不能为空") |
|||
@ApiModelProperty(value="支付场景:1.会员充值",required = true) |
|||
private Integer sceneCode; |
|||
@ApiModelProperty(value="支付状态:1000未支付;1001支付成功 ;1002支付失败") |
|||
private Integer payStatus; |
|||
|
|||
@ApiModelProperty(value="单笔对账状态:1001 对账成功") |
|||
private Integer singleStatus; |
|||
|
|||
@NotBlank(message = "支付类型不能为空") |
|||
@ApiModelProperty(value="支付类型:wxpay/alipay",required = true) |
|||
@ApiModelProperty(value="单笔对账时间") |
|||
private Date singleTime; |
|||
|
|||
@ApiModelProperty(value="支付类型:wxpay/alipay/kspay/dypay") |
|||
private String payType; |
|||
|
|||
@ApiModelProperty(value="交易类型 1--JSAPI支付(小程序appId支付)、2--Native支付、3--app支付,4--JSAPI支付(公众号appId支付)5--H5支付,微信支付必填",example = "1") |
|||
@CustomParamsValidation(range = "1",message = "交易类型暂时只支持JSAPI") |
|||
@ApiModelProperty(value="支付渠道:wxpay/alipay") |
|||
private String payChannel; |
|||
|
|||
@ApiModelProperty(value = "交易类型:JSAPI等") |
|||
private String tradeType; |
|||
|
|||
@ApiModelProperty(value="支付单号(第三方返回)") |
|||
private String payNo; |
|||
|
|||
@ApiModelProperty(value="用户侧订单号(第三方返回)") |
|||
private String tradeNo; |
|||
|
|||
@ApiModelProperty(value="appid") |
|||
private String appid; |
|||
|
|||
@ApiModelProperty(value="商品标题") |
|||
private String goodsSubject; |
|||
|
|||
@ApiModelProperty(value="商品描述") |
|||
private String goodsDesc; |
|||
|
|||
@ApiModelProperty(value="支付金额,单位元") |
|||
private BigDecimal payAmount; |
|||
|
|||
@ApiModelProperty(value="支付时间") |
|||
private Date payTime; |
|||
|
|||
@ApiModelProperty(value="支付场景:1.会员充值") |
|||
private Integer sceneCode; |
|||
|
|||
@ApiModelProperty(value="用户ip") |
|||
private String ip; |
|||
|
|||
@ApiModelProperty(value="调用第三方下单返回") |
|||
private String thirdCode; |
|||
|
|||
@ApiModelProperty(value="调用第三方下单返回") |
|||
private String thirdMsg; |
|||
|
|||
@ApiModelProperty(value="调用第三方下单返回") |
|||
private String thirdNo; |
|||
|
|||
@ApiModelProperty(value="备注") |
|||
private String remark; |
|||
|
|||
} |
|||
|
|||
@ -0,0 +1,39 @@ |
|||
package com.bnyer.pay.dto; |
|||
|
|||
import com.bnyer.common.core.annotation.CustomParamsValidation; |
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.Getter; |
|||
import lombok.NoArgsConstructor; |
|||
import lombok.Setter; |
|||
|
|||
import javax.validation.constraints.NotBlank; |
|||
|
|||
/** |
|||
* @author :WXC |
|||
* @Date :2023/04/03 |
|||
* @description : |
|||
*/ |
|||
@Getter |
|||
@Setter |
|||
@NoArgsConstructor |
|||
public class InOrderDto { |
|||
|
|||
@NotBlank(message = "业务主订单号不能为空") |
|||
@ApiModelProperty(value="业务主订单号:关联内部业务订单表",required = true) |
|||
private String orderNo; |
|||
|
|||
@NotBlank(message = "支付场景不能为空") |
|||
@ApiModelProperty(value="支付场景:1.会员充值",required = true) |
|||
private Integer sceneCode; |
|||
|
|||
@NotBlank(message = "支付类型不能为空") |
|||
@ApiModelProperty(value="支付类型:wxpay/alipay",required = true) |
|||
private String payType; |
|||
|
|||
@ApiModelProperty(value="交易类型 1--JSAPI支付(小程序appId支付)、2--Native支付、3--app支付,4--JSAPI支付(公众号appId支付)5--H5支付,微信支付必填",example = "1") |
|||
@CustomParamsValidation(range = "1",message = "交易类型暂时只支持JSAPI") |
|||
private String tradeType; |
|||
|
|||
@ApiModelProperty(value="备注") |
|||
private String remark; |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
package com.bnyer.pay.dto; |
|||
|
|||
import com.bnyer.common.core.annotation.CustomParamsValidation; |
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.Getter; |
|||
import lombok.NoArgsConstructor; |
|||
import lombok.Setter; |
|||
|
|||
import javax.validation.constraints.NotBlank; |
|||
|
|||
/** |
|||
* @author :WXC |
|||
* @Date :2023/05/05 |
|||
* @description : |
|||
*/ |
|||
@Getter |
|||
@Setter |
|||
@NoArgsConstructor |
|||
public class QueryOrderDto { |
|||
|
|||
@NotBlank(message = "支付类型不能为空") |
|||
@ApiModelProperty(value="支付类型:wxpay/alipay/kspay/dypay",required = true) |
|||
private String payType; |
|||
|
|||
@ApiModelProperty(value="交易类型 1--JSAPI支付(小程序appId支付)、2--Native支付、3--app支付,4--JSAPI支付(公众号appId支付)5--H5支付,微信支付必填",example = "1") |
|||
@CustomParamsValidation(range = "1",message = "交易类型暂时只支持JSAPI") |
|||
private String tradeType; |
|||
|
|||
@NotBlank(message = "支付单号不能为空") |
|||
@ApiModelProperty(value="支付单号",required = true) |
|||
private String payId; |
|||
|
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
package com.bnyer.pay.enums; |
|||
|
|||
import com.bnyer.common.core.enums.EnumPayStatus; |
|||
import com.bnyer.common.core.exception.ServiceException; |
|||
import lombok.AllArgsConstructor; |
|||
import lombok.Getter; |
|||
|
|||
import java.util.Objects; |
|||
|
|||
/** |
|||
* @author :WXC |
|||
* @Date :2023/05/05 |
|||
* @description : |
|||
*/ |
|||
@Getter |
|||
@AllArgsConstructor |
|||
public enum EnumDyPayStatus { |
|||
|
|||
PROCESSING("PROCESSING",EnumPayStatus.NO_PAY), |
|||
SUCCESS("SUCCESS",EnumPayStatus.SUCCESS), |
|||
FAIL("FAIL",EnumPayStatus.FAILS), |
|||
TIMEOUT("TIMEOUT",EnumPayStatus.FAILS), |
|||
; |
|||
private final String status; |
|||
|
|||
private final EnumPayStatus enumPayStatus; |
|||
|
|||
public static EnumPayStatus getEnumPayStatusByStatus(String status) { |
|||
for (EnumDyPayStatus s : EnumDyPayStatus.values()) { |
|||
if (Objects.equals(status, s.getStatus())) { |
|||
return s.getEnumPayStatus(); |
|||
} |
|||
} |
|||
throw new ServiceException("status 未匹配上对应的支付状态"); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
package com.bnyer.pay.enums; |
|||
|
|||
import com.bnyer.common.core.enums.EnumPayStatus; |
|||
import com.bnyer.common.core.exception.ServiceException; |
|||
import lombok.AllArgsConstructor; |
|||
import lombok.Getter; |
|||
|
|||
import java.util.Objects; |
|||
|
|||
/** |
|||
* @author :WXC |
|||
* @Date :2023/05/05 |
|||
* @description : |
|||
*/ |
|||
@Getter |
|||
@AllArgsConstructor |
|||
public enum EnumKsPayStatus { |
|||
|
|||
PROCESSING("PROCESSING",EnumPayStatus.NO_PAY), |
|||
SUCCESS("SUCCESS",EnumPayStatus.SUCCESS), |
|||
FAILED("FAILED",EnumPayStatus.FAILS), |
|||
TIMEOUT("TIMEOUT",EnumPayStatus.FAILS), |
|||
; |
|||
private final String status; |
|||
|
|||
private final EnumPayStatus enumPayStatus; |
|||
|
|||
public static EnumPayStatus getEnumPayStatusByStatus(String status) { |
|||
for (EnumKsPayStatus s : EnumKsPayStatus.values()) { |
|||
if (Objects.equals(status, s.getStatus())) { |
|||
return s.getEnumPayStatus(); |
|||
} |
|||
} |
|||
throw new ServiceException("status 未匹配上对应的支付状态"); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
package com.bnyer.pay.enums; |
|||
|
|||
import com.bnyer.common.core.enums.EnumPayStatus; |
|||
import com.bnyer.common.core.exception.ServiceException; |
|||
import lombok.AllArgsConstructor; |
|||
import lombok.Getter; |
|||
|
|||
import java.util.Objects; |
|||
|
|||
/** |
|||
* @author :WXC |
|||
* @Date :2023/05/05 |
|||
* @description : |
|||
*/ |
|||
@Getter |
|||
@AllArgsConstructor |
|||
public enum EnumWxPayStatus { |
|||
|
|||
NOT_PAY("NOTPAY",EnumPayStatus.NO_PAY), |
|||
USER_PAYING("USERPAYING",EnumPayStatus.NO_PAY), |
|||
SUCCESS("SUCCESS",EnumPayStatus.SUCCESS), |
|||
PAY_ERROR("PAYERROR",EnumPayStatus.FAILS), |
|||
; |
|||
private final String status; |
|||
|
|||
private final EnumPayStatus enumPayStatus; |
|||
|
|||
public static EnumPayStatus getEnumPayStatusByStatus(String status) { |
|||
for (EnumWxPayStatus s : EnumWxPayStatus.values()) { |
|||
if (Objects.equals(status, s.getStatus())) { |
|||
return s.getEnumPayStatus(); |
|||
} |
|||
} |
|||
throw new ServiceException("status 未匹配上对应的支付状态"); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
package com.bnyer.pay.service; |
|||
|
|||
import com.bnyer.pay.dto.InOrderDto; |
|||
import com.bnyer.pay.dto.QueryOrderDto; |
|||
import com.bnyer.pay.vo.QueryOrderVo; |
|||
import com.bnyer.pay.vo.ThirdInOrderVo; |
|||
|
|||
import javax.servlet.http.HttpServletRequest; |
|||
|
|||
/** |
|||
* @author :WXC |
|||
* @Date :2023/05/05 |
|||
* @description : |
|||
*/ |
|||
public interface UnifiedPayService { |
|||
|
|||
/** |
|||
* 统一下单,并生成支付订单 |
|||
* @param dto |
|||
* @param request |
|||
* @return |
|||
*/ |
|||
ThirdInOrderVo inOrder(InOrderDto dto, HttpServletRequest request); |
|||
|
|||
/** |
|||
* 统一订单查询 |
|||
* @param dto |
|||
* @return |
|||
*/ |
|||
QueryOrderVo queryOrder(QueryOrderDto dto); |
|||
} |
|||
@ -0,0 +1,209 @@ |
|||
package com.bnyer.pay.service.impl; |
|||
|
|||
import com.bnyer.common.core.domain.R; |
|||
import com.bnyer.common.core.enums.EnumPayStatus; |
|||
import com.bnyer.common.core.enums.EnumPayType; |
|||
import com.bnyer.common.core.enums.EnumSceneCode; |
|||
import com.bnyer.common.core.enums.EnumUserClientType; |
|||
import com.bnyer.common.core.exception.ServiceException; |
|||
import com.bnyer.common.core.utils.OrderUtil; |
|||
import com.bnyer.common.core.utils.bean.EntityConvertUtil; |
|||
import com.bnyer.common.core.utils.ip.IpUtils; |
|||
import com.bnyer.order.api.dto.QueryVipOrderDto; |
|||
import com.bnyer.order.api.remote.RemoteVipOrderService; |
|||
import com.bnyer.order.api.vo.VipOrderVo; |
|||
import com.bnyer.pay.bo.QueryOrderBo; |
|||
import com.bnyer.pay.bo.UnifiedOrderBo; |
|||
import com.bnyer.pay.constant.KSPayConstants; |
|||
import com.bnyer.pay.design.factory.PayFactory; |
|||
import com.bnyer.pay.design.strategy.IPayStrategy; |
|||
import com.bnyer.pay.dto.AddPayInfoDto; |
|||
import com.bnyer.pay.dto.InOrderDto; |
|||
import com.bnyer.pay.dto.QueryOrderDto; |
|||
import com.bnyer.pay.enums.EnumDyPayStatus; |
|||
import com.bnyer.pay.enums.EnumKsPayStatus; |
|||
import com.bnyer.pay.enums.EnumWxPayStatus; |
|||
import com.bnyer.pay.service.PayInfoService; |
|||
import com.bnyer.pay.service.UnifiedPayService; |
|||
import com.bnyer.pay.vo.QueryOrderVo; |
|||
import com.bnyer.pay.vo.ThirdInOrderVo; |
|||
import com.bnyer.pay.vo.PayInfoDetailsVo; |
|||
import com.bnyer.pay.vo.ThirdQueryOrderVo; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import javax.servlet.http.HttpServletRequest; |
|||
import java.math.BigDecimal; |
|||
import java.util.Date; |
|||
import java.util.List; |
|||
import java.util.Objects; |
|||
|
|||
/** |
|||
* @author :WXC |
|||
* @Date :2023/05/05 |
|||
* @description : |
|||
*/ |
|||
@Slf4j |
|||
@Service |
|||
public class UnifiedPayServiceImpl implements UnifiedPayService { |
|||
|
|||
@Autowired |
|||
private PayInfoService payInfoService; |
|||
|
|||
@Autowired |
|||
private RemoteVipOrderService remoteVipOrderService; |
|||
|
|||
/** |
|||
* 统一下单,并生成支付订单 |
|||
* @param dto |
|||
* @param request |
|||
* @return |
|||
*/ |
|||
@Override |
|||
public ThirdInOrderVo inOrder(InOrderDto dto, HttpServletRequest request) { |
|||
//支付金额
|
|||
String payAmount = ""; |
|||
//商品类型:快手支付需要
|
|||
int goodsType; |
|||
//payId
|
|||
String payId; |
|||
EnumSceneCode enumSceneCode = EnumSceneCode.getSceneCodeByCode(dto.getSceneCode()); |
|||
switch (enumSceneCode){ |
|||
//会员充值场景
|
|||
case VIP_RECHARGE: |
|||
QueryVipOrderDto queryVipOrderDto = new QueryVipOrderDto(); |
|||
queryVipOrderDto.setOrderNo(dto.getOrderNo()); |
|||
//查询会员业务订单信息
|
|||
R<List<VipOrderVo>> vipOrderVoListR = remoteVipOrderService.getVipOrderList(queryVipOrderDto); |
|||
if (!vipOrderVoListR.isSuccess()){ |
|||
throw new ServiceException(vipOrderVoListR.getMsg()); |
|||
} |
|||
VipOrderVo vipOrderVo = vipOrderVoListR.getData().get(0); |
|||
payAmount = vipOrderVo.getPayAmount().toString(); |
|||
goodsType = KSPayConstants.GOODS_TYPE_VIP; |
|||
payId = OrderUtil.getOrderNo("RV",new Date(), EnumUserClientType.getCodeByType(vipOrderVo.getUserClientType()) |
|||
,String.valueOf(vipOrderVo.getUserId())); |
|||
break; |
|||
default: |
|||
throw new ServiceException("sceneCode未匹配上对应支付场景"); |
|||
} |
|||
//构建统一下单请求实体
|
|||
UnifiedOrderBo unifiedOrderBo = buildUnifiedOrderDto(dto, goodsType,payAmount,payId, request); |
|||
//下单,获取第三方返回信息
|
|||
IPayStrategy payStrategy = PayFactory.getInstance().getConcreteStrategy(dto.getPayType()); |
|||
if (Objects.isNull(payStrategy)){ |
|||
throw new ServiceException("暂不支持该支付方式"); |
|||
} |
|||
ThirdInOrderVo thirdInOrderVo = payStrategy.unifiedOrder(unifiedOrderBo); |
|||
//构建支付订单完成入库
|
|||
AddPayInfoDto addPayInfoDto = buildPayInfo(thirdInOrderVo, unifiedOrderBo,dto); |
|||
payInfoService.addPayInfo(addPayInfoDto); |
|||
return thirdInOrderVo; |
|||
} |
|||
|
|||
/** |
|||
* 构建支付订单 |
|||
* |
|||
* @param thirdInOrderVo |
|||
* @param unifiedOrderBo |
|||
* @param dto |
|||
* @return |
|||
*/ |
|||
private AddPayInfoDto buildPayInfo(ThirdInOrderVo thirdInOrderVo, UnifiedOrderBo unifiedOrderBo, InOrderDto dto) { |
|||
AddPayInfoDto addPayInfoDto = new AddPayInfoDto(); |
|||
addPayInfoDto.setOrderNo(dto.getOrderNo()); |
|||
addPayInfoDto.setSceneCode(dto.getSceneCode()); |
|||
addPayInfoDto.setRemark(dto.getRemark()); |
|||
addPayInfoDto.setPayType(dto.getPayType()); |
|||
addPayInfoDto.setPayId(unifiedOrderBo.getPayId()); |
|||
addPayInfoDto.setPayAmount(new BigDecimal(unifiedOrderBo.getPayAmount())); |
|||
addPayInfoDto.setAppid(thirdInOrderVo.getAppid()); |
|||
addPayInfoDto.setGoodsSubject(unifiedOrderBo.getGoodsSubject()); |
|||
addPayInfoDto.setGoodsDesc(unifiedOrderBo.getGoodsDesc()); |
|||
addPayInfoDto.setThirdNo(thirdInOrderVo.getPrepayid()); |
|||
addPayInfoDto.setIp(unifiedOrderBo.getIp()); |
|||
return addPayInfoDto; |
|||
} |
|||
|
|||
/** |
|||
* 构建统一下单请求实体 |
|||
* |
|||
* @param dto 入参 |
|||
* @param goodsType 商品类型 |
|||
* @param payAmount 不同支付场景下的支付金额 |
|||
* @param payId 内部系统支付单号 |
|||
* @param request 请求request用于获取ip地址 |
|||
* @return |
|||
*/ |
|||
private UnifiedOrderBo buildUnifiedOrderDto(InOrderDto dto, int goodsType, String payAmount, String payId, HttpServletRequest request) { |
|||
//当前时间
|
|||
Date currDate = new Date(); |
|||
//ip地址
|
|||
String ip = IpUtils.getIpAddr(request); |
|||
UnifiedOrderBo unifiedOrderBo = EntityConvertUtil.copy(dto, UnifiedOrderBo.class); |
|||
unifiedOrderBo.setPayId(payId); |
|||
unifiedOrderBo.setIp(ip); |
|||
unifiedOrderBo.setCurrDate(currDate); |
|||
unifiedOrderBo.setPayAmount(payAmount); |
|||
unifiedOrderBo.setGoodsType(goodsType); |
|||
return unifiedOrderBo; |
|||
} |
|||
|
|||
/** |
|||
* 统一订单查询 |
|||
* @param dto |
|||
* @return |
|||
*/ |
|||
@Override |
|||
public QueryOrderVo queryOrder(QueryOrderDto dto) { |
|||
//先查询系统支付单是否已经完成支付,如果因为延迟导致没有及时同步,在调用第三方接口查询支付状态返回
|
|||
PayInfoDetailsVo payInfoDetailsVo = payInfoService.queryOrder(dto.getPayId()); |
|||
Integer payStatus = payInfoDetailsVo.getPayStatus(); |
|||
EnumPayStatus enumPayStatus = EnumPayStatus.getEnumPayStatusByStatus(payStatus); |
|||
if (EnumPayStatus.NO_PAY != enumPayStatus){ |
|||
QueryOrderVo queryOrderVo = new QueryOrderVo(); |
|||
queryOrderVo.setPayId(dto.getPayId()); |
|||
queryOrderVo.setPayStatus(enumPayStatus.getStatus()); |
|||
return queryOrderVo; |
|||
} |
|||
//获取第三方订单信息
|
|||
IPayStrategy strategy = PayFactory.getInstance().getConcreteStrategy(dto.getPayType()); |
|||
if (Objects.isNull(strategy)){ |
|||
throw new ServiceException("暂不支持该支付方式"); |
|||
} |
|||
//构建统一订单查询实体
|
|||
QueryOrderBo queryOrderBo = EntityConvertUtil.copy(dto, QueryOrderBo.class); |
|||
ThirdQueryOrderVo thirdQueryOrderVo = strategy.queryOrder(queryOrderBo); |
|||
QueryOrderVo queryOrderVo = new QueryOrderVo(); |
|||
queryOrderVo.setPayId(dto.getPayId()); |
|||
queryOrderVo.setPayStatus(getPayStatus(dto.getPayType(), thirdQueryOrderVo.getPayStatus())); |
|||
return queryOrderVo; |
|||
} |
|||
|
|||
/** |
|||
* 通过第三方系统支付状态构建业务系统对应支付状态 |
|||
* @param payType |
|||
* @param thirdPayStatus |
|||
* @return |
|||
*/ |
|||
private Integer getPayStatus(String payType,String thirdPayStatus){ |
|||
EnumPayType enumPayType = EnumPayType.getEnumPayTypeByType(payType); |
|||
switch (enumPayType){ |
|||
case KS_PAY: |
|||
EnumPayStatus enumPayStatusKs = EnumKsPayStatus.getEnumPayStatusByStatus(thirdPayStatus); |
|||
return enumPayStatusKs.getStatus(); |
|||
case WX_PAY: |
|||
EnumPayStatus enumPayStatusWx = EnumWxPayStatus.getEnumPayStatusByStatus(thirdPayStatus); |
|||
return enumPayStatusWx.getStatus(); |
|||
case DY_PAY: |
|||
EnumPayStatus enumPayStatusDy = EnumDyPayStatus.getEnumPayStatusByStatus(thirdPayStatus); |
|||
return enumPayStatusDy.getStatus(); |
|||
case ALI_PAY: |
|||
|
|||
default: |
|||
throw new ServiceException("payType 参数参数传递错误"); |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,131 @@ |
|||
package com.bnyer.pay.utils; |
|||
|
|||
|
|||
import org.apache.commons.lang3.StringUtils; |
|||
|
|||
import java.math.BigDecimal; |
|||
import java.text.DecimalFormat; |
|||
|
|||
public class MoneyUtil { |
|||
|
|||
/** |
|||
* 费用:元TO元 |
|||
* 四舍五入,保留2位小数 |
|||
* 正常情况用不到,但是如果传入的不合规范的超长小数点,则需要规范小数:例如12.26999999999998 |
|||
* @param yuan |
|||
* @return |
|||
*/ |
|||
public static String yuanToYuan(String yuan){ |
|||
return yuanToYuan(yuan,false); |
|||
} |
|||
|
|||
/** |
|||
* 费用:元TO元 |
|||
* 四舍五入,保留2位小数 |
|||
* 正常情况用不到,但是如果传入的不合规范的超长小数点,则需要规范小数:例如12.26999999999998 |
|||
* @param yuan |
|||
* @param returnZeroFlag |
|||
* @return |
|||
*/ |
|||
public static String yuanToYuan(String yuan,boolean returnZeroFlag){ |
|||
String ret = "0"; |
|||
if(StringUtils.isNotBlank(yuan)){ |
|||
try{ |
|||
DecimalFormat df = new DecimalFormat("0.00"); |
|||
ret = df.format(Float.valueOf(yuan)); |
|||
}catch(Exception e){} |
|||
}else{ |
|||
if(returnZeroFlag) {//空的时候是否返回0
|
|||
return ret; |
|||
}else{ |
|||
return yuan; |
|||
} |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
/** |
|||
* 费用:元TO分 |
|||
* @return |
|||
*/ |
|||
public static String yuanToFen(String yuan){ |
|||
return yuanToFen(yuan,false); |
|||
} |
|||
|
|||
/** |
|||
* |
|||
* @param yuan |
|||
* @param returnZeroFlag 入参空的是或否是否返回0 |
|||
* @return |
|||
*/ |
|||
public static String yuanToFen(String yuan,boolean returnZeroFlag){ |
|||
String ret = "0"; |
|||
if(StringUtils.isNotBlank(yuan)){ |
|||
try{ |
|||
|
|||
BigDecimal res = new BigDecimal(yuan).multiply(new BigDecimal(100)); |
|||
DecimalFormat df = new DecimalFormat("0"); |
|||
ret = df.format(res.doubleValue()); |
|||
}catch(Exception e){} |
|||
}else{ |
|||
if(returnZeroFlag) {//空的时候是否返回0
|
|||
return ret; |
|||
}else{ |
|||
return yuan; |
|||
} |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
/** |
|||
* 费用:分TO元 |
|||
* 格式化0.00 表示:比如结果0.50 |
|||
* #.00表示:比如.50 |
|||
* @param fen |
|||
* @return |
|||
*/ |
|||
public static String fenToYuan(String fen){ |
|||
return fenToYuan(fen,false); |
|||
} |
|||
|
|||
/** |
|||
* 费用:分TO元 |
|||
* 格式化0.00 表示:比如结果0.50 |
|||
* #.00表示:比如.50 |
|||
* @param fen |
|||
* @param returnZeroFlag |
|||
* @return |
|||
*/ |
|||
public static String fenToYuan(String fen,boolean returnZeroFlag){ |
|||
String ret = "0.00"; |
|||
if(StringUtils.isNotBlank(fen)){ |
|||
try{ |
|||
BigDecimal res = new BigDecimal(fen).divide(new BigDecimal(100)); |
|||
DecimalFormat df = new DecimalFormat("0.00"); |
|||
ret = df.format(res.doubleValue()); |
|||
|
|||
}catch(Exception e){} |
|||
}else{ |
|||
if(returnZeroFlag){//空的时候是否返回0
|
|||
return ret; |
|||
}else{ |
|||
return fen; |
|||
} |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
public static void main(String[] args) { |
|||
|
|||
String[] yuans = new String[]{ |
|||
"1.01","12.09","123.08","1234.11","12345.99","123456.11","1234567.98","12345678.02","123456789.01","1234567890.55","12345678901.99" |
|||
}; |
|||
for(String yuan : yuans){ |
|||
String fen = yuanToFen(yuan); |
|||
System.out.println(yuan+"元转分"+fen); |
|||
System.out.println(fen+"分转元"+fenToYuan(fen)); |
|||
} |
|||
|
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
package com.bnyer.pay.vo; |
|||
|
|||
import lombok.AllArgsConstructor; |
|||
import lombok.Getter; |
|||
import lombok.NoArgsConstructor; |
|||
import lombok.Setter; |
|||
|
|||
/** |
|||
* @author :WXC |
|||
* @Date :2023/05/05 |
|||
* @description : |
|||
*/ |
|||
@Getter |
|||
@Setter |
|||
@NoArgsConstructor |
|||
@AllArgsConstructor |
|||
public class PayInfoDetailsVo extends PayInfoVo { |
|||
|
|||
} |
|||
@ -0,0 +1,86 @@ |
|||
package com.bnyer.pay.vo; |
|||
|
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.AllArgsConstructor; |
|||
import lombok.Getter; |
|||
import lombok.NoArgsConstructor; |
|||
import lombok.Setter; |
|||
|
|||
import java.math.BigDecimal; |
|||
import java.util.Date; |
|||
|
|||
/** |
|||
* @author :WXC |
|||
* @Date :2023/05/05 |
|||
* @description : |
|||
*/ |
|||
@Getter |
|||
@Setter |
|||
@NoArgsConstructor |
|||
@AllArgsConstructor |
|||
public class PayInfoVo { |
|||
|
|||
@ApiModelProperty(value="支付单号(内部生成)") |
|||
private String payId; |
|||
|
|||
@ApiModelProperty(value="业务主订单号:关联内部业务订单表") |
|||
private String orderNo; |
|||
|
|||
@ApiModelProperty(value="支付状态:1000未支付;1001支付成功 ;1002支付失败") |
|||
private Integer payStatus; |
|||
|
|||
@ApiModelProperty(value="单笔对账状态:1001 对账成功") |
|||
private Integer singleStatus; |
|||
|
|||
@ApiModelProperty(value="单笔对账时间") |
|||
private Date singleTime; |
|||
|
|||
@ApiModelProperty(value="支付类型:wxpay/alipay/kspay/dypay") |
|||
private String payType; |
|||
|
|||
@ApiModelProperty(value="支付渠道:wxpay/alipay") |
|||
private String payChannel; |
|||
|
|||
@ApiModelProperty(value = "交易类型:JSAPI等") |
|||
private String tradeType; |
|||
|
|||
@ApiModelProperty(value="支付单号(第三方返回)") |
|||
private String payNo; |
|||
|
|||
@ApiModelProperty(value="用户侧订单号(第三方返回)") |
|||
private String tradeNo; |
|||
|
|||
@ApiModelProperty(value="appid") |
|||
private String appid; |
|||
|
|||
@ApiModelProperty(value="商品标题") |
|||
private String goodsSubject; |
|||
|
|||
@ApiModelProperty(value="商品描述") |
|||
private String goodsDesc; |
|||
|
|||
@ApiModelProperty(value="支付金额,单位元") |
|||
private BigDecimal payAmount; |
|||
|
|||
@ApiModelProperty(value="支付时间") |
|||
private Date payTime; |
|||
|
|||
@ApiModelProperty(value="支付场景:1.会员充值") |
|||
private Integer sceneCode; |
|||
|
|||
@ApiModelProperty(value="用户ip") |
|||
private String ip; |
|||
|
|||
@ApiModelProperty(value="调用第三方下单返回") |
|||
private String thirdCode; |
|||
|
|||
@ApiModelProperty(value="调用第三方下单返回") |
|||
private String thirdMsg; |
|||
|
|||
@ApiModelProperty(value="调用第三方下单返回") |
|||
private String thirdNo; |
|||
|
|||
@ApiModelProperty(value="备注") |
|||
private String remark; |
|||
|
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
package com.bnyer.pay.vo; |
|||
|
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.Getter; |
|||
import lombok.NoArgsConstructor; |
|||
import lombok.Setter; |
|||
|
|||
/** |
|||
* @author :WXC |
|||
* @Date :2023/05/05 |
|||
* @description : |
|||
*/ |
|||
@Getter |
|||
@Setter |
|||
@NoArgsConstructor |
|||
public class QueryOrderVo { |
|||
@ApiModelProperty(value="内部支付单号") |
|||
private String payId; |
|||
|
|||
@ApiModelProperty(value = "支付状态:1000未支付;1001支付成功 ;1002支付失败") |
|||
private Integer payStatus; |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
package com.bnyer.pay.vo; |
|||
|
|||
import lombok.Getter; |
|||
import lombok.NoArgsConstructor; |
|||
import lombok.Setter; |
|||
|
|||
/** |
|||
* @author :WXC |
|||
* @Date :2023/05/05 |
|||
* @description : |
|||
*/ |
|||
@Getter |
|||
@Setter |
|||
@NoArgsConstructor |
|||
public class ThirdQueryOrderVo { |
|||
//开发者下单单号
|
|||
private String outOrderNo; |
|||
/** |
|||
* 快手取值:PROCESSING-处理中|SUCCESS-成功|FAILED-失败 TIMEOUT-超时 |
|||
* 抖音取值:SUCCESS:成功 TIMEOUT:超时未支付 PROCESSING:处理中 FAIL:失败 |
|||
* 微信取值:SUCCESS—支付成功,REFUND—转入退款,NOTPAY—未支付,CLOSED—已关闭,REVOKED—已撤销(刷卡支付),USERPAYING--用户支付中,PAYERROR--支付失败(其他原因,如银行返回失败) |
|||
* 支付宝取值: |
|||
*/ |
|||
private String payStatus; |
|||
//预下单用户支付金额:单位统一成元
|
|||
private String totalAmount; |
|||
//订单支付时间,统一处理为yyyy-MM-dd HH:mm:ss
|
|||
private String payTime; |
|||
//快手支付渠道。取值:UNKNOWN - 未知|WECHAT-微信 |ALIPAY-支付宝。(注:如果用户还未支付,这里返回的是UNKNOWN.)
|
|||
private String ksPayChannel; |
|||
//抖音支付渠道
|
|||
private Integer dyPayChannel; |
|||
//第三方平台订单号:抖音快手平台订单号
|
|||
private String thirdOrderNo; |
|||
//开发者回传的订单同步状态
|
|||
private String orderStatus; |
|||
//订单对应的用户openid
|
|||
private String openId; |
|||
//支付渠道侧的支付单号
|
|||
private String channelNo; |
|||
|
|||
} |
|||
Loading…
Reference in new issue