添加国赛购买流程

This commit is contained in:
joylink_zhangsai 2021-01-29 17:49:11 +08:00
parent 917705eea8
commit cf5e1238d7
38 changed files with 1078 additions and 305 deletions

View File

@ -0,0 +1,3 @@
alter table sale_order
add transaction_id varchar(32) null comment '支付平台订单号';

View File

@ -48,6 +48,8 @@ public class WebConfig implements WebMvcConfigurer {
whiteList.add("/api/rpTools/**");
whiteList.add("/api/license/validate");
whiteList.add("/api/license/local");
// 微信回调接口
whiteList.add("/api/wechatPay/receive");
registry.addInterceptor(authenticateInterceptor).excludePathPatterns(whiteList);
}

View File

@ -1,5 +1,8 @@
package club.joylink.rtss.constants;
import lombok.Getter;
@Getter
public enum SaleOrderPayWaysEnum {
Offline("01", "线下"),
Alipay("02", "支付宝"),

View File

@ -1,6 +1,7 @@
package club.joylink.rtss.controller.advice;
import club.joylink.rtss.exception.BusinessException;
import club.joylink.rtss.exception.PayException;
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
import club.joylink.rtss.vo.CommonJsonResponse;
import club.joylink.rtss.vo.ResponseConsts;
@ -15,6 +16,7 @@ import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.util.List;
@ -50,7 +52,14 @@ public class CommonResponseBody implements ResponseBodyAdvice {
return commonJsonResponse;
}
@ExceptionHandler(Exception.class)
@ExceptionHandler({PayException.class})
@ResponseStatus
public CommonJsonResponse handleException(PayException e) {
log.error("【支付异常】", e);
return CommonJsonResponse.newErrorResponse();
}
@ExceptionHandler({Exception.class})
@ResponseBody
public CommonJsonResponse handleException(Exception e) {
if(e instanceof MethodArgumentNotValidException) {

View File

@ -11,6 +11,7 @@ import club.joylink.rtss.vo.client.competition.CompetitionPagedQueryVO;
import club.joylink.rtss.vo.client.competition.CompetitionResult;
import club.joylink.rtss.vo.client.competition.CompetitionVO;
import club.joylink.rtss.vo.client.competition.OperationStatisticVO;
import club.joylink.rtss.vo.client.pay.WxPayUnifiedOrderResultVO;
import club.joylink.rtss.vo.client.userPermission.UserPermissionVO;
import club.joylink.rtss.vo.client.validGroup.competition.CompetitionUpdateCheck;
import club.joylink.rtss.vo.view.OperationStatisticAnswerView;
@ -97,8 +98,8 @@ public class CompetitionPracticalController {
@ApiOperation("购买权限")
@PostMapping("/purchasePermission")
public String purchasePermission(Long mapId, Long amount, @RequestAttribute UserVO user) {
return iCompetitionPracticalService.purchasePermission(mapId, amount, user);
public WxPayUnifiedOrderResultVO purchasePermission(Long mapId, Integer monthAmount, @RequestAttribute UserVO user) {
return iCompetitionPracticalService.purchasePermission(mapId, monthAmount, user);
}
/* ------------------------- 竞赛运行相关 ------------------------- */

View File

@ -3,10 +3,7 @@ package club.joylink.rtss.controller.pay;
import club.joylink.rtss.services.pay.wechat.WechatPayService;
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 org.springframework.web.bind.annotation.*;
@Slf4j
@RestController
@ -16,9 +13,20 @@ public class WechatPayController {
@Autowired
private WechatPayService wechatPayService;
/**
* 微信支付回调接口
* @param data 数据主体
* @param signatureStr 签名
* @param timestamp 用于验签
* @param nonce 用于验签
* @param serial 平台证书序列号如果与商户所持的平台证书序列号不一致需更新证书
*/
@PostMapping("/receive")
public void receive(@RequestBody String data) {
public void receive(@RequestBody String data, @RequestHeader("Wechatpay-Signature") String signatureStr,
@RequestHeader("Wechatpay-Timestamp") String timestamp,
@RequestHeader("Wechatpay-Nonce") String nonce,
@RequestHeader("Wechatpay-Serial") String serial) {
log.info(String.format("微信回调信息:%s", data));
wechatPayService.receive(data);
wechatPayService.receive(data, signatureStr, timestamp, nonce, serial);
}
}

View File

@ -49,87 +49,28 @@ public class OrderController {
// -----------未完成接口------------
@ApiOperation(value = "订单支付")
@GetMapping(path = "/{id}/{payType}/pay")
public String pay(@PathVariable long id, @PathVariable String payType) {
return this.iOrderService.pay(id, payType);
}
@ApiOperation(value = "订单提交")
@PostMapping(path = "/submit")
public OrderCreateVO submit(@RequestBody OrderCreateVO orderCreateVO, @RequestAttribute UserVO user) {
return this.iOrderService.submit(orderCreateVO, user);
}
@ApiOperation(value = "计算订单总价")
@GetMapping(path = "/price")
public Float computeTotal(Long goodsId, Integer goodsAmount, Integer monthAmount) {
return this.iOrderService.compute(goodsId, goodsAmount, monthAmount);
}
@ApiOperation(value = "订单取消支付")
@PutMapping(path = "/{id}/cancelPay")
public void cancelPay(@PathVariable Long id, @RequestAttribute UserVO user) {
this.iOrderService.cancelPay(id, user);
}
/*
@ApiOperation(value = "创建订单")
@PostMapping(path="")
public void createOrder(@RequestBody @Validated OrderCreateVO order, @RequestAttribute @ApiIgnore UserVO user) {
this.iOrderService.createOrder(order, user);
}
*/
/**
* 快速生成订单
* @param order
* @param user
* @return 返回生成的订单id
*//*
@PostMapping(path = "/quicklyGenerateOrder")
public String quicklyGenerateOrder(@RequestBody OrderJsonVO order,@RequestAttribute UserVO user){
return this.iOrderService.quicklyGenerateOrder(order,user);
}
@ApiOperation(value = "计算订单总价")
@GetMapping(path = "/price")
public Float computeTotal(Long goodsId, Integer goodsAmount, Integer monthAmount) {
return this.iOrderService.compute(goodsId, goodsAmount, monthAmount);
}
@ApiOperation(value = "订单提交")
@PostMapping(path = "/submit")
public OrderCreateVO submit(@RequestBody OrderCreateVO orderCreateVO, @RequestAttribute UserVO user) {
return this.iOrderService.submit(orderCreateVO, user);
}
@ApiOperation(value = "订单支付")
@GetMapping(path = "/{id}/{payType}/pay")
public String pay(@PathVariable long id, @PathVariable String payType) {
return this.iOrderService.pay(id, payType);
}
// @ApiOperation(value = "订单支付完成,为用户生成权限,测试分发权限使用,先数据库修改订单状态")
// @GetMapping(path = "/{code}/{totalfee}/completePay")
// public SaleOrder completePay(@PathVariable String code,@PathVariable int totalfee) throws PayException {
// return this.iOrderService.completePay(code,totalfee,"03");
// @ApiOperation(value = "订单支付")
// @GetMapping(path = "/{id}/{payType}/pay")
// public String pay(@PathVariable long id, @PathVariable String payType) {
// return this.iOrderService.pay(id, payType, null);
// }
@ApiOperation(value = "订单提交")
@PostMapping(path = "/submit")
public OrderCreateVO submit(@RequestBody OrderCreateVO orderCreateVO, @RequestAttribute UserVO user) {
return this.iOrderService.submit(orderCreateVO, user);
}
@ApiOperation(value = "计算订单总价")
@GetMapping(path = "/price")
public Float computeTotal(Long goodsId, Integer goodsAmount, Integer monthAmount) {
return this.iOrderService.compute(goodsId, goodsAmount, monthAmount);
}
@ApiOperation(value = "订单取消支付")
@PutMapping(path = "/{id}/cancelPay")
public void cancelPay(@PathVariable Long id, @RequestAttribute UserVO user) {
this.iOrderService.cancelPay(id, user);
}
@ApiOperation(value = "查询订单")
@GetMapping(path = "/{id}")
public OrderCreateVO get(@PathVariable long id) {
return this.iOrderService.get(id);
}
*/
}

View File

@ -37,7 +37,7 @@ public class UserPermissionController {
@ApiOperation(value = "获取用户可以分发的权限")
@GetMapping(path="/getAvailableUserPermission")
public List<UserPermissionVO> findAvailablePermission(DistributeSelectVO distributeSelectVO, @RequestAttribute @ApiIgnore UserVO user) {
return this.iUserPermissionService.findUserPermissionVOListThatCanDistribute(distributeSelectVO,user);
return this.iUserPermissionService.queryUserPermissionVOListThatCanDistribute(distributeSelectVO,user);
}
@ApiOperation(value = "分页获取个人权限数据")

View File

@ -4,8 +4,8 @@ import java.io.Serializable;
import java.time.LocalDateTime;
/**
* sale_order
* @author
* 订单
*/
public class SaleOrder implements Serializable {
private Long id;
@ -77,6 +77,11 @@ public class SaleOrder implements Serializable {
*/
private Long sellerId;
/**
* 支付平台订单号
*/
private String transactionId;
private static final long serialVersionUID = 1L;
public Long getId() {
@ -199,6 +204,14 @@ public class SaleOrder implements Serializable {
this.sellerId = sellerId;
}
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
@Override
public boolean equals(Object that) {
if (this == that) {
@ -225,7 +238,8 @@ public class SaleOrder implements Serializable {
&& (this.getUpdateUserId() == null ? other.getUpdateUserId() == null : this.getUpdateUserId().equals(other.getUpdateUserId()))
&& (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime()))
&& (this.getQrCodeGenerated() == null ? other.getQrCodeGenerated() == null : this.getQrCodeGenerated().equals(other.getQrCodeGenerated()))
&& (this.getSellerId() == null ? other.getSellerId() == null : this.getSellerId().equals(other.getSellerId()));
&& (this.getSellerId() == null ? other.getSellerId() == null : this.getSellerId().equals(other.getSellerId()))
&& (this.getTransactionId() == null ? other.getTransactionId() == null : this.getTransactionId().equals(other.getTransactionId()));
}
@Override
@ -247,6 +261,7 @@ public class SaleOrder implements Serializable {
result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode());
result = prime * result + ((getQrCodeGenerated() == null) ? 0 : getQrCodeGenerated().hashCode());
result = prime * result + ((getSellerId() == null) ? 0 : getSellerId().hashCode());
result = prime * result + ((getTransactionId() == null) ? 0 : getTransactionId().hashCode());
return result;
}
@ -271,6 +286,7 @@ public class SaleOrder implements Serializable {
sb.append(", updateTime=").append(updateTime);
sb.append(", qrCodeGenerated=").append(qrCodeGenerated);
sb.append(", sellerId=").append(sellerId);
sb.append(", transactionId=").append(transactionId);
sb.append(", serialVersionUID=").append(serialVersionUID);
sb.append("]");
return sb.toString();

View File

@ -1084,6 +1084,76 @@ public class SaleOrderExample {
addCriterion("seller_id not between", value1, value2, "sellerId");
return (Criteria) this;
}
public Criteria andTransactionIdIsNull() {
addCriterion("transaction_id is null");
return (Criteria) this;
}
public Criteria andTransactionIdIsNotNull() {
addCriterion("transaction_id is not null");
return (Criteria) this;
}
public Criteria andTransactionIdEqualTo(String value) {
addCriterion("transaction_id =", value, "transactionId");
return (Criteria) this;
}
public Criteria andTransactionIdNotEqualTo(String value) {
addCriterion("transaction_id <>", value, "transactionId");
return (Criteria) this;
}
public Criteria andTransactionIdGreaterThan(String value) {
addCriterion("transaction_id >", value, "transactionId");
return (Criteria) this;
}
public Criteria andTransactionIdGreaterThanOrEqualTo(String value) {
addCriterion("transaction_id >=", value, "transactionId");
return (Criteria) this;
}
public Criteria andTransactionIdLessThan(String value) {
addCriterion("transaction_id <", value, "transactionId");
return (Criteria) this;
}
public Criteria andTransactionIdLessThanOrEqualTo(String value) {
addCriterion("transaction_id <=", value, "transactionId");
return (Criteria) this;
}
public Criteria andTransactionIdLike(String value) {
addCriterion("transaction_id like", value, "transactionId");
return (Criteria) this;
}
public Criteria andTransactionIdNotLike(String value) {
addCriterion("transaction_id not like", value, "transactionId");
return (Criteria) this;
}
public Criteria andTransactionIdIn(List<String> values) {
addCriterion("transaction_id in", values, "transactionId");
return (Criteria) this;
}
public Criteria andTransactionIdNotIn(List<String> values) {
addCriterion("transaction_id not in", values, "transactionId");
return (Criteria) this;
}
public Criteria andTransactionIdBetween(String value1, String value2) {
addCriterion("transaction_id between", value1, value2, "transactionId");
return (Criteria) this;
}
public Criteria andTransactionIdNotBetween(String value1, String value2) {
addCriterion("transaction_id not between", value1, value2, "transactionId");
return (Criteria) this;
}
}
/**

View File

@ -0,0 +1,21 @@
package club.joylink.rtss.event;
import lombok.Getter;
@Getter
public class OrderPaySuccessEvent {
/**
* 订单编号
*/
private String orderCode;
/**
* 用户id
*/
private String userId;
public OrderPaySuccessEvent(String orderCode, String userId) {
this.orderCode = orderCode;
this.userId = userId;
}
}

View File

@ -56,7 +56,8 @@ public enum BusinessExceptionAssertEnum implements BusinessExceptionAssert {
THIRD_SERVICE_CALL_EXCEPTION(40071, "the third service call exception"),
//支付异常
PAY_ERROR(50000, "pay error")
PAY_ERROR(50000, "pay error"),
WECHAT_NOTIFY_ERROR(401, "wechat notify error")
;
int code;

View File

@ -0,0 +1,19 @@
package club.joylink.rtss.exception;
public class PayException extends BaseException {
public PayException(IExceptionMessage exceptionMessage) {
super(exceptionMessage);
}
public PayException(IExceptionMessage exceptionMessage, String message) {
super(exceptionMessage, message);
}
public PayException(IExceptionMessage exceptionMessage, Throwable cause) {
super(exceptionMessage, cause);
}
public PayException(IExceptionMessage exceptionMessage, String message, Throwable cause) {
super(exceptionMessage, message, cause);
}
}

View File

@ -245,6 +245,18 @@ public class GoodsService implements IGoodsService {
return saleGoods.stream().map(GoodsVO::new).collect(Collectors.toList());
}
@Override
public SaleGoods getByPermissionId(Long permissionId) {
SaleGoodsExample example = new SaleGoodsExample();
example.createCriteria().andPermissionIdEqualTo(permissionId);
List<SaleGoods> goodsList = saleGoodsDAO.selectByExample(example);
BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertCollectionNotEmpty(goodsList,
String.format("权限[%s]没有关联的商品", permissionId));
BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertTrue(goodsList.size() == 1,
String.format("权限[%s]关联了多个商品", permissionId));
return goodsList.get(0);
}
public SaleGoods findEntity(Long id) {
return saleGoodsDAO.selectByPrimaryKey(id);
}

View File

@ -1,5 +1,6 @@
package club.joylink.rtss.services;
import club.joylink.rtss.entity.SaleGoods;
import club.joylink.rtss.vo.UserVO;
import club.joylink.rtss.vo.client.GoodsTryVO;
import club.joylink.rtss.vo.client.PageVO;
@ -66,4 +67,9 @@ public interface IGoodsService {
boolean isExist(Long goodsId);
List<GoodsVO> getByPermissionIds(List<Long> permissionIds);
/**
* 根据权限id获取商品
*/
SaleGoods getByPermissionId(Long permissionId);
}

View File

@ -6,6 +6,7 @@ import club.joylink.rtss.vo.client.order.OrderCreateVO;
import club.joylink.rtss.vo.client.order.OrderDetailCreateVO;
import club.joylink.rtss.vo.client.order.OrderDetailVO;
import club.joylink.rtss.vo.client.order.OrderVO;
import club.joylink.rtss.vo.client.pay.WxPayUnifiedOrderResultVO;
import club.joylink.rtss.vo.client.permission.OrderQueryVO;
import java.util.List;
@ -44,11 +45,11 @@ public interface IOrderService {
OrderCreateVO submit(OrderCreateVO orderCreateVO, UserVO user);
String pay(long id, String payType);
WxPayUnifiedOrderResultVO pay(long id, String payType, String description);
void cancelPay(Long id, UserVO user);
OrderVO findByCode(String orderCode);
OrderVO queryByCode(String orderCode);
List<OrderDetailVO> findOrderDetailVOListByOrderId(Long id);
@ -56,4 +57,19 @@ public interface IOrderService {
* 创建 内部分配订单创建对象
*/
OrderCreateVO createInternalOrderCreateVO(Long organizationId, List<OrderDetailCreateVO> orderDetails);
/**
* 根据订单编号获取订单
*/
OrderVO getByCode(String orderCode);
/**
* 完成支付
*/
void finishPay(OrderVO orderVO);
/**
* 记录订单的支付平台订单号
*/
void recordTransactionId(String orderCode, String transactionId);
}

View File

@ -34,7 +34,7 @@ public interface IUserPermissionService {
List<UserPermissionVO> getLessonUserPermission(UserVO userVO, Long mapId, String prdType, Long lessonId);
List<UserPermissionVO> findUserPermissionVOListThatCanDistribute(DistributeSelectVO distributeSelectVO, UserVO user);
List<UserPermissionVO> queryUserPermissionVOListThatCanDistribute(DistributeSelectVO distributeSelectVO, UserVO user);
PageVO<UserPermissionVO> queryMyPermission(UserVO user, PermissionQueryVO queryVO);
@ -46,14 +46,12 @@ public interface IUserPermissionService {
void createUserPermissionFromPermissionDistribute(PermissionDistribute permissionDistribute, UserVO user);
List<UserPermissionVO> findValidByUserIdAndDistributeId(Long userId, Long distributeId);
List<UserPermissionVO> queryValidByUserIdAndDistributeId(Long userId, Long distributeId);
UserPermissionVO getById(Long id);
void updateById(UserPermissionVO upVO);
List<UserPermissionVO> queryByDistribute(Long id);
void restorePermissionToDistribute(Long userPermissionId);
List<UserPermissionVO> findByDistributeIdAndStatus(Long distributeId, StatusEnum status);
@ -65,14 +63,11 @@ public interface IUserPermissionService {
/**
* 使distributeId为此的用户权限失效
* @param distributeId
*/
void invalidateUserPermissionByDistributeId(Long distributeId);
/**
* 获取个人所有用户权限
* @param user
* @return
*/
List<UserPermissionVO> queryPersonalUserPermission(UserVO user);
@ -90,9 +85,13 @@ public interface IUserPermissionService {
/**
* 给该用户领取该地图的权限
* @param mapId
* @param count
* @param user
*/
void getPermissions4Map(Long mapId, Integer count, UserVO user);
/**
* 用户权限延长续费
* @param id 要延长的权限
* @param monthAmount 要延长的月数
*/
void renewal(long id, int monthAmount);
}

View File

@ -10,12 +10,15 @@ import club.joylink.rtss.entity.SaleOrderDetail;
import club.joylink.rtss.entity.SaleOrderDetailExample;
import club.joylink.rtss.entity.SaleOrderExample;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.services.pay.bean.OrderPay;
import club.joylink.rtss.services.pay.wechat.WechatPayService;
import club.joylink.rtss.vo.UserVO;
import club.joylink.rtss.vo.client.PageVO;
import club.joylink.rtss.vo.client.order.OrderCreateVO;
import club.joylink.rtss.vo.client.order.OrderDetailCreateVO;
import club.joylink.rtss.vo.client.order.OrderDetailVO;
import club.joylink.rtss.vo.client.order.OrderVO;
import club.joylink.rtss.vo.client.pay.WxPayUnifiedOrderResultVO;
import club.joylink.rtss.vo.client.permission.OrderQueryVO;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
@ -25,6 +28,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@ -50,6 +54,9 @@ public class OrderService implements IOrderService {
@Autowired
private IOrderNoGenerator iOrderNoGenerator;
@Autowired
private WechatPayService wechatPayService;
@Override
public PageVO<OrderVO> queryPagedOrders(OrderQueryVO queryVO) {
return queryPagedOrders(queryVO, null);
@ -112,93 +119,9 @@ public class OrderService implements IOrderService {
return create(createVO, user);
}
private String create(OrderCreateVO createVO, UserVO user) {
confirmCorrect(createVO);
//新增订单
SaleOrder saleOrder = createVO.convert2DB();
saleOrder.setCode(iOrderNoGenerator.next());
saleOrder.setStatus(BusinessConsts.STATUS_USE);
saleOrder.setCreatorId(user.getId());
saleOrder.setCreateTime(LocalDateTime.now());
saleOrder.setQrCodeGenerated(false);
try {
saleOrderDAO.insertSelective(saleOrder);
} catch (DuplicateKeyException e) {
throw BusinessExceptionAssertEnum.DATA_UNIQUE_PROPERTY_REPEAT.exception("订单编号重复");
}
Long orderId = saleOrder.getId();
//新增订单明细
createVO.getDetailCreateVOList().forEach(detailCreateVO -> {
SaleOrderDetail detail = detailCreateVO.convert2DB();
detail.setOrderId(orderId);
detail.setForever(createVO.getForever());
detail.setMonthAmount(createVO.getMonthAmount());
detail.setStartTime(createVO.getStartTime());
detail.setPrice((long) (iGoodsService.getById(detail.getGoodsId()).getPrice() * 100));
saleOrderDetailDAO.insertSelective(detail);
});
return saleOrder.getCode();
}
/**
* 确认订单参数正确
*/
private void confirmCorrect(OrderCreateVO createVO) {
SaleOrderTypeEnum type = SaleOrderTypeEnum.getSaleOrderTypeByCode(createVO.getOrderType());
switch (type) {
case Business_Contract:
// BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getOrganizationId(), "订单组织/单位不能为空");
// BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getContractNo(), "订单合同号不能为空");
// BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getSellerId(), "订单销售人员不能为空");
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getForever(), "订单是否永久不能不填");
if (createVO.getOrganizationId() != null) {
BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertTrue(iOrganizationService.isExist(createVO.getOrganizationId()),
"没有该组织机构/企业");
}
if (createVO.getContractNo() != null) {
BusinessExceptionAssertEnum.DATA_ALREADY_EXIST.assertTrue(isContractNoExist(createVO.getContractNo()),
String.format("合同编号为[%s]的订单已存在", createVO.getContractNo()));
}
if (!createVO.getForever()) {
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getStartTime(), "非永久订单开始时间不能为空");
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getMonthAmount(), "非永久订单购买时长不能为空");
}
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getPrice(), "订单总价不能为空");
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getPayWays(), "订单支付方式不能为空");
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getPayStatus(), "订单支付状态不能为空");
break;
case Contract_Gift:
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getOrganizationId(), "订单组织/单位不能为空");
break;
}
//公共校验
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertCollectionNotEmpty(createVO.getDetailCreateVOList(),
"订单明细列表不能为空");
if (!createVO.getForever()) {
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getStartTime(),
"非永久的权限必须有开始时间");
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(
createVO.getMonthAmount() != null && createVO.getMonthAmount() > 0,
"非永久的权限月数必须大于0");
}
List<OrderDetailCreateVO> detailCreateVOList = createVO.getDetailCreateVOList();
for (OrderDetailCreateVO detailVO : detailCreateVOList) {
BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertTrue(iGoodsService.isExist(detailVO.getGoodsId()),
String.format("id为[%s]的商品不存在", detailVO.getGoodsId()));
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(
detailVO.getGoodsAmount() != null && detailVO.getGoodsAmount() > 0,
"商品数量至少为1");
}
}
/**
* 更新订单
* 如果要更新的订单不存在报DBException订单不存在
*
* @param orderVO
* @param userVO
*/
@Override
public void update(OrderVO orderVO, UserVO userVO) {
@ -230,8 +153,19 @@ public class OrderService implements IOrderService {
}
@Override
public String pay(long id, String payType) {
return null;
public WxPayUnifiedOrderResultVO pay(long id, String payType, String description) {
SaleOrder order = getEntity(id);
if (!StringUtils.hasText(description)) {
description = "城轨平台权限";
}
OrderPay orderPay = new OrderPay(order, description);
try {
WxPayUnifiedOrderResultVO result = wechatPayService.unifiedOrder(orderPay);
return result;
} catch (IOException e) {
throw BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.exception(String.format("订单[%s]下单失败", orderPay.getOrderNo()));
}
}
@Override
@ -246,7 +180,7 @@ public class OrderService implements IOrderService {
return true;
}
public SaleOrder getById(Long id) {
public SaleOrder getEntity(Long id) {
SaleOrder saleOrder = saleOrderDAO.selectByPrimaryKey(id);
BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertNotNull(saleOrder);
return saleOrder;
@ -262,7 +196,7 @@ public class OrderService implements IOrderService {
return saleOrderDAO.selectByPrimaryKey(id);
}
public OrderVO findByCode(String code) {
public OrderVO queryByCode(String code) {
SaleOrderExample example = new SaleOrderExample();
example.createCriteria()
.andCodeEqualTo(code);
@ -295,4 +229,121 @@ public class OrderService implements IOrderService {
orderCreate.setDetailCreateVOList(orderDetails);
return orderCreate;
}
@Override
public OrderVO getByCode(String orderCode) {
OrderVO orderVO = queryByCode(orderCode);
BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertNotNull(orderVO, String.format("编号为[%s]的订单不存在", orderCode));
return orderVO;
}
@Override
public void finishPay(OrderVO orderVO) {
SaleOrder entity = getEntity(orderVO.getId());
entity.setPayStatus(SaleOrderPayStatusEnum.Paid.getCode());
saleOrderDAO.updateByPrimaryKey(entity);
}
@Override
public void recordTransactionId(String orderCode, String transactionId) {
SaleOrder entity = getEntityByCode(orderCode);
entity.setTransactionId(transactionId);
saleOrderDAO.updateByPrimaryKey(entity);
}
private SaleOrder getEntityByCode(String orderCode) {
SaleOrderExample example = new SaleOrderExample();
example.createCriteria().andCodeEqualTo(orderCode);
List<SaleOrder> orders = saleOrderDAO.selectByExample(example);
BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertCollectionNotEmpty(orders,
String.format("编号[%s]的订单不存在", orderCode));
BusinessExceptionAssertEnum.DATA_ERROR.assertTrue(orders.size() == 1,
String.format("编号[%s]的订单不止一个", orderCode));
return orders.get(0);
}
/**
* 确认订单参数正确
*/
private void confirmCorrect(OrderCreateVO createVO) {
//公共校验
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertCollectionNotEmpty(createVO.getDetailCreateVOList(),
"订单明细列表不能为空");
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getForever(), "订单是否永久不能不填");
if (!createVO.getForever()) {
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getStartTime(),
"非永久的权限必须有开始时间");
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(
createVO.getMonthAmount() != null && createVO.getMonthAmount() > 0,
"非永久的权限月数必须大于0");
}
//分类校验
SaleOrderTypeEnum type = SaleOrderTypeEnum.getSaleOrderTypeByCode(createVO.getOrderType());
switch (type) {
case Individual:
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getPrice(), "个人订单价格不能为空");
case Business_Contract:
// BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getOrganizationId(), "订单组织/单位不能为空");
// BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getContractNo(), "订单合同号不能为空");
// BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getSellerId(), "订单销售人员不能为空");
if (createVO.getOrganizationId() != null) {
BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertTrue(iOrganizationService.isExist(createVO.getOrganizationId()),
"没有该组织机构/企业");
}
if (createVO.getContractNo() != null) {
BusinessExceptionAssertEnum.DATA_ALREADY_EXIST.assertTrue(isContractNoExist(createVO.getContractNo()),
String.format("合同编号为[%s]的订单已存在", createVO.getContractNo()));
}
if (!createVO.getForever()) {
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getStartTime(), "非永久订单开始时间不能为空");
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getMonthAmount(), "非永久订单购买时长不能为空");
}
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getPrice(), "订单总价不能为空");
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getPayWays(), "订单支付方式不能为空");
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getPayStatus(), "订单支付状态不能为空");
break;
case Contract_Gift:
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(createVO.getOrganizationId(), "订单组织/单位不能为空");
break;
}
List<OrderDetailCreateVO> detailCreateVOList = createVO.getDetailCreateVOList();
for (OrderDetailCreateVO detailVO : detailCreateVOList) {
BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertTrue(iGoodsService.isExist(detailVO.getGoodsId()),
String.format("id为[%s]的商品不存在", detailVO.getGoodsId()));
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(
detailVO.getGoodsAmount() != null && detailVO.getGoodsAmount() > 0,
"商品数量至少为1");
}
}
private String create(OrderCreateVO createVO, UserVO user) {
confirmCorrect(createVO);
//新增订单
SaleOrder saleOrder = createVO.convert2DB();
saleOrder.setCode(iOrderNoGenerator.next());
saleOrder.setStatus(BusinessConsts.STATUS_USE);
saleOrder.setCreatorId(user.getId());
saleOrder.setCreateTime(LocalDateTime.now());
saleOrder.setQrCodeGenerated(false);
try {
saleOrderDAO.insertSelective(saleOrder);
} catch (DuplicateKeyException e) {
throw BusinessExceptionAssertEnum.DATA_UNIQUE_PROPERTY_REPEAT.exception("订单编号重复");
}
Long orderId = saleOrder.getId();
//新增订单明细
createVO.getDetailCreateVOList().forEach(detailCreateVO -> {
SaleOrderDetail detail = detailCreateVO.convert2DB();
detail.setOrderId(orderId);
detail.setForever(createVO.getForever());
detail.setMonthAmount(createVO.getMonthAmount());
detail.setStartTime(createVO.getStartTime());
detail.setPrice((long) (iGoodsService.getById(detail.getGoodsId()).getPrice() * 100));
saleOrderDetailDAO.insertSelective(detail);
});
return saleOrder.getCode();
}
}

View File

@ -180,7 +180,7 @@ public class PermissionDistributeService implements IPermissionDistributeService
@Transactional
public String distributeFromOrder(String orderCode, UserVO user) {
//校验
OrderVO order = iOrderService.findByCode(orderCode);
OrderVO order = iOrderService.queryByCode(orderCode);
BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertNotNull(order);
Long permissionDistributeId;
@ -239,13 +239,13 @@ public class PermissionDistributeService implements IPermissionDistributeService
* 领取权限
* 如果权限分发不存在报DBException数据不存在
*
* @param state 权限分发id
* @param id 权限分发id
* @param user 要获取权限的用户
*/
@Override
@Transactional
public void getUserPermission(Long state, UserVO user) {
PermissionDistribute distribute = getEntityById(state);
public void getUserPermission(Long id, UserVO user) {
PermissionDistribute distribute = getEntityById(id);
canReceiveValid(distribute, user);
if (distribute.getIsPackage()) {
List<PermissionDistribute> permissionDistributeList = getEntityByParentId(distribute.getId());
@ -309,7 +309,7 @@ public class PermissionDistributeService implements IPermissionDistributeService
public List<UserPermissionVO> wmGetPermission(String code, Long id) {
UserVO userVO = this.iAuthenticateService.getOrCreateUserByWmcode(code);
this.getUserPermission(id, userVO);
List<UserPermissionVO> voList = iUserPermissionService.findValidByUserIdAndDistributeId(userVO.getId(), id);
List<UserPermissionVO> voList = iUserPermissionService.queryValidByUserIdAndDistributeId(userVO.getId(), id);
return voList;
}

View File

@ -128,7 +128,7 @@ public class UserPermissionService implements IUserPermissionService {
* @return
*/
@Override
public List<UserPermissionVO> findUserPermissionVOListThatCanDistribute(DistributeSelectVO paramVO, UserVO user) {
public List<UserPermissionVO> queryUserPermissionVOListThatCanDistribute(DistributeSelectVO paramVO, UserVO user) {
// Permission permission = permissionService.getTeachPermissionByMapId(distributeParamVO.getMapId());
PermissionTypeEnum type = PermissionTypeEnum.getPermissionTypeByCode(paramVO.getType());
List<UserPermissionVO> voList1 = null;
@ -338,17 +338,6 @@ public class UserPermissionService implements IUserPermissionService {
return userPermissionDAO.selectByExample(example);
}
public List<UserPermissionVO> findByPermissionIdAndUserId(Long permissionId, Long userId) {
UserPermissionExample example = new UserPermissionExample();
example.createCriteria()
.andStatusEqualTo(StatusEnum.Valid.getCode())
.andPermissionIdEqualTo(permissionId)
.andUserIdEqualTo(userId);
List<UserPermission> userPermissionList = userPermissionDAO.selectByExample(example);
List<UserPermissionVO> voList = UserPermissionVO.convert2VOList(userPermissionList);
return voList;
}
/**
* 从权限分发创建用户权限
*
@ -383,16 +372,6 @@ public class UserPermissionService implements IUserPermissionService {
userPermissionDAO.updateByPrimaryKeySelective(userPermission);
}
@Override
public List<UserPermissionVO> queryByDistribute(Long distributeId) {
UserPermissionExample example = new UserPermissionExample();
example.createCriteria()
.andDistributeIdEqualTo(distributeId)
.andStatusEqualTo(StatusEnum.Valid.getCode());
List<UserPermission> list = this.userPermissionDAO.selectByExample(example);
return UserPermissionVO.convert2VOList(list);
}
/**
* 通过用户id和权限分发id获取用户权限列表
*
@ -401,7 +380,7 @@ public class UserPermissionService implements IUserPermissionService {
* @return
*/
@Override
public List<UserPermissionVO> findValidByUserIdAndDistributeId(Long userId, Long distributeId) {
public List<UserPermissionVO> queryValidByUserIdAndDistributeId(Long userId, Long distributeId) {
DistributeVO distribute = iPermissionDistributeService.getById(distributeId);
UserPermissionExample example = new UserPermissionExample();
if (distribute.getIsPackage()) {
@ -423,18 +402,6 @@ public class UserPermissionService implements IUserPermissionService {
return voList;
}
/**
* 通过mapId和userId查询该用户关于这张地图的综合演练权限的用户权限
*
* @param mapId
* @param userId
* @return
*/
public List<UserPermissionVO> findJointUserPermissionByMapIdAndUserId(Long mapId, Long userId) {
PermissionVO permission = iPermissionService.getJointSimulationPermissionByMapId(mapId);
return this.findByPermissionIdAndUserId(permission.getId(), userId);
}
@Transactional
@Override
public void restorePermissionToDistribute(Long userPermissionId) {
@ -536,6 +503,13 @@ public class UserPermissionService implements IUserPermissionService {
iPermissionDistributeService.getUserPermission(distributeId, user);
}
@Override
public void renewal(long id, int monthAmount) {
UserPermission entity = getEntityById(id);
entity.setEndTime(entity.getEndTime().plusMonths(monthAmount));
userPermissionDAO.updateByPrimaryKey(entity);
}
private List<UserPermissionVO> findByUserId(Long userId) {
UserPermissionExample example = new UserPermissionExample();
example.createCriteria().andUserIdEqualTo(userId);

View File

@ -1,18 +1,11 @@
package club.joylink.rtss.services.completition;
import club.joylink.rtss.constants.MapPrdTypeEnum;
import club.joylink.rtss.constants.Project;
import club.joylink.rtss.constants.*;
import club.joylink.rtss.dao.CompetitionDAO;
import club.joylink.rtss.dao.CompetitionRecordDAO;
import club.joylink.rtss.entity.Competition;
import club.joylink.rtss.entity.CompetitionExample;
import club.joylink.rtss.entity.CompetitionRecord;
import club.joylink.rtss.entity.CompetitionWithBLOBs;
import club.joylink.rtss.entity.*;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.services.IGoodsService;
import club.joylink.rtss.services.IOrderService;
import club.joylink.rtss.services.IPermissionService;
import club.joylink.rtss.services.IUserPermissionService;
import club.joylink.rtss.services.*;
import club.joylink.rtss.services.script.IScriptService;
import club.joylink.rtss.services.script.IScriptSimulationService;
import club.joylink.rtss.services.simulation.ProjectSimulationService;
@ -32,6 +25,12 @@ import club.joylink.rtss.vo.LoginUserInfoVO;
import club.joylink.rtss.vo.UserVO;
import club.joylink.rtss.vo.client.PageVO;
import club.joylink.rtss.vo.client.competition.*;
import club.joylink.rtss.vo.client.map.MapVO;
import club.joylink.rtss.vo.client.order.OrderCreateVO;
import club.joylink.rtss.vo.client.order.OrderDetailCreateVO;
import club.joylink.rtss.vo.client.order.OrderVO;
import club.joylink.rtss.vo.client.pay.WxPayUnifiedOrderResultVO;
import club.joylink.rtss.vo.client.permission.PermissionVO;
import club.joylink.rtss.vo.client.script.ScriptActionVO;
import club.joylink.rtss.vo.client.script.ScriptVO;
import club.joylink.rtss.vo.client.userPermission.UserPermissionVO;
@ -93,6 +92,9 @@ public class CompetitionPracticalService implements ICompetitionPracticalService
@Autowired
private IOrderService iOrderService;
@Autowired
private IMapService iMapService;
@Override
public PageVO<CompetitionVO> pagedQueryCompetition(CompetitionPagedQueryVO queryVO) {
PageHelper.startPage(queryVO.getPageNum(), queryVO.getPageSize());
@ -399,25 +401,54 @@ public class CompetitionPracticalService implements ICompetitionPracticalService
Optional<UserPermissionVO> optional = permissions.stream()
.filter(up -> up.getRemains() > 0 && !up.getStartTime().isAfter(now) && (up.getEndTime() == null || !up.getEndTime().isBefore(now)))
.max((o1, o2) -> {
if (o1.getEndTime().isAfter(o2.getEndTime())) {
if (o1.getEndTime() == null) {
return 1;
} else if (o2.getEndTime().isAfter(o1.getEndTime())) {
} else if (o2.getEndTime() == null) {
return -1;
} else {
return 0;
if (o1.getEndTime().isAfter(o2.getEndTime())) {
return 1;
} else if (o2.getEndTime().isAfter(o1.getEndTime())) {
return -1;
} else {
return 0;
}
}
});
return optional.orElse(null);
}
@Override
public String purchasePermission(Long mapId, Long amount, UserVO user) {
// PermissionVO jointPermission = iPermissionService.getJointSimulationPermissionByMapId(mapId);
// GoodsVO goods = iGoodsService.queryGoodsByPermissionId(jointPermission.getId());
// OrderCreateVO orderCreateVO = new OrderCreateVO();
// orderCreateVO.setOrganizationId();
// iOrderService.createOrder()
return "待实现";
public WxPayUnifiedOrderResultVO purchasePermission(Long mapId, Integer monthAmount, UserVO user) {
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertTrue(monthAmount > 0,
"购买月数需大于0");
MapVO mapInfo = iMapService.getMapInfoById(mapId);
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertTrue(Project.DRTS.name().equals(mapInfo.getProjectCode()),
"非国赛地图无需购买权限");
List<UserPermissionVO> ups = iUserPermissionService.getSimulationUserPermission(user, mapId, MapPrdTypeEnum.JOINT.getCode());
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(ups.size() > 1,
"地图权限数量大于1暂不能购买");
if (ups.size() == 1) {
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(ups.get(0).getAmount() > 1,
"地图权限数量大于1暂不能购买");
}
PermissionVO permission = iPermissionService.getJointSimulationPermissionByMapId(mapId);
SaleGoods goods = iGoodsService.getByPermissionId(permission.getId());
//创建订单
OrderCreateVO orderCreate = new OrderCreateVO();
orderCreate.setPrice(0.01f * monthAmount);
orderCreate.setPayWays(SaleOrderPayWaysEnum.Wechat.getCode());
orderCreate.setPayStatus(SaleOrderPayStatusEnum.Unpaid.getCode());
orderCreate.setOrderType(SaleOrderTypeEnum.Individual.getCode());
orderCreate.setForever(false);
orderCreate.setStartTime(LocalDateTime.now());
orderCreate.setMonthAmount(monthAmount);
orderCreate.setDetailCreateVOList(List.of(new OrderDetailCreateVO(goods.getId(), 1)));
String orderCode = iOrderService.createOrder(orderCreate, user);
//下单
OrderVO order = iOrderService.getByCode(orderCode);
return iOrderService.pay(order.getId(), null, "调度大赛权限");
}
/**

View File

@ -9,6 +9,7 @@ import club.joylink.rtss.vo.client.competition.CompetitionPagedQueryVO;
import club.joylink.rtss.vo.client.competition.CompetitionResult;
import club.joylink.rtss.vo.client.competition.CompetitionVO;
import club.joylink.rtss.vo.client.competition.OperationStatisticVO;
import club.joylink.rtss.vo.client.pay.WxPayUnifiedOrderResultVO;
import club.joylink.rtss.vo.client.userPermission.UserPermissionVO;
import java.util.List;
@ -117,7 +118,9 @@ public interface ICompetitionPracticalService {
/**
* 购买权限
* @param mapId
* @param amount 购买数量单位为月
* @return
*/
String purchasePermission(Long mapId, Long amount, UserVO user);
WxPayUnifiedOrderResultVO purchasePermission(Long mapId, Integer amount, UserVO user);
}

View File

@ -1,7 +1,9 @@
package club.joylink.rtss.services.pay.bean;
import club.joylink.rtss.entity.SaleOrder;
import club.joylink.rtss.vo.client.order.OrderDetailVO;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.time.OffsetDateTime;
@ -9,6 +11,7 @@ import java.util.List;
@Getter
@Setter
@NoArgsConstructor
public class OrderPay {
/**
@ -36,4 +39,10 @@ public class OrderPay {
*/
private List<OrderDetailVO> orderDetail;
public OrderPay(SaleOrder order, String description) {
this.orderNo = order.getCode();
this.description = description;
this.totalFee = order.getPrice().intValue();
this.timeExpire = OffsetDateTime.now().plusMinutes(10);
}
}

View File

@ -1,12 +1,27 @@
package club.joylink.rtss.services.pay.wechat;
import club.joylink.rtss.constants.MapPrdTypeEnum;
import club.joylink.rtss.constants.Project;
import club.joylink.rtss.event.OrderPaySuccessEvent;
import club.joylink.rtss.exception.BusinessException;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.services.IOrderService;
import club.joylink.rtss.exception.PayException;
import club.joylink.rtss.services.*;
import club.joylink.rtss.services.pay.bean.OrderPay;
import club.joylink.rtss.services.pay.wechat.bean.WxUnifiedOrder;
import club.joylink.rtss.util.JsonUtils;
import club.joylink.rtss.vo.UserVO;
import club.joylink.rtss.vo.client.goods.GoodsVO;
import club.joylink.rtss.vo.client.map.MapVO;
import club.joylink.rtss.vo.client.order.OrderDetailVO;
import club.joylink.rtss.websocket.StompMessageService;
import club.joylink.rtss.vo.client.order.OrderVO;
import club.joylink.rtss.vo.client.pay.WxPayNotifyData;
import club.joylink.rtss.vo.client.pay.WxPayNotifyRespondVO;
import club.joylink.rtss.vo.client.pay.WxPayNotifyVO;
import club.joylink.rtss.vo.client.pay.WxPayUnifiedOrderResultVO;
import club.joylink.rtss.vo.client.permission.PermissionVO;
import club.joylink.rtss.vo.client.permissionDistribute.DistributeVO;
import club.joylink.rtss.vo.client.userPermission.UserPermissionVO;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
@ -15,18 +30,26 @@ import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.PrivateKey;
import java.time.OffsetDateTime;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;
import java.util.List;
import static club.joylink.rtss.services.pay.wechat.constant.WechatConstants.*;
@ -36,20 +59,44 @@ import static club.joylink.rtss.services.pay.wechat.constant.WechatConstants.*;
public class WechatPayService {
@Autowired
private IOrderService iorderService;
private IOrderService iOrderService;
@Autowired
private StompMessageService stompMessageService;
private IGoodsService iGoodsService;
@Autowired
private ApplicationContext applicationContext;
@Autowired
private ISysUserService iSysUserService;
@Autowired
private IUserPermissionService iUserPermissionService;
@Autowired
private IPermissionService iPermissionService;
@Autowired
private IMapService iMapService;
@Autowired
private IPermissionDistributeService iPermissionDistributeService;
private CloseableHttpClient httpClient;
private AutoUpdateCertificatesVerifier verifier;
static final int TAG_LENGTH_BIT = 128;
private static final byte[] aesKey = APIV3_KEY.getBytes();
/**
* 统一下单
*
* @param orderPay
* @return 支付二维码url
* @throws IOException
*/
public String unifiedOrder(OrderPay orderPay) throws IOException {
public WxPayUnifiedOrderResultVO unifiedOrder(OrderPay orderPay) throws IOException {
CloseableHttpResponse response = null;
try {
if (httpClient == null)
@ -66,31 +113,161 @@ public class WechatPayService {
//处理请求结果
int statusCode = response.getStatusLine().getStatusCode();
String result = EntityUtils.toString(response.getEntity());
WxPayUnifiedOrderResultVO resultVO = JsonUtils.read(result, WxPayUnifiedOrderResultVO.class);
resultVO.setOrderCode(wxUnifiedOrder.getOut_trade_no());
if (statusCode == 200) { //处理成功
log.info("微信支付下单成功,return body = " + result);
return result;
return resultVO;
} else if (statusCode == 204) { //处理成功无返回Body
System.out.println("微信支付下单成功");
return result;
return resultVO;
} else {
log.error("failed,resp code = " + statusCode+ ",return body = " + result);
log.error("failed,resp code = " + statusCode + ",return body = " + result);
throw BusinessExceptionAssertEnum.PAY_ERROR.exception();
}
} catch (Exception e) {
throw BusinessExceptionAssertEnum.PAY_ERROR.exception("微信Native支付异常", e);
throw BusinessExceptionAssertEnum.PAY_ERROR.exception("微信Native支付下单异常", e);
} finally {
if (httpClient != null)
httpClient.close();
if (response != null)
response.close();
}
}
public void queryOrder(String orderCode) throws IOException {
CloseableHttpResponse response = null;
try {
if (httpClient == null)
buildHttpClient();
//构建并发送请求
String uri = String.format("https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/%s?mchid=%s", orderCode, MCH_ID);
HttpGet httpGet = new HttpGet(uri);
httpGet.setHeader("Accept", "application/json");
response = httpClient.execute(httpGet);
//处理请求结果
int statusCode = response.getStatusLine().getStatusCode();
String result = EntityUtils.toString(response.getEntity());
System.out.println(result);
} catch (Exception e) {
throw BusinessExceptionAssertEnum.PAY_ERROR.exception("微信Native支付下单异常", e);
} finally {
if (response != null)
response.close();
}
}
public static void main(String[] args) throws Exception {
// OrderPay pay = new OrderPay();
// pay.setOrderNo("2018081400004");
// pay.setDescription("标准1号线ATS现地工作站实操");
// pay.setTotalFee(1);
// pay.setTimeExpire(OffsetDateTime.now().plusMinutes(10));
// OrderDetailVO orderDetailVO = new OrderDetailVO();
// orderDetailVO.setGoodsId(1L);
// orderDetailVO.setGoodsName("测试");
// orderDetailVO.setGoodsAmount(1);
// orderDetailVO.setPrice(1L);
// pay.setOrderDetail(List.of(orderDetailVO));
// WechatPayService wps = new WechatPayService();
// WxPayUnifiedOrderResultVO result = wps.unifiedOrder(pay);
// System.out.println(result.getCode_url());
// String ciphertext = "g/oFDehAMQtFTAZy9yTmr9GUNcvZKbSnQnaKtH+c6QIXxI66bAHNl5O9BHAAVxGPSbB7FVkhTfVF0BxX/tKp3lSUOVZNhKgl+il/T1/gIBgCfecgkbPtn6iZGdYQ1cqJVr1y3PXF+g4jx0zdYNQSwke/ekacAcPyk1599uaptFb6gON27rZ7hLQfO9GAic9cdxQ2GER3J2fV/adoPx/fBU3/ru35w9IBxfQl97fzB0xTGjOQyS5wvIrcsdqcvUErpiOr+H/B1UIFG8E/QRRRvuh7q1hWkZcejhN8oz+F8YBdKGUTtQ2wBtMes6KakqhjuyQx/RXGYM5+JOiRI16jlPh/QK3Z0zvY1IvECAPo6l9zWlgupYZCy8kCbBdBSppc+gaAh83pVPSPp9yqib+x4oYBWYPuj8NQjUXuMU02WUF6Lhlf3J3kpOi+Djjz+LXdApRrLIfmQyiY/3NtacxyfwzYZech3tEvOGh9JHkii9NpoOsuNJOgz8MvEH8Br/rEUZFK4jFj3+86PBQI9WJ93hmnfWyx6+hKrRx0DEXjHvCwcfKh2rRlXRARmeNG";
// String associated_data = "transaction";
// String nonce ="jlrqKcdL725Q";
// System.out.println(decryptToString(associated_data.getBytes(), nonce.getBytes(), ciphertext));
WechatPayService service = new WechatPayService();
service.queryOrder("2021012900013");
}
/**
* 支付结果处理
*/
@Transactional
public WxPayNotifyRespondVO receive(String data, String signatureStr, String timestamp, String nonce, String serial) {
//验签
try {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(verifier.getValidCertificate());
String content = String.join("\n", timestamp, nonce, data);
signature.update(content.getBytes());
if (signature.verify(Base64.getDecoder().decode(signatureStr))) {
throw new RuntimeException(String.format("验签失败[timestamp:%s][nonce:%s][data:%s]", timestamp, nonce, data));
}
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
throw new PayException(BusinessExceptionAssertEnum.WECHAT_NOTIFY_ERROR, "验签异常", e);
}
WxPayNotifyVO notifyVO = JsonUtils.read(data, WxPayNotifyVO.class);
//解密
WxPayNotifyData result;
try {
String decryptText = decryptToString(notifyVO.getResource().getAssociated_data().getBytes(), notifyVO.getResource().getNonce().getBytes(), notifyVO.getResource().getCiphertext());
result = JsonUtils.read(decryptText, WxPayNotifyData.class);
} catch (GeneralSecurityException | IOException e) {
throw new PayException(BusinessExceptionAssertEnum.WECHAT_NOTIFY_ERROR, "解密异常", e);
}
//处理
synchronized (this) {
log.info(result.logStr());
if (!APP_ID.equals(result.getAppid()))
throw new PayException(BusinessExceptionAssertEnum.WECHAT_NOTIFY_ERROR, "微信通知appid校验不通过");
if (!MCH_ID.equals(result.getMchid()))
throw new PayException(BusinessExceptionAssertEnum.WECHAT_NOTIFY_ERROR, "微信通知mchid校验不通过");
iOrderService.recordTransactionId(result.getOut_trade_no(), result.getTransaction_id());
if (result.getTrade_state().equals(TradeState.SUCCESS)) {
OrderVO orderVO = iOrderService.getByCode(result.getOut_trade_no());
if (orderVO.isUnpaid()) {
iOrderService.finishPay(orderVO);
List<OrderDetailVO> orderDetails = iOrderService.getOrderDetail(orderVO.getId());
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertTrue(orderDetails.size() == 1,
String.format("支付的[%s]中有多个商品", orderVO.logStr()));
OrderDetailVO orderDetail = orderDetails.get(0);
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertTrue(orderDetail.getGoodsAmount() == 1,
String.format("支付的[%s]中购买的权限数量不应大于1", orderVO.logStr()));
GoodsVO goods = iGoodsService.getById(orderDetail.getGoodsId());
PermissionVO permission = iPermissionService.getById(goods.getPermissionId());
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertTrue(permission.getName().contains("综合演练"),
String.format("支付的[%s]中的商品不是综合演练权限", orderVO.logStr()));
MapVO mapInfo = iMapService.getMapInfoById(permission.getMapId());
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertTrue(Project.DRTS.name().equals(mapInfo.getProjectCode()),
String.format("支付的[%s]中的商品不是国赛的权限", orderVO.logStr()));
UserVO user = iSysUserService.getUserById(orderVO.getCreatorId());
List<UserPermissionVO> ups = iUserPermissionService.getSimulationUserPermission(user, mapInfo.getId(), MapPrdTypeEnum.JOINT.getCode());
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(ups.size() > 1,
"权限数量大于一,暂不能购买");
try {
if (ups.size() == 0) { //第一次购买
iPermissionDistributeService.distributeFromOrder(orderVO.getCode(), user); //创建权限分发
DistributeVO distribute = iPermissionDistributeService.getByOrderCode(orderVO.getCode()); //查询权限分发
iPermissionDistributeService.getUserPermission(distribute.getId(), user);
} else {
UserPermissionVO up = ups.get(0);
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(up.getAmount() > 1,
"权限数量大于一,暂不能购买");
iUserPermissionService.renewal(up.getId(), orderDetail.getMonthAmount());
}
} catch (BusinessException e) {
throw BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.exception(String.format("%s付款成功后权限获取异常", orderVO.logStr()));
}
applicationContext.publishEvent(new OrderPaySuccessEvent(orderVO.getCode(), user.getIdStr()));
return new WxPayNotifyRespondVO("SUCCESS", null);
} else {
return new WxPayNotifyRespondVO("SUCCESS", "已处理过");
}
} else {
return new WxPayNotifyRespondVO("SUCCESS", "支付未成功,不处理");
}
}
// TODO: 2021/1/28 考虑加下退款逻辑
}
private void buildHttpClient() {
try {
PrivateKey privateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(MCH_PRIVATE_KEY.getBytes("utf-8")));
AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
new WechatPay2Credentials(MCH_ID, new PrivateKeySigner(MCH_SERIAL_NO, privateKey)), APIV3_KEY.getBytes("utf-8"));
PrivateKey privateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(MCH_PRIVATE_KEY.getBytes(StandardCharsets.UTF_8)));
this.verifier = new AutoUpdateCertificatesVerifier(
new WechatPay2Credentials(MCH_ID, new PrivateKeySigner(MCH_SERIAL_NO, privateKey)), APIV3_KEY.getBytes(StandardCharsets.UTF_8));
httpClient = WechatPayHttpClientBuilder.create()
.withMerchant(MCH_ID, MCH_SERIAL_NO, privateKey)
.withValidator(new WechatPay2Validator(verifier))
@ -100,30 +277,24 @@ public class WechatPayService {
}
}
public static void main(String[] args) throws Exception {
OrderPay pay = new OrderPay();
pay.setOrderNo("2018081400003");
pay.setDescription("标准1号线ATS现地工作站实操");
pay.setTotalFee(1);
pay.setTimeExpire(OffsetDateTime.now().plusMinutes(10));
OrderDetailVO orderDetailVO = new OrderDetailVO();
orderDetailVO.setGoodsId(1L);
orderDetailVO.setGoodsName("测试");
orderDetailVO.setGoodsAmount(1);
orderDetailVO.setPrice(1L);
pay.setOrderDetail(List.of(orderDetailVO));
WechatPayService wps = new WechatPayService();
String result = wps.unifiedOrder(pay);
System.out.println(result);
}
/**
* 支付结果处理
* 回调报文解密
*/
public String receive(String data) {
String result = "支付结果:" + data;
log.info(result);
return result;
}
private static String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext) throws GeneralSecurityException, IOException {
try {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);
cipher.init(Cipher.DECRYPT_MODE, key, spec);
cipher.updateAAD(associatedData);
return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), StandardCharsets.UTF_8);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new IllegalStateException(e);
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
throw new IllegalArgumentException(e);
}
}
}

View File

@ -4,7 +4,7 @@ public interface WechatConstants {
public static interface PayUrl {
/** 统一下单接口地址 */
String UNIFIED_ORDER = "https://api.mch.weixin.qq.com/pay/unifiedorder";
String UNIFIED_ORDER = "https://api.mch.weixin.qq.com/v3/pay/transactions/native";
}
String DATE_FORMAT_STR = "yyyyMMddHHmmss";
@ -61,7 +61,7 @@ public interface WechatConstants {
* 支付类型
* @author sheng
*/
public static interface TradeType {
interface TradeType {
/** 扫码支付 */
String NATIVE = "NATIVE";
/** 公众号支付 */
@ -70,4 +70,34 @@ public interface WechatConstants {
String APP = "APP";
}
/**
* 交易状态
*/
public static interface TradeState {
/** 支付成功 */
String SUCCESS = "SUCCESS";
/** 转入退款 */
String REFUND = "REFUND";
/**
* 未支付
*/
String NOTPAY = "NOTPAY";
/**
* 已关闭
*/
String CLOSED = "CLOSED";
/**
* 已撤销付款码支付
*/
String REVOKED = "REVOKED";
/**
* 用户支付中付款码支付
*/
String USERPAYING = "USERPAYING";
/**
* 支付失败其它原因如银行返回失败
*/
String PAYERROR = "PAYERROR";
}
}

View File

@ -306,7 +306,7 @@ public class DepartUserStaticServiceImpl implements IDepartUserStatisticService
Long distributeId = distribute.getId();
iPermissionDistributeService.getUserPermission(distributeId, userZJ);
//从赵杰的权限创建权限分发
UserPermissionVO userPermission = iUserPermissionService.findValidByUserIdAndDistributeId(userZJ.getId(), distributeId).get(0);
UserPermissionVO userPermission = iUserPermissionService.queryValidByUserIdAndDistributeId(userZJ.getId(), distributeId).get(0);
UserPermissionDistributeVO distributeFromUP = new UserPermissionDistributeVO();
distributeFromUP.setStartTime(distribute.getStartTime());
distributeFromUP.setEndTime(distribute.getEndTime());

View File

@ -1,5 +1,6 @@
package club.joylink.rtss.simulation.cbtc.ATS.service;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.cbtc.CI.CiApiService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.constant.SimulationModule;
@ -124,6 +125,7 @@ public class AtsStandService {
*/
public void setJumpStop(Simulation simulation, String standCode, String trainGroupNumber) {
Stand stand = getStand(simulation, standCode);
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(stand.isHoldTrain(), stand.debugStr() + "正在扣车,无法跳停");
//TrainCodes为空全部跳停指定列车跳停
if (!StringUtils.hasText(trainGroupNumber)) {
stand.setAllSkip(true);

View File

@ -1,5 +1,6 @@
package club.joylink.rtss.simulation.cbtc;
import club.joylink.rtss.event.OrderPaySuccessEvent;
import club.joylink.rtss.services.IVirtualRealityIbpService;
import club.joylink.rtss.services.completition.ICompetitionPracticalService;
import club.joylink.rtss.simulation.cbtc.ATP.ground.ZCLogicLoop;
@ -833,4 +834,10 @@ public class SimulationMainThread {
.build(WebSocketMessageType.Simulation_Alarm, simulation.getGroup(), list);
this.stompMessageService.sendToUser(simulation.getSimulationUserIds(), messageVO);
}
@EventListener
public void handleDeviceFaultOverEvent(OrderPaySuccessEvent event) {
SocketMessageVO<String> message = SocketMessageFactory.buildOrderPaySuccessMessage(event.getOrderCode());
this.stompMessageService.sendToUser(event.getUserId(), message);
}
}

View File

@ -46,7 +46,8 @@ public class AESUtil {
Cipher cipher = Cipher.getInstance(AES_ALGORITHM);// 创建密码器
IvParameterSpec iv = new IvParameterSpec(key.getEncoded());//使用CBC模式需要一个向量iv可增加加密算法的强度
cipher.init(Cipher.DECRYPT_MODE, key, iv);// 初始化
byte[] result = cipher.doFinal(Base64.getDecoder().decode(cipherText));// 解密
byte[] decode = Base64.getDecoder().decode(cipherText);
byte[] result = cipher.doFinal(decode);// 解密
return new String(result, CHARSET_UTF8);
} catch (Exception e) {
e.printStackTrace();

View File

@ -346,4 +346,11 @@ public class SocketMessageFactory {
public static SocketMessageVO<String> buildSimulationScriptActionErrorMessage(String group, String id) {
return build(WebSocketMessageType.Simulation_Script_Action_Error, group, id);
}
/**
* 订单支付成功
*/
public static SocketMessageVO<String> buildOrderPaySuccessMessage(String orderCode) {
return build(WebSocketMessageType.Order_Pay_Result, null, orderCode);
}
}

View File

@ -1,7 +1,7 @@
package club.joylink.rtss.vo.client.order;
import com.fasterxml.jackson.annotation.JsonFormat;
import club.joylink.rtss.entity.SaleOrder;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import lombok.Getter;
import lombok.NoArgsConstructor;

View File

@ -1,8 +1,9 @@
package club.joylink.rtss.vo.client.order;
import club.joylink.rtss.constants.SaleOrderPayStatusEnum;
import club.joylink.rtss.entity.SaleOrder;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import club.joylink.rtss.entity.SaleOrder;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
@ -117,4 +118,14 @@ public class OrderVO {
return saleOrder;
}
/**
* 订单是否待支付
*/
public boolean isUnpaid() {
return SaleOrderPayStatusEnum.Unpaid.getCode().equals(this.payStatus);
}
public String logStr() {
return String.format("订单[%s]", id);
}
}

View File

@ -0,0 +1,142 @@
package club.joylink.rtss.vo.client.pay;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.List;
/**
* 微信支付回调通知的结果通知中的密文解密得到
*/
@Getter
@Setter
@NoArgsConstructor
public class WxPayNotifyData {
/**
* 应用ID
*/
private String appid;
/**
* 商户号
*/
private String mchid;
/**
* 商户订单号
*/
private String out_trade_no;
/**
* 微信支付订单号
*/
private String transaction_id;
/**
* 交易类型
*/
private String trade_type;
/**
* 交易状态
*/
private String trade_state;
/**
* 交易状态描述
*/
private String trade_state_desc;
/**
* 付款银行
*/
private String bank_type;
/**
* 附加数据
*/
private String attach;
/**
* 支付完成时间
*/
private String success_time;
/**
* 支付者
*/
private Payer payer;
/**
* 订单金额
*/
private Amount amount;
/**
* 场景信息
*/
private SceneInfo scene_info;
/**
* 优惠功能
*/
private List<PromotionDetail> promotion_detail;
public String logStr() {
return String.format("微信支付回调通知:商户订单号[%s]-微信支付订单号[%S]-交易类型[%s]-交易状态[%s]-交易状态描述[%s]",
out_trade_no, transaction_id, trade_type, trade_state, trade_state_desc);
}
@Getter
@Setter
@NoArgsConstructor
public class Payer {
/**
* 用户在直连商户appid下的唯一标识
*/
private String openid;
}
@Getter
@Setter
@NoArgsConstructor
public class Amount{
/**
* 总金额单位分
*/
private int total;
/**
* 用户支付的金额
*/
private int payer_total;
/**
* 货币类型
*/
private String currency;
/**
* 用户支付币种
*/
private String payer_currency;
}
@Getter
@Setter
@NoArgsConstructor
public class SceneInfo{
/**
* 终端设备号门店号或收银设备ID
*/
private String device_id;
}
@Getter
@Setter
@NoArgsConstructor
public class PromotionDetail{
//先略过暂时用不上字段太多了
}
}

View File

@ -0,0 +1,18 @@
package club.joylink.rtss.vo.client.pay;
import lombok.Getter;
/**
* 微信支付通知应答
*/
@Getter
public class WxPayNotifyRespondVO {
private String code;
private String message;
public WxPayNotifyRespondVO(String code, String message) {
this.code = code;
this.message = message;
}
}

View File

@ -0,0 +1,77 @@
package club.joylink.rtss.vo.client.pay;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* 微信支付通知
*/
@Getter
@Setter
@NoArgsConstructor
public class WxPayNotifyVO {
/**
* 通知ID
*/
private String id;
/**
* 通知创建时间
*/
private String create_time;
/**
* 通知类型
*/
private String event_type;
/**
* 通知数据类型
*/
private String resource_type;
/**
* 通知数据
*/
private Resource resource;
/**
* 回调摘要
*/
private String summary;
/**
* 通知数据
*/
@Getter
@Setter
@NoArgsConstructor
public
class Resource {
/**
* 加密算法类型
*/
private String algorithm;
/**
* 数据密文
*/
private String ciphertext;
/**
* 附加数据
*/
private String associated_data;
/**
* 原始类型
*/
private String original_type;
/**
* 随机串
*/
private String nonce;
}
}

View File

@ -0,0 +1,71 @@
package club.joylink.rtss.vo.client.pay;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* 微信申请退款数据
*/
@Getter
@Setter
@NoArgsConstructor
public class WxPayRefund {
/**
* 微信支付订单号
*/
private String transaction_id;
/**
* 商户订单号
*/
private String out_trade_no;
/**
* 商户退款单号
*/
private String out_refund_no;
/**
* 退款原因
*/
private String reason;
/**
* 退款结果回调URL
*/
private String notify_url;
/**
* 退款资金来源
*/
private String funds_account;
/**
* 退款金额
*/
private Amount amount;
/**
* 金额信息
*/
@Getter
@Setter
@NoArgsConstructor
public class Amount {
/**
* 退款金额币种的最小单位不能超过原价
*/
private Integer refund;
/**
* 原订单金额币种的最小单位
*/
private Integer total;
/**
* 退款币种
*/
private String currency;
}
}

View File

@ -0,0 +1,23 @@
package club.joylink.rtss.vo.client.pay;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* 微信统一下单结果
*/
@Getter
@Setter
@NoArgsConstructor
public class WxPayUnifiedOrderResultVO {
/**
* 二维码
*/
private String code_url;
/**
* 订单编号
*/
private String orderCode;
}

View File

@ -15,8 +15,9 @@
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
<result column="update_user_id" jdbcType="BIGINT" property="updateUserId" />
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
<result column="qr_code_generated" jdbcType="BIT" property="qrCodeGenerated" />
<result column="qr_code_generated" jdbcType="TINYINT" property="qrCodeGenerated" />
<result column="seller_id" jdbcType="BIGINT" property="sellerId" />
<result column="transaction_id" jdbcType="VARCHAR" property="transactionId" />
</resultMap>
<sql id="Example_Where_Clause">
<where>
@ -78,7 +79,8 @@
</sql>
<sql id="Base_Column_List">
id, code, organization_id, price, pay_ways, pay_status, `status`, contract_no, order_type,
creator_id, create_time, update_user_id, update_time, qr_code_generated, seller_id
creator_id, create_time, update_user_id, update_time, qr_code_generated, seller_id,
transaction_id
</sql>
<select id="selectByExample" parameterType="club.joylink.rtss.entity.SaleOrderExample" resultMap="BaseResultMap">
select
@ -123,12 +125,14 @@
pay_ways, pay_status, `status`,
contract_no, order_type, creator_id,
create_time, update_user_id, update_time,
qr_code_generated, seller_id)
qr_code_generated, seller_id, transaction_id
)
values (#{code,jdbcType=VARCHAR}, #{organizationId,jdbcType=BIGINT}, #{price,jdbcType=BIGINT},
#{payWays,jdbcType=VARCHAR}, #{payStatus,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR},
#{contractNo,jdbcType=VARCHAR}, #{orderType,jdbcType=VARCHAR}, #{creatorId,jdbcType=BIGINT},
#{createTime,jdbcType=TIMESTAMP}, #{updateUserId,jdbcType=BIGINT}, #{updateTime,jdbcType=TIMESTAMP},
#{qrCodeGenerated,jdbcType=BIT}, #{sellerId,jdbcType=BIGINT})
#{qrCodeGenerated,jdbcType=TINYINT}, #{sellerId,jdbcType=BIGINT}, #{transactionId,jdbcType=VARCHAR}
)
</insert>
<insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="club.joylink.rtss.entity.SaleOrder" useGeneratedKeys="true">
insert into sale_order
@ -175,6 +179,9 @@
<if test="sellerId != null">
seller_id,
</if>
<if test="transactionId != null">
transaction_id,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="code != null">
@ -214,11 +221,14 @@
#{updateTime,jdbcType=TIMESTAMP},
</if>
<if test="qrCodeGenerated != null">
#{qrCodeGenerated,jdbcType=BIT},
#{qrCodeGenerated,jdbcType=TINYINT},
</if>
<if test="sellerId != null">
#{sellerId,jdbcType=BIGINT},
</if>
<if test="transactionId != null">
#{transactionId,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="club.joylink.rtss.entity.SaleOrderExample" resultType="java.lang.Long">
@ -270,11 +280,14 @@
update_time = #{record.updateTime,jdbcType=TIMESTAMP},
</if>
<if test="record.qrCodeGenerated != null">
qr_code_generated = #{record.qrCodeGenerated,jdbcType=BIT},
qr_code_generated = #{record.qrCodeGenerated,jdbcType=TINYINT},
</if>
<if test="record.sellerId != null">
seller_id = #{record.sellerId,jdbcType=BIGINT},
</if>
<if test="record.transactionId != null">
transaction_id = #{record.transactionId,jdbcType=VARCHAR},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
@ -295,8 +308,9 @@
create_time = #{record.createTime,jdbcType=TIMESTAMP},
update_user_id = #{record.updateUserId,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=TIMESTAMP},
qr_code_generated = #{record.qrCodeGenerated,jdbcType=BIT},
seller_id = #{record.sellerId,jdbcType=BIGINT}
qr_code_generated = #{record.qrCodeGenerated,jdbcType=TINYINT},
seller_id = #{record.sellerId,jdbcType=BIGINT},
transaction_id = #{record.transactionId,jdbcType=VARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
@ -341,11 +355,14 @@
update_time = #{updateTime,jdbcType=TIMESTAMP},
</if>
<if test="qrCodeGenerated != null">
qr_code_generated = #{qrCodeGenerated,jdbcType=BIT},
qr_code_generated = #{qrCodeGenerated,jdbcType=TINYINT},
</if>
<if test="sellerId != null">
seller_id = #{sellerId,jdbcType=BIGINT},
</if>
<if test="transactionId != null">
transaction_id = #{transactionId,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=BIGINT}
</update>
@ -363,8 +380,9 @@
create_time = #{createTime,jdbcType=TIMESTAMP},
update_user_id = #{updateUserId,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=TIMESTAMP},
qr_code_generated = #{qrCodeGenerated,jdbcType=BIT},
seller_id = #{sellerId,jdbcType=BIGINT}
qr_code_generated = #{qrCodeGenerated,jdbcType=TINYINT},
seller_id = #{sellerId,jdbcType=BIGINT},
transaction_id = #{transactionId,jdbcType=VARCHAR}
where id = #{id,jdbcType=BIGINT}
</update>
</mapper>