提交 d3b8a353 authored 作者: jacksmith1988's avatar jacksmith1988

//init

上级 ed53a40a
......@@ -160,4 +160,8 @@ public class Constant {
public static final String 下级账号查询范围_指定账号及直接下级 = "20";
public static final String 支付渠道_银行卡 = "bankcard";
public static final String 支付渠道_微信码 = "wechat";
public static final String 支付渠道_支付宝码 = "alipay";
}
......@@ -29,52 +29,64 @@ import me.zohar.runscore.useraccount.domain.UserAccount;
@DynamicUpdate(true)
public class GatheringCode {
/**
* 主键id
*/
@Id
@Column(name = "id", length = 32)
private String id;
/**
* 收款渠道
*/
private String gatheringChannelCode;
/**
* 状态,启用:1;禁用:0
*/
private String state;
private Boolean fixedGatheringAmount;
/**
* 收款金额
*/
private Double gatheringAmount;
/**
* 收款人
*/
private String payee;
/**
* 创建时间
*/
private Date createTime;
@Column(name = "storage_id", length = 32)
private String storageId;
/**
* 用户账号id
*/
@Column(name = "user_account_id", length = 32)
private String userAccountId;
@NotFound(action = NotFoundAction.IGNORE)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_account_id", updatable = false, insertable = false, foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
private UserAccount userAccount;
/**
* 主键id
*/
@Id
@Column(name = "id", length = 32)
private String id;
/**
* 收款渠道
*/
private String gatheringChannelCode;
/**
* 状态,启用:1;禁用:0
*/
private String state;
private Boolean fixedGatheringAmount;
/**
* 收款金额
*/
private Double gatheringAmount;
/**
* 收款人
*/
private String payee;
/**
* 开户行
*/
private String bankAddress;
/**
* 卡号
*/
private String bankCode;
/**
* 卡户主
*/
private String bankUsername;
/**
* 创建时间
*/
private Date createTime;
@Column(name = "storage_id", length = 32)
private String storageId;
/**
* 用户账号id
*/
@Column(name = "user_account_id", length = 32)
private String userAccountId;
@NotFound(action = NotFoundAction.IGNORE)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_account_id", updatable = false, insertable = false, foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
private UserAccount userAccount;
}
......@@ -54,6 +54,19 @@ public class GatheringCodeParam {
private String storageId;
/**
* 开户行
*/
private String bankAddress;
/**
* 卡号
*/
private String bankCode;
/**
* 卡户主
*/
private String bankUsername;
public GatheringCode convertToPo(String userAccountId) {
GatheringCode po = new GatheringCode();
BeanUtils.copyProperties(this, po);
......
......@@ -38,150 +38,156 @@ import me.zohar.runscore.useraccount.repo.UserAccountRepo;
@Service
public class GatheringCodeService {
@Autowired
private GatheringCodeRepo gatheringCodeRepo;
@Autowired
private StorageRepo storageRepo;
@Autowired
private UserAccountRepo userAccountRepo;
@Transactional
public void delMyGatheringCodeById(String id, String userAccountId) {
GatheringCode gatheringCode = gatheringCodeRepo.getOne(id);
if (!userAccountId.equals(gatheringCode.getUserAccountId())) {
throw new BizException(BizError.无权删除数据);
}
delGatheringCodeById(id);
}
@Transactional
public void delGatheringCodeById(String id) {
GatheringCode gatheringCode = gatheringCodeRepo.getOne(id);
disassociationGatheringCodeStorage(gatheringCode.getStorageId());
gatheringCodeRepo.delete(gatheringCode);
}
@Transactional(readOnly = true)
public GatheringCodeVO findMyGatheringCodeById(String id, String userAccountId) {
GatheringCodeVO vo = findGatheringCodeById(id);
if (!userAccountId.equals(vo.getUserAccountId())) {
throw new BizException(BizError.无权查看数据);
}
return vo;
}
@Transactional(readOnly = true)
public GatheringCodeVO findGatheringCodeById(String id) {
GatheringCode gatheringCode = gatheringCodeRepo.getOne(id);
return GatheringCodeVO.convertFor(gatheringCode);
}
@Transactional(readOnly = true)
public PageResult<GatheringCodeVO> findMyGatheringCodeByPage(GatheringCodeQueryCondParam param) {
if (StrUtil.isBlank(param.getUserAccountId())) {
throw new BizException(BizError.无权查看数据);
}
return findGatheringCodeByPage(param);
}
@Transactional(readOnly = true)
public PageResult<GatheringCodeVO> findGatheringCodeByPage(GatheringCodeQueryCondParam param) {
Specification<GatheringCode> spec = new Specification<GatheringCode>() {
/**
*
*/
private static final long serialVersionUID = 1L;
public Predicate toPredicate(Root<GatheringCode> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
List<Predicate> predicates = new ArrayList<Predicate>();
if (StrUtil.isNotEmpty(param.getState())) {
predicates.add(builder.equal(root.get("state"), param.getState()));
}
if (StrUtil.isNotEmpty(param.getGatheringChannelCode())) {
predicates.add(builder.equal(root.get("gatheringChannelCode"), param.getGatheringChannelCode()));
}
if (StrUtil.isNotEmpty(param.getPayee())) {
predicates.add(builder.equal(root.get("payee"), param.getPayee()));
}
if (StrUtil.isNotEmpty(param.getUserName())) {
predicates.add(builder.equal(root.join("userAccount", JoinType.INNER).get("userName"),
param.getUserName()));
}
if (StrUtil.isNotEmpty(param.getUserAccountId())) {
predicates.add(builder.equal(root.get("userAccountId"), param.getUserAccountId()));
}
return predicates.size() > 0 ? builder.and(predicates.toArray(new Predicate[predicates.size()])) : null;
}
};
Page<GatheringCode> result = gatheringCodeRepo.findAll(spec,
PageRequest.of(param.getPageNum() - 1, param.getPageSize(), Sort.by(Sort.Order.desc("createTime"))));
PageResult<GatheringCodeVO> pageResult = new PageResult<>(GatheringCodeVO.convertFor(result.getContent()),
param.getPageNum(), param.getPageSize(), result.getTotalElements());
return pageResult;
}
@Transactional
public void associateGatheringCodeStorage(String storageId, String gatheringCodeId) {
Storage storage = storageRepo.getOne(storageId);
storage.setAssociateId(gatheringCodeId);
storage.setAssociateBiz("gatheringCode");
storageRepo.save(storage);
}
@Transactional
public void disassociationGatheringCodeStorage(String storageId) {
Storage oldStorage = storageRepo.getOne(storageId);
oldStorage.setAssociateId(null);
oldStorage.setAssociateBiz(null);
storageRepo.save(oldStorage);
}
@Transactional
public void addOrUpdateGatheringCode(GatheringCodeParam param) {
String userAccountId = null;
if (StrUtil.isBlank(param.getId())) {
if (StrUtil.isBlank(param.getUserName())) {
throw new BizException(BizError.参数异常);
}
UserAccount userAccount = userAccountRepo.findByUserName(param.getUserName());
if (userAccount == null) {
throw new BizException(BizError.找不到所属账号无法新增收款码);
}
userAccountId = userAccount.getId();
}
addOrUpdateGatheringCode(param, userAccountId);
}
@ParamValid
@Transactional
public void addOrUpdateGatheringCode(GatheringCodeParam param, String userAccountId) {
if (param.getFixedGatheringAmount()) {
@Autowired
private GatheringCodeRepo gatheringCodeRepo;
@Autowired
private StorageRepo storageRepo;
@Autowired
private UserAccountRepo userAccountRepo;
@Transactional
public void delMyGatheringCodeById(String id, String userAccountId) {
GatheringCode gatheringCode = gatheringCodeRepo.getOne(id);
if (!userAccountId.equals(gatheringCode.getUserAccountId())) {
throw new BizException(BizError.无权删除数据);
}
delGatheringCodeById(id);
}
@Transactional
public void delGatheringCodeById(String id) {
GatheringCode gatheringCode = gatheringCodeRepo.getOne(id);
disassociationGatheringCodeStorage(gatheringCode.getStorageId());
gatheringCodeRepo.delete(gatheringCode);
}
@Transactional(readOnly = true)
public GatheringCodeVO findMyGatheringCodeById(String id, String userAccountId) {
GatheringCodeVO vo = findGatheringCodeById(id);
if (!userAccountId.equals(vo.getUserAccountId())) {
throw new BizException(BizError.无权查看数据);
}
return vo;
}
@Transactional(readOnly = true)
public GatheringCodeVO findGatheringCodeById(String id) {
GatheringCode gatheringCode = gatheringCodeRepo.getOne(id);
return GatheringCodeVO.convertFor(gatheringCode);
}
@Transactional(readOnly = true)
public PageResult<GatheringCodeVO> findMyGatheringCodeByPage(GatheringCodeQueryCondParam param) {
if (StrUtil.isBlank(param.getUserAccountId())) {
throw new BizException(BizError.无权查看数据);
}
return findGatheringCodeByPage(param);
}
@Transactional(readOnly = true)
public PageResult<GatheringCodeVO> findGatheringCodeByPage(GatheringCodeQueryCondParam param) {
Specification<GatheringCode> spec = new Specification<GatheringCode>() {
/**
*
*/
private static final long serialVersionUID = 1L;
public Predicate toPredicate(Root<GatheringCode> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
List<Predicate> predicates = new ArrayList<Predicate>();
if (StrUtil.isNotEmpty(param.getState())) {
predicates.add(builder.equal(root.get("state"), param.getState()));
}
if (StrUtil.isNotEmpty(param.getGatheringChannelCode())) {
predicates.add(builder.equal(root.get("gatheringChannelCode"), param.getGatheringChannelCode()));
}
if (StrUtil.isNotEmpty(param.getPayee())) {
predicates.add(builder.equal(root.get("payee"), param.getPayee()));
}
if (StrUtil.isNotEmpty(param.getUserName())) {
predicates.add(builder.equal(root.join("userAccount", JoinType.INNER).get("userName"),
param.getUserName()));
}
if (StrUtil.isNotEmpty(param.getUserAccountId())) {
predicates.add(builder.equal(root.get("userAccountId"), param.getUserAccountId()));
}
return predicates.size() > 0 ? builder.and(predicates.toArray(new Predicate[predicates.size()])) : null;
}
};
Page<GatheringCode> result = gatheringCodeRepo.findAll(spec,
PageRequest.of(param.getPageNum() - 1, param.getPageSize(), Sort.by(Sort.Order.desc("createTime"))));
PageResult<GatheringCodeVO> pageResult = new PageResult<>(GatheringCodeVO.convertFor(result.getContent()),
param.getPageNum(), param.getPageSize(), result.getTotalElements());
return pageResult;
}
@Transactional
public void associateGatheringCodeStorage(String storageId, String gatheringCodeId) {
Storage storage = storageRepo.getOne(storageId);
storage.setAssociateId(gatheringCodeId);
storage.setAssociateBiz("gatheringCode");
storageRepo.save(storage);
}
@Transactional
public void disassociationGatheringCodeStorage(String storageId) {
Storage oldStorage = storageRepo.getOne(storageId);
oldStorage.setAssociateId(null);
oldStorage.setAssociateBiz(null);
storageRepo.save(oldStorage);
}
@Transactional
public void addOrUpdateGatheringCode(GatheringCodeParam param) {
String userAccountId = null;
if (StrUtil.isBlank(param.getId())) {
if (StrUtil.isBlank(param.getUserName())) {
throw new BizException(BizError.参数异常);
}
UserAccount userAccount = userAccountRepo.findByUserName(param.getUserName());
if (userAccount == null) {
throw new BizException(BizError.找不到所属账号无法新增收款码);
}
userAccountId = userAccount.getId();
}
addOrUpdateGatheringCode(param, userAccountId);
}
@ParamValid
@Transactional
public void addOrUpdateGatheringCode(GatheringCodeParam param, String userAccountId) {
/*if (param.getFixedGatheringAmount()) {
if (param.getGatheringAmount() == null) {
throw new BizException(BizError.参数异常);
}
if (param.getGatheringAmount() <= 0) {
throw new BizException(BizError.参数异常);
}
}
// 新增
if (StrUtil.isBlank(param.getId())) {
GatheringCode gatheringCode = param.convertToPo(userAccountId);
gatheringCodeRepo.save(gatheringCode);
associateGatheringCodeStorage(param.getStorageId(), gatheringCode.getId());
}
// 修改
else {
GatheringCode gatheringCode = gatheringCodeRepo.getOne(param.getId());
// 取消关联旧的收款码图片
if (!param.getStorageId().equals(gatheringCode.getStorageId())) {
disassociationGatheringCodeStorage(gatheringCode.getStorageId());
}
BeanUtils.copyProperties(param, gatheringCode);
gatheringCodeRepo.save(gatheringCode);
associateGatheringCodeStorage(param.getStorageId(), gatheringCode.getId());
}
}
}*/
// 新增
if (StrUtil.isBlank(param.getId())) {
GatheringCode gatheringCode = param.convertToPo(userAccountId);
gatheringCodeRepo.save(gatheringCode);
if (param.getGatheringChannelCode().equals("bankcard")) {
return;
}
associateGatheringCodeStorage(param.getStorageId(), gatheringCode.getId());
}
// 修改
else {
GatheringCode gatheringCode = gatheringCodeRepo.getOne(param.getId());
// 取消关联旧的收款码图片
if (!param.getStorageId().equals(gatheringCode.getStorageId())) {
disassociationGatheringCodeStorage(gatheringCode.getStorageId());
}
BeanUtils.copyProperties(param, gatheringCode);
gatheringCodeRepo.save(gatheringCode);
if (param.getGatheringChannelCode().equals("bankcard")) {
return;
}
associateGatheringCodeStorage(param.getStorageId(), gatheringCode.getId());
}
}
}
......@@ -37,6 +37,7 @@ import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
......@@ -84,658 +85,681 @@ import me.zohar.runscore.useraccount.repo.UserAccountRepo;
@Service
public class MerchantOrderService {
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private MerchantOrderRepo merchantOrderRepo;
@Autowired
private MerchantOrderPayInfoRepo merchantOrderPayInfoRepo;
@Autowired
private MerchantRepo merchantRepo;
@Autowired
private UserAccountRepo userAccountRepo;
@Autowired
private GatheringCodeRepo gatheringCodeRepo;
@Autowired
private AccountChangeLogRepo accountChangeLogRepo;
@Autowired
private ReceiveOrderSettingRepo platformOrderSettingRepo;
@Autowired
private OrderRebateRepo orderRebateRepo;
@Transactional(readOnly = true)
public MerchantOrderDetailsVO findMerchantOrderDetailsById(@NotBlank String orderId) {
MerchantOrderDetailsVO vo = MerchantOrderDetailsVO.convertFor(merchantOrderRepo.getOne(orderId));
return vo;
}
/**
* 客服取消订单退款
*
* @param orderId
*/
@Transactional
public void customerServiceCancelOrderRefund(@NotBlank String orderId) {
MerchantOrder merchantOrder = merchantOrderRepo.getOne(orderId);
if (!(Constant.商户订单状态_申诉中.equals(merchantOrder.getOrderState()))) {
throw new BizException(BizError.只有申诉中的商户订单才能取消订单退款);
}
UserAccount userAccount = merchantOrder.getReceivedAccount();
Double cashDeposit = NumberUtil.round(userAccount.getCashDeposit() + merchantOrder.getGatheringAmount(), 4)
.doubleValue();
userAccount.setCashDeposit(cashDeposit);
userAccountRepo.save(userAccount);
merchantOrder.customerCancelOrderRefund();
merchantOrderRepo.save(merchantOrder);
accountChangeLogRepo.save(AccountChangeLog.buildWithCustomerCancelOrderRefund(userAccount, merchantOrder));
}
// @Transactional
// public void merchantConfirmToPaid(@NotBlank String secretKey, @NotBlank
// String orderId) {
// Merchant merchant = merchantRepo.findByMerchantNum(secretKey);
// if (merchant == null) {
// throw new BizException(BizError.商户未接入);
// }
// MerchantOrder order = merchantOrderRepo.findById(orderId).orElse(null);
// if (order == null) {
// log.error("商家订单不存在;secretKey:{},orderId:{}", secretKey, orderId);
// throw new BizException(BizError.商户订单不存在);
// }
// if (!order.getMerchantId().equals(merchant.getId())) {
// log.error("无权更新商家订单状态为商户已确认支付;secretKey:{},orderId:{}", secretKey, orderId);
// throw new BizException(BizError.无权更新商户订单状态为商户已确认支付);
// }
// if (!Constant.商户订单状态_已接单.equals(order.getOrderState())) {
// throw new BizException(BizError.订单状态为已接单才能转为平台已确认支付);
// }
// order.merchantConfirmToPaid();
// merchantOrderRepo.save(order);
// }
@Transactional(readOnly = true)
public OrderGatheringCodeVO getOrderGatheringCode(@NotBlank String orderNo) {
MerchantOrder order = merchantOrderRepo.findByOrderNo(orderNo);
if (order == null) {
log.error("商户订单不存在;orderNo:{}", orderNo);
throw new BizException(BizError.商户订单不存在);
}
String gatheringCodeStorageId = getGatheringCodeStorageId(order.getReceivedAccountId(),
order.getGatheringChannelCode(), order.getGatheringAmount());
OrderGatheringCodeVO vo = OrderGatheringCodeVO.convertFor(order);
vo.setGatheringCodeStorageId(gatheringCodeStorageId);
return vo;
}
@Transactional(readOnly = true)
public String getGatheringCodeStorageId(String receivedAccountId, String gatheringChannelCode,
Double gatheringAmount) {
ReceiveOrderSetting merchantOrderSetting = platformOrderSettingRepo.findTopByOrderByLatelyUpdateTime();
if (merchantOrderSetting.getUnfixedGatheringCodeReceiveOrder()) {
GatheringCode gatheringCode = gatheringCodeRepo
.findTopByUserAccountIdAndGatheringChannelCodeAndFixedGatheringAmountIsFalse(receivedAccountId,
gatheringChannelCode);
if (gatheringCode != null) {
return gatheringCode.getStorageId();
}
} else {
GatheringCode gatheringCode = gatheringCodeRepo
.findTopByUserAccountIdAndGatheringChannelCodeAndGatheringAmount(receivedAccountId,
gatheringChannelCode, gatheringAmount);
if (gatheringCode != null) {
return gatheringCode.getStorageId();
}
}
return null;
}
@Transactional
public void userConfirmToPaid(@NotBlank String userAccountId, @NotBlank String orderId) {
MerchantOrder platformOrder = merchantOrderRepo.findByIdAndReceivedAccountId(orderId, userAccountId);
if (platformOrder == null) {
throw new BizException(BizError.商户订单不存在);
}
if (!(Constant.商户订单状态_已接单.equals(platformOrder.getOrderState())
|| Constant.商户订单状态_商户已确认支付.equals(platformOrder.getOrderState()))) {
throw new BizException(BizError.订单状态为已接单或平台已确认支付才能转为确认已支付);
}
platformOrder.confirmToPaid(null);
merchantOrderRepo.save(platformOrder);
receiveOrderBountySettlement(platformOrder);
}
/**
* 客服确认已支付
*
* @param orderId
*/
@Transactional
public void customerServiceConfirmToPaid(@NotBlank String orderId, String note) {
MerchantOrder platformOrder = merchantOrderRepo.findById(orderId).orElse(null);
if (platformOrder == null) {
throw new BizException(BizError.商户订单不存在);
}
if (!Constant.商户订单状态_申诉中.equals(platformOrder.getOrderState())) {
throw new BizException(BizError.订单状态为申述中才能转为确认已支付);
}
platformOrder.confirmToPaid(note);
merchantOrderRepo.save(platformOrder);
receiveOrderBountySettlement(platformOrder);
}
/**
* 接单奖励金结算
*/
@Transactional
public void receiveOrderBountySettlement(MerchantOrder merchantOrder) {
UserAccount userAccount = merchantOrder.getReceivedAccount();
double bounty = NumberUtil.round(merchantOrder.getGatheringAmount() * userAccount.getRebate() * 0.01, 4)
.doubleValue();
merchantOrder.updateBounty(bounty);
merchantOrderRepo.save(merchantOrder);
userAccount.setCashDeposit(NumberUtil.round(userAccount.getCashDeposit() + bounty, 4).doubleValue());
userAccountRepo.save(userAccount);
accountChangeLogRepo
.save(AccountChangeLog.buildWithReceiveOrderBounty(userAccount, bounty, userAccount.getRebate()));
generateOrderRebate(merchantOrder);
ThreadPoolUtils.getPaidMerchantOrderPool().schedule(() -> {
redisTemplate.opsForList().leftPush(Constant.商户订单ID, merchantOrder.getId());
}, 1, TimeUnit.SECONDS);
}
/**
* 生成订单返点
*
* @param bettingOrder
*/
public void generateOrderRebate(MerchantOrder merchantOrder) {
UserAccount userAccount = merchantOrder.getReceivedAccount();
UserAccount superior = merchantOrder.getReceivedAccount().getInviter();
while (superior != null) {
double rebate = NumberUtil.round(superior.getRebate() - userAccount.getRebate(), 4).doubleValue();
if (rebate < 0) {
log.error("订单返点异常,下级账号的返点不能大于上级账号;下级账号id:{},上级账号id:{}", userAccount.getId(), superior.getId());
break;
}
double rebateAmount = NumberUtil.round(merchantOrder.getGatheringAmount() * rebate * 0.01, 4).doubleValue();
OrderRebate orderRebate = OrderRebate.build(rebate, rebateAmount, merchantOrder.getId(), superior.getId());
orderRebateRepo.save(orderRebate);
userAccount = superior;
superior = superior.getInviter();
}
}
@Transactional(readOnly = true)
public void orderRebateAutoSettlement() {
List<OrderRebate> orderRebates = orderRebateRepo.findBySettlementTimeIsNull();
for (OrderRebate orderRebate : orderRebates) {
redisTemplate.opsForList().leftPush(Constant.订单返点ID, orderRebate.getId());
}
}
/**
* 通知指定的订单进行返点结算
*
* @param issueId
*/
@Transactional(readOnly = true)
public void noticeOrderRebateSettlement(@NotBlank String orderId) {
List<OrderRebate> orderRebates = orderRebateRepo.findByMerchantOrderId(orderId);
for (OrderRebate orderRebate : orderRebates) {
redisTemplate.opsForList().leftPush(Constant.订单返点ID, orderRebate.getId());
}
}
/**
* 订单返点结算
*/
@Transactional
public void orderRebateSettlement(@NotBlank String orderRebateId) {
OrderRebate orderRebate = orderRebateRepo.getOne(orderRebateId);
if (orderRebate.getSettlementTime() != null) {
log.warn("当前的订单返点记录已结算,无法重复结算;id:{}", orderRebateId);
return;
}
orderRebate.settlement();
orderRebateRepo.save(orderRebate);
UserAccount userAccount = orderRebate.getRebateAccount();
double cashDeposit = userAccount.getCashDeposit() + orderRebate.getRebateAmount();
userAccount.setCashDeposit(NumberUtil.round(cashDeposit, 4).doubleValue());
userAccountRepo.save(userAccount);
accountChangeLogRepo.save(AccountChangeLog.buildWithOrderRebate(userAccount, orderRebate));
}
@Transactional(readOnly = true)
public List<MyWaitConfirmOrderVO> findMyWaitConfirmOrder(@NotBlank String userAccountId) {
return MyWaitConfirmOrderVO
.convertFor(merchantOrderRepo.findByOrderStateInAndReceivedAccountIdOrderBySubmitTimeDesc(
Arrays.asList(Constant.商户订单状态_已接单, Constant.商户订单状态_商户已确认支付), userAccountId));
}
@Transactional(readOnly = true)
public List<MyWaitReceivingOrderVO> findMyWaitReceivingOrder(@NotBlank String userAccountId) {
UserAccount userAccount = userAccountRepo.getOne(userAccountId);
List<GatheringCode> gatheringCodes = gatheringCodeRepo.findByUserAccountId(userAccountId);
if (CollectionUtil.isEmpty(gatheringCodes)) {
throw new BizException(BizError.未设置收款码无法接单);
}
ReceiveOrderSetting merchantOrderSetting = platformOrderSettingRepo.findTopByOrderByLatelyUpdateTime();
if (merchantOrderSetting.getUnfixedGatheringCodeReceiveOrder()) {
Map<String, String> gatheringChannelCodeMap = new HashMap<>();
for (GatheringCode gatheringCode : gatheringCodes) {
gatheringChannelCodeMap.put(gatheringCode.getGatheringChannelCode(),
gatheringCode.getGatheringChannelCode());
}
List<MerchantOrder> waitReceivingOrders = merchantOrderRepo
.findTop10ByOrderStateAndGatheringAmountIsLessThanEqualAndGatheringChannelCodeInOrderBySubmitTimeDesc(
Constant.商户订单状态_等待接单, userAccount.getCashDeposit(),
new ArrayList<>(gatheringChannelCodeMap.keySet()));
return MyWaitReceivingOrderVO.convertFor(waitReceivingOrders);
}
Map<String, List<Double>> gatheringChannelCodeMap = new HashMap<>();
for (GatheringCode gatheringCode : gatheringCodes) {
if (gatheringChannelCodeMap.get(gatheringCode.getGatheringChannelCode()) == null) {
gatheringChannelCodeMap.put(gatheringCode.getGatheringChannelCode(), new ArrayList<>());
}
if (userAccount.getCashDeposit() < gatheringCode.getGatheringAmount()) {
continue;
}
gatheringChannelCodeMap.get(gatheringCode.getGatheringChannelCode())
.add(gatheringCode.getGatheringAmount());
}
List<MerchantOrder> waitReceivingOrders = new ArrayList<>();
for (Entry<String, List<Double>> entry : gatheringChannelCodeMap.entrySet()) {
if (CollectionUtil.isEmpty(entry.getValue())) {
continue;
}
List<MerchantOrder> tmpOrders = merchantOrderRepo
.findTop10ByOrderStateAndGatheringAmountInAndGatheringChannelCodeOrderBySubmitTimeDesc(
Constant.商户订单状态_等待接单, entry.getValue(), entry.getKey());
waitReceivingOrders.addAll(tmpOrders);
}
Collections.sort(waitReceivingOrders, new Comparator<MerchantOrder>() {
@Override
public int compare(MerchantOrder o1, MerchantOrder o2) {
return o1.getSubmitTime().before(o2.getSubmitTime()) ? 1 : -1;
}
});
if (waitReceivingOrders.isEmpty()) {
return MyWaitReceivingOrderVO.convertFor(waitReceivingOrders);
}
return MyWaitReceivingOrderVO.convertFor(
waitReceivingOrders.subList(0, waitReceivingOrders.size() >= 10 ? 10 : waitReceivingOrders.size()));
}
@ParamValid
@Transactional
public MerchantOrderVO manualStartOrder(ManualStartOrderParam param) {
Merchant merchant = merchantRepo.findByMerchantNum(param.getMerchantNum());
if (merchant == null) {
throw new BizException(BizError.商户未接入);
}
String sign = param.getMerchantNum() + param.getOrderNo()
+ new DecimalFormat("###################.###########").format(param.getGatheringAmount())
+ param.getNotifyUrl() + merchant.getSecretKey();
sign = new Digester(DigestAlgorithm.MD5).digestHex(sign);
param.setSign(sign);
Integer orderEffectiveDuration = Constant.商户订单接单有效时长;
ReceiveOrderSetting setting = platformOrderSettingRepo.findTopByOrderByLatelyUpdateTime();
if (setting != null) {
orderEffectiveDuration = setting.getReceiveOrderEffectiveDuration();
}
MerchantOrder merchantOrder = param.convertToPo(merchant.getId(), orderEffectiveDuration);
MerchantOrderPayInfo payInfo = param.convertToPayInfoPo(merchantOrder.getId());
merchantOrder.setPayInfoId(payInfo.getId());
merchantOrderRepo.save(merchantOrder);
merchantOrderPayInfoRepo.save(payInfo);
return MerchantOrderVO.convertFor(merchantOrder);
}
/**
* 接单
*
* @param param
* @return
*/
@Lock(keys = "'receiveOrder_' + #orderId")
@Transactional
public void receiveOrder(@NotBlank String userAccountId, @NotBlank String orderId) {
List<GatheringCode> gatheringCodes = gatheringCodeRepo.findByUserAccountId(userAccountId);
if (CollectionUtil.isEmpty(gatheringCodes)) {
throw new BizException(BizError.未设置收款码无法接单);
}
MerchantOrder platformOrder = merchantOrderRepo.getOne(orderId);
if (platformOrder == null) {
throw new BizException(BizError.商户订单不存在);
}
if (!Constant.商户订单状态_等待接单.equals(platformOrder.getOrderState())) {
throw new BizException(BizError.订单已被接或已取消);
}
String gatheringCodeStorageId = getGatheringCodeStorageId(userAccountId,
platformOrder.getGatheringChannelCode(), platformOrder.getGatheringAmount());
if (StrUtil.isBlank(gatheringCodeStorageId)) {
throw new BizException(BizError.无法接单找不到对应金额的收款码);
}
// 校验用户是否达到接单上限,若达到上限,则不能接单
ReceiveOrderSetting setting = platformOrderSettingRepo.findTopByOrderByLatelyUpdateTime();
if (setting != null && setting.getReceiveOrderUpperLimit() != null) {
List<MyWaitConfirmOrderVO> waitConfirmOrders = findMyWaitConfirmOrder(userAccountId);
if (waitConfirmOrders.size() >= setting.getReceiveOrderUpperLimit()) {
throw new BizException(BizError.已达到接单数量上限);
}
}
UserAccount userAccount = userAccountRepo.getOne(userAccountId);
if (setting != null && setting.getCashDepositMinimumRequire() != null) {
if (userAccount.getCashDeposit() < setting.getCashDepositMinimumRequire()) {
throw new BizException(BizError.未达到接单保证金最低要求);
}
}
Double cashDeposit = NumberUtil.round(userAccount.getCashDeposit() - platformOrder.getGatheringAmount(), 4)
.doubleValue();
if (cashDeposit < 0) {
throw new BizException(BizError.保证金不足无法接单);
}
userAccount.setCashDeposit(cashDeposit);
userAccountRepo.save(userAccount);
Integer orderEffectiveDuration = Constant.商户订单支付有效时长;
if (setting != null && setting.getOrderPayEffectiveDuration() != null) {
orderEffectiveDuration = setting.getOrderPayEffectiveDuration();
}
platformOrder.updateReceived(userAccount.getId(), gatheringCodeStorageId);
platformOrder.updateUsefulTime(
DateUtil.offset(platformOrder.getReceivedTime(), DateField.MINUTE, orderEffectiveDuration));
merchantOrderRepo.save(platformOrder);
accountChangeLogRepo.save(AccountChangeLog.buildWithReceiveOrderDeduction(userAccount, platformOrder));
}
@Transactional(readOnly = true)
public PageResult<MerchantOrderVO> findMerchantOrderByPage(MerchantOrderQueryCondParam param) {
Specification<MerchantOrder> spec = new Specification<MerchantOrder>() {
/**
*
*/
private static final long serialVersionUID = 1L;
public Predicate toPredicate(Root<MerchantOrder> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
List<Predicate> predicates = new ArrayList<Predicate>();
if (StrUtil.isNotBlank(param.getOrderNo())) {
predicates.add(builder.equal(root.get("orderNo"), param.getOrderNo()));
}
if (StrUtil.isNotBlank(param.getPlatformName())) {
predicates.add(
builder.equal(root.join("merchant", JoinType.INNER).get("name"), param.getPlatformName()));
}
if (StrUtil.isNotBlank(param.getGatheringChannelCode())) {
predicates.add(builder.equal(root.get("gatheringChannelCode"), param.getGatheringChannelCode()));
}
if (StrUtil.isNotBlank(param.getOrderState())) {
predicates.add(builder.equal(root.get("orderState"), param.getOrderState()));
}
if (StrUtil.isNotBlank(param.getReceiverUserName())) {
predicates.add(builder.equal(root.join("userAccount", JoinType.INNER).get("userName"),
param.getReceiverUserName()));
}
if (param.getSubmitStartTime() != null) {
predicates.add(builder.greaterThanOrEqualTo(root.get("submitTime").as(Date.class),
DateUtil.beginOfDay(param.getSubmitStartTime())));
}
if (param.getSubmitEndTime() != null) {
predicates.add(builder.lessThanOrEqualTo(root.get("submitTime").as(Date.class),
DateUtil.endOfDay(param.getSubmitEndTime())));
}
if (param.getReceiveOrderStartTime() != null) {
predicates.add(builder.greaterThanOrEqualTo(root.get("receivedTime").as(Date.class),
DateUtil.beginOfDay(param.getReceiveOrderStartTime())));
}
if (param.getReceiveOrderEndTime() != null) {
predicates.add(builder.lessThanOrEqualTo(root.get("receivedTime").as(Date.class),
DateUtil.endOfDay(param.getReceiveOrderEndTime())));
}
return predicates.size() > 0 ? builder.and(predicates.toArray(new Predicate[predicates.size()])) : null;
}
};
Page<MerchantOrder> result = merchantOrderRepo.findAll(spec,
PageRequest.of(param.getPageNum() - 1, param.getPageSize(), Sort.by(Sort.Order.desc("submitTime"))));
PageResult<MerchantOrderVO> pageResult = new PageResult<>(MerchantOrderVO.convertFor(result.getContent()),
param.getPageNum(), param.getPageSize(), result.getTotalElements());
return pageResult;
}
@Transactional(readOnly = true)
public PageResult<ReceiveOrderRecordVO> findMyReceiveOrderRecordByPage(MyReceiveOrderRecordQueryCondParam param) {
Specification<MerchantOrder> spec = new Specification<MerchantOrder>() {
/**
*
*/
private static final long serialVersionUID = 1L;
public Predicate toPredicate(Root<MerchantOrder> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
List<Predicate> predicates = new ArrayList<Predicate>();
if (StrUtil.isNotBlank(param.getGatheringChannelCode())) {
predicates.add(builder.equal(root.get("gatheringChannelCode"), param.getGatheringChannelCode()));
}
if (StrUtil.isNotBlank(param.getReceiverUserName())) {
predicates.add(builder.equal(root.join("receivedAccount", JoinType.INNER).get("userName"),
param.getReceiverUserName()));
}
if (param.getReceiveOrderTime() != null) {
predicates.add(builder.greaterThanOrEqualTo(root.get("receivedTime").as(Date.class),
DateUtil.beginOfDay(param.getReceiveOrderTime())));
predicates.add(builder.lessThanOrEqualTo(root.get("receivedTime").as(Date.class),
DateUtil.endOfDay(param.getReceiveOrderTime())));
}
return predicates.size() > 0 ? builder.and(predicates.toArray(new Predicate[predicates.size()])) : null;
}
};
Page<MerchantOrder> result = merchantOrderRepo.findAll(spec,
PageRequest.of(param.getPageNum() - 1, param.getPageSize(), Sort.by(Sort.Order.desc("submitTime"))));
PageResult<ReceiveOrderRecordVO> pageResult = new PageResult<>(
ReceiveOrderRecordVO.convertFor(result.getContent()), param.getPageNum(), param.getPageSize(),
result.getTotalElements());
return pageResult;
}
/**
* 取消订单
*
* @param id
*/
@Transactional
public void cancelOrder(@NotBlank String id) {
MerchantOrder platformOrder = merchantOrderRepo.getOne(id);
if (!Constant.商户订单状态_等待接单.equals(platformOrder.getOrderState())) {
throw new BizException(BizError.只有等待接单状态的商户订单才能取消);
}
platformOrder.setOrderState(Constant.商户订单状态_人工取消);
platformOrder.setDealTime(new Date());
merchantOrderRepo.save(platformOrder);
}
/**
* 商户取消订单
*
* @param id
*/
@Transactional
public void merchatCancelOrder(@NotBlank String merchantId, @NotBlank String id) {
MerchantOrder platformOrder = merchantOrderRepo.getOne(id);
if (!merchantId.equals(platformOrder.getMerchantId())) {
throw new BizException(BizError.无权取消订单);
}
if (!Constant.商户订单状态_等待接单.equals(platformOrder.getOrderState())) {
throw new BizException(BizError.只有等待接单状态的商户订单才能取消);
}
platformOrder.setOrderState(Constant.商户订单状态_商户取消订单);
platformOrder.setDealTime(new Date());
merchantOrderRepo.save(platformOrder);
}
@Transactional
public void orderTimeoutDeal() {
Date now = new Date();
List<MerchantOrder> orders = merchantOrderRepo.findByOrderStateAndUsefulTimeLessThan(Constant.商户订单状态_等待接单, now);
for (MerchantOrder order : orders) {
order.setDealTime(now);
order.setOrderState(Constant.商户订单状态_超时取消);
merchantOrderRepo.save(order);
}
}
@ParamValid
@Transactional
public StartOrderSuccessVO startOrder(StartOrderParam param) {
Merchant merchant = merchantRepo.findByMerchantNum(param.getMerchantNum());
if (merchant == null) {
throw new BizException(BizError.商户未接入);
}
boolean unknownPayTypeFlag = true;
List<DictItemVO> payTypes = DictHolder.findDictItem("gatheringChannel");
for (DictItemVO payType : payTypes) {
if (payType.getDictItemCode().equals(param.getPayType())) {
unknownPayTypeFlag = false;
}
}
if (unknownPayTypeFlag) {
throw new BizException(BizError.不支持该支付类型);
}
String sign = param.getMerchantNum() + param.getOrderNo()
+ new DecimalFormat("###################.###########").format(param.getAmount()) + param.getNotifyUrl()
+ merchant.getSecretKey();
sign = new Digester(DigestAlgorithm.MD5).digestHex(sign);
if (!sign.equals(param.getSign())) {
throw new BizException(BizError.签名不正确);
}
Integer orderEffectiveDuration = Constant.商户订单接单有效时长;
ReceiveOrderSetting setting = platformOrderSettingRepo.findTopByOrderByLatelyUpdateTime();
if (setting != null) {
orderEffectiveDuration = setting.getReceiveOrderEffectiveDuration();
}
MerchantOrder merchantOrder = param.convertToPo(merchant.getId(), orderEffectiveDuration);
MerchantOrderPayInfo payInfo = param.convertToPayInfoPo(merchantOrder.getId());
merchantOrder.setPayInfoId(payInfo.getId());
merchantOrderRepo.save(merchantOrder);
merchantOrderPayInfoRepo.save(payInfo);
return StartOrderSuccessVO.convertFor(merchantOrder.getOrderNo());
}
/**
* 支付成功异步通知
*
* @param merchantOrderId
*/
@Transactional
public String paySuccessAsynNotice(@NotBlank String merchantOrderId) {
MerchantOrderPayInfo payInfo = merchantOrderPayInfoRepo.findByMerchantOrderId(merchantOrderId);
if (Constant.商户订单支付通知状态_通知成功.equals(payInfo.getNoticeState())) {
log.warn("商户订单支付已通知成功,无需重复通知;商户订单id为{}", merchantOrderId);
return Constant.商户订单通知成功返回值;
}
Merchant merchant = merchantRepo.findByMerchantNum(payInfo.getMerchantNum());
if (merchant == null) {
throw new BizException(BizError.商户未接入);
}
String sign = Constant.商户订单支付成功 + payInfo.getMerchantNum() + payInfo.getOrderNo()
+ new DecimalFormat("###################.###########").format(payInfo.getAmount())
+ merchant.getSecretKey();
sign = new Digester(DigestAlgorithm.MD5).digestHex(sign);
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("merchantNum", payInfo.getMerchantNum());
paramMap.put("orderNo", payInfo.getOrderNo());
paramMap.put("platformOrderNo", payInfo.getMerchantOrder().getOrderNo());
paramMap.put("amount", payInfo.getAmount());
paramMap.put("attch", payInfo.getAttch());
paramMap.put("state", Constant.商户订单支付成功);
paramMap.put("payTime",
DateUtil.format(payInfo.getMerchantOrder().getConfirmTime(), DatePattern.NORM_DATETIME_PATTERN));
paramMap.put("sign", sign);
String result = "fail";
// 通知3次
for (int i = 0; i < 3; i++) {
try {
result = HttpUtil.get(payInfo.getNotifyUrl(), paramMap, 2500);
if (Constant.商户订单通知成功返回值.equals(result)) {
break;
}
} catch (Exception e) {
result = e.getMessage();
log.error(MessageFormat.format("商户订单支付成功异步通知地址请求异常,id为{0}", merchantOrderId), e);
}
}
payInfo.setNoticeState(
Constant.商户订单通知成功返回值.equals(result) ? Constant.商户订单支付通知状态_通知成功 : Constant.商户订单支付通知状态_通知失败);
merchantOrderPayInfoRepo.save(payInfo);
return result;
}
@Transactional(readOnly = true)
public PageResult<ReceiveOrderRecordVO> findLowerLevelAccountReceiveOrderRecordByPage(
LowerLevelAccountReceiveOrderQueryCondParam param) {
UserAccount currentAccount = userAccountRepo.getOne(param.getCurrentAccountId());
UserAccount lowerLevelAccount = currentAccount;
if (StrUtil.isNotBlank(param.getUserName())) {
lowerLevelAccount = userAccountRepo.findByUserName(param.getUserName());
if (lowerLevelAccount == null) {
throw new BizException(BizError.用户名不存在);
}
// 说明该用户名对应的账号不是当前账号的下级账号
if (!lowerLevelAccount.getAccountLevelPath().startsWith(currentAccount.getAccountLevelPath())) {
throw new BizException(BizError.不是上级账号无权查看该账号及下级的接单记录);
}
}
String lowerLevelAccountId = lowerLevelAccount.getId();
String lowerLevelAccountLevelPath = lowerLevelAccount.getAccountLevelPath();
Specification<MerchantOrder> spec = new Specification<MerchantOrder>() {
/**
*
*/
private static final long serialVersionUID = 1L;
public Predicate toPredicate(Root<MerchantOrder> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
List<Predicate> predicates = new ArrayList<Predicate>();
if (StrUtil.isNotBlank(param.getUserName())) {
predicates.add(builder.equal(root.get("receivedAccountId"), lowerLevelAccountId));
} else {
predicates.add(builder.like(root.join("receivedAccount", JoinType.INNER).get("accountLevelPath"),
lowerLevelAccountLevelPath + "%"));
}
if (StrUtil.isNotBlank(param.getOrderState())) {
predicates.add(builder.equal(root.get("orderState"), param.getOrderState()));
}
if (StrUtil.isNotBlank(param.getGatheringChannelCode())) {
predicates.add(builder.equal(root.get("gatheringChannelCode"), param.getGatheringChannelCode()));
}
if (param.getStartTime() != null) {
predicates.add(builder.greaterThanOrEqualTo(root.get("receivedTime").as(Date.class),
DateUtil.beginOfDay(param.getStartTime())));
}
if (param.getEndTime() != null) {
predicates.add(builder.lessThanOrEqualTo(root.get("receivedTime").as(Date.class),
DateUtil.endOfDay(param.getEndTime())));
}
return predicates.size() > 0 ? builder.and(predicates.toArray(new Predicate[predicates.size()])) : null;
}
};
Page<MerchantOrder> result = merchantOrderRepo.findAll(spec,
PageRequest.of(param.getPageNum() - 1, param.getPageSize(), Sort.by(Sort.Order.desc("submitTime"))));
PageResult<ReceiveOrderRecordVO> pageResult = new PageResult<>(
ReceiveOrderRecordVO.convertFor(result.getContent()), param.getPageNum(), param.getPageSize(),
result.getTotalElements());
return pageResult;
}
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private MerchantOrderRepo merchantOrderRepo;
@Autowired
private MerchantOrderPayInfoRepo merchantOrderPayInfoRepo;
@Autowired
private MerchantRepo merchantRepo;
@Autowired
private UserAccountRepo userAccountRepo;
@Autowired
private GatheringCodeRepo gatheringCodeRepo;
@Autowired
private AccountChangeLogRepo accountChangeLogRepo;
@Autowired
private ReceiveOrderSettingRepo platformOrderSettingRepo;
@Autowired
private OrderRebateRepo orderRebateRepo;
@Transactional(readOnly = true)
public MerchantOrderDetailsVO findMerchantOrderDetailsById(@NotBlank String orderId) {
MerchantOrderDetailsVO vo = MerchantOrderDetailsVO.convertFor(merchantOrderRepo.getOne(orderId));
return vo;
}
/**
* 客服取消订单退款
*/
@Transactional
public void customerServiceCancelOrderRefund(@NotBlank String orderId) {
MerchantOrder merchantOrder = merchantOrderRepo.getOne(orderId);
if (!(Constant.商户订单状态_申诉中.equals(merchantOrder.getOrderState()))) {
throw new BizException(BizError.只有申诉中的商户订单才能取消订单退款);
}
UserAccount userAccount = merchantOrder.getReceivedAccount();
Double cashDeposit = NumberUtil.round(userAccount.getCashDeposit() + merchantOrder.getGatheringAmount(), 4)
.doubleValue();
userAccount.setCashDeposit(cashDeposit);
userAccountRepo.save(userAccount);
merchantOrder.customerCancelOrderRefund();
merchantOrderRepo.save(merchantOrder);
accountChangeLogRepo.save(AccountChangeLog.buildWithCustomerCancelOrderRefund(userAccount, merchantOrder));
}
// @Transactional
// public void merchantConfirmToPaid(@NotBlank String secretKey, @NotBlank
// String orderId) {
// Merchant merchant = merchantRepo.findByMerchantNum(secretKey);
// if (merchant == null) {
// throw new BizException(BizError.商户未接入);
// }
// MerchantOrder order = merchantOrderRepo.findById(orderId).orElse(null);
// if (order == null) {
// log.error("商家订单不存在;secretKey:{},orderId:{}", secretKey, orderId);
// throw new BizException(BizError.商户订单不存在);
// }
// if (!order.getMerchantId().equals(merchant.getId())) {
// log.error("无权更新商家订单状态为商户已确认支付;secretKey:{},orderId:{}", secretKey, orderId);
// throw new BizException(BizError.无权更新商户订单状态为商户已确认支付);
// }
// if (!Constant.商户订单状态_已接单.equals(order.getOrderState())) {
// throw new BizException(BizError.订单状态为已接单才能转为平台已确认支付);
// }
// order.merchantConfirmToPaid();
// merchantOrderRepo.save(order);
// }
@Transactional(readOnly = true)
public OrderGatheringCodeVO getOrderGatheringCode(@NotBlank String orderNo) {
MerchantOrder order = merchantOrderRepo.findByOrderNo(orderNo);
if (order == null) {
log.error("商户订单不存在;orderNo:{}", orderNo);
throw new BizException(BizError.商户订单不存在);
}
GatheringCode gatheringCode = getGatheringCode(order.getReceivedAccountId(),
order.getGatheringChannelCode(), order.getGatheringAmount());
OrderGatheringCodeVO vo = OrderGatheringCodeVO.convertFor(order);
vo.setGatheringCodeStorageId(gatheringCode.getStorageId());
vo.setGatheringCode(gatheringCode);
return vo;
}
@Transactional(readOnly = true)
public String getGatheringCodeStorageId(String receivedAccountId, String gatheringChannelCode,
Double gatheringAmount) {
ReceiveOrderSetting merchantOrderSetting = platformOrderSettingRepo.findTopByOrderByLatelyUpdateTime();
if (merchantOrderSetting.getUnfixedGatheringCodeReceiveOrder()) {
GatheringCode gatheringCode = gatheringCodeRepo
.findTopByUserAccountIdAndGatheringChannelCodeAndFixedGatheringAmountIsFalse(receivedAccountId,
gatheringChannelCode);
if (gatheringCode != null) {
return gatheringCode.getStorageId();
}
} else {
GatheringCode gatheringCode = gatheringCodeRepo
.findTopByUserAccountIdAndGatheringChannelCodeAndGatheringAmount(receivedAccountId,
gatheringChannelCode, gatheringAmount);
if (gatheringCode != null) {
return gatheringCode.getStorageId();
}
}
return null;
}
@Transactional(readOnly = true)
public GatheringCode getGatheringCode(String receivedAccountId, String gatheringChannelCode,
Double gatheringAmount) {
ReceiveOrderSetting merchantOrderSetting = platformOrderSettingRepo.findTopByOrderByLatelyUpdateTime();
if (merchantOrderSetting.getUnfixedGatheringCodeReceiveOrder()) {
GatheringCode gatheringCode = gatheringCodeRepo
.findTopByUserAccountIdAndGatheringChannelCodeAndFixedGatheringAmountIsFalse(receivedAccountId,
gatheringChannelCode);
if (gatheringCode != null) {
return gatheringCode;
}
} else {
GatheringCode gatheringCode = gatheringCodeRepo
.findTopByUserAccountIdAndGatheringChannelCodeAndGatheringAmount(receivedAccountId,
gatheringChannelCode, gatheringAmount);
if (gatheringCode != null) {
return gatheringCode;
}
}
return null;
}
@Transactional
public void userConfirmToPaid(@NotBlank String userAccountId, @NotBlank String orderId) {
MerchantOrder platformOrder = merchantOrderRepo.findByIdAndReceivedAccountId(orderId, userAccountId);
if (platformOrder == null) {
throw new BizException(BizError.商户订单不存在);
}
if (!(Constant.商户订单状态_已接单.equals(platformOrder.getOrderState())
|| Constant.商户订单状态_商户已确认支付.equals(platformOrder.getOrderState()))) {
throw new BizException(BizError.订单状态为已接单或平台已确认支付才能转为确认已支付);
}
platformOrder.confirmToPaid(null);
merchantOrderRepo.save(platformOrder);
receiveOrderBountySettlement(platformOrder);
}
/**
* 客服确认已支付
*/
@Transactional
public void customerServiceConfirmToPaid(@NotBlank String orderId, String note) {
MerchantOrder platformOrder = merchantOrderRepo.findById(orderId).orElse(null);
if (platformOrder == null) {
throw new BizException(BizError.商户订单不存在);
}
if (!Constant.商户订单状态_申诉中.equals(platformOrder.getOrderState())) {
throw new BizException(BizError.订单状态为申述中才能转为确认已支付);
}
platformOrder.confirmToPaid(note);
merchantOrderRepo.save(platformOrder);
receiveOrderBountySettlement(platformOrder);
}
/**
* 接单奖励金结算
*/
@Transactional
public void receiveOrderBountySettlement(MerchantOrder merchantOrder) {
UserAccount userAccount = merchantOrder.getReceivedAccount();
double bounty = NumberUtil.round(merchantOrder.getGatheringAmount() * userAccount.getRebate() * 0.01, 4)
.doubleValue();
merchantOrder.updateBounty(bounty);
merchantOrderRepo.save(merchantOrder);
userAccount.setCashDeposit(NumberUtil.round(userAccount.getCashDeposit() + bounty, 4).doubleValue());
userAccountRepo.save(userAccount);
accountChangeLogRepo
.save(AccountChangeLog.buildWithReceiveOrderBounty(userAccount, bounty, userAccount.getRebate()));
generateOrderRebate(merchantOrder);
ThreadPoolUtils.getPaidMerchantOrderPool().schedule(() -> {
redisTemplate.opsForList().leftPush(Constant.商户订单ID, merchantOrder.getId());
}, 1, TimeUnit.SECONDS);
}
/**
* 生成订单返点
*/
public void generateOrderRebate(MerchantOrder merchantOrder) {
UserAccount userAccount = merchantOrder.getReceivedAccount();
UserAccount superior = merchantOrder.getReceivedAccount().getInviter();
while (superior != null) {
double rebate = NumberUtil.round(superior.getRebate() - userAccount.getRebate(), 4).doubleValue();
if (rebate < 0) {
log.error("订单返点异常,下级账号的返点不能大于上级账号;下级账号id:{},上级账号id:{}", userAccount.getId(), superior.getId());
break;
}
double rebateAmount = NumberUtil.round(merchantOrder.getGatheringAmount() * rebate * 0.01, 4).doubleValue();
OrderRebate orderRebate = OrderRebate.build(rebate, rebateAmount, merchantOrder.getId(), superior.getId());
orderRebateRepo.save(orderRebate);
userAccount = superior;
superior = superior.getInviter();
}
}
@Transactional(readOnly = true)
public void orderRebateAutoSettlement() {
List<OrderRebate> orderRebates = orderRebateRepo.findBySettlementTimeIsNull();
for (OrderRebate orderRebate : orderRebates) {
redisTemplate.opsForList().leftPush(Constant.订单返点ID, orderRebate.getId());
}
}
/**
* 通知指定的订单进行返点结算
*/
@Transactional(readOnly = true)
public void noticeOrderRebateSettlement(@NotBlank String orderId) {
List<OrderRebate> orderRebates = orderRebateRepo.findByMerchantOrderId(orderId);
for (OrderRebate orderRebate : orderRebates) {
redisTemplate.opsForList().leftPush(Constant.订单返点ID, orderRebate.getId());
}
}
/**
* 订单返点结算
*/
@Transactional
public void orderRebateSettlement(@NotBlank String orderRebateId) {
OrderRebate orderRebate = orderRebateRepo.getOne(orderRebateId);
if (orderRebate.getSettlementTime() != null) {
log.warn("当前的订单返点记录已结算,无法重复结算;id:{}", orderRebateId);
return;
}
orderRebate.settlement();
orderRebateRepo.save(orderRebate);
UserAccount userAccount = orderRebate.getRebateAccount();
double cashDeposit = userAccount.getCashDeposit() + orderRebate.getRebateAmount();
userAccount.setCashDeposit(NumberUtil.round(cashDeposit, 4).doubleValue());
userAccountRepo.save(userAccount);
accountChangeLogRepo.save(AccountChangeLog.buildWithOrderRebate(userAccount, orderRebate));
}
@Transactional(readOnly = true)
public List<MyWaitConfirmOrderVO> findMyWaitConfirmOrder(@NotBlank String userAccountId) {
return MyWaitConfirmOrderVO
.convertFor(merchantOrderRepo.findByOrderStateInAndReceivedAccountIdOrderBySubmitTimeDesc(
Arrays.asList(Constant.商户订单状态_已接单, Constant.商户订单状态_商户已确认支付), userAccountId));
}
@Transactional(readOnly = true)
public List<MyWaitReceivingOrderVO> findMyWaitReceivingOrder(@NotBlank String userAccountId) {
UserAccount userAccount = userAccountRepo.getOne(userAccountId);
List<GatheringCode> gatheringCodes = gatheringCodeRepo.findByUserAccountId(userAccountId);
if (CollectionUtil.isEmpty(gatheringCodes)) {
throw new BizException(BizError.未设置收款码无法接单);
}
ReceiveOrderSetting merchantOrderSetting = platformOrderSettingRepo.findTopByOrderByLatelyUpdateTime();
if (merchantOrderSetting.getUnfixedGatheringCodeReceiveOrder()) {
Map<String, String> gatheringChannelCodeMap = new HashMap<>();
for (GatheringCode gatheringCode : gatheringCodes) {
gatheringChannelCodeMap.put(gatheringCode.getGatheringChannelCode(),
gatheringCode.getGatheringChannelCode());
}
List<MerchantOrder> waitReceivingOrders = merchantOrderRepo
.findTop10ByOrderStateAndGatheringAmountIsLessThanEqualAndGatheringChannelCodeInOrderBySubmitTimeDesc(
Constant.商户订单状态_等待接单, userAccount.getCashDeposit(),
new ArrayList<>(gatheringChannelCodeMap.keySet()));
return MyWaitReceivingOrderVO.convertFor(waitReceivingOrders);
}
Map<String, List<Double>> gatheringChannelCodeMap = new HashMap<>();
for (GatheringCode gatheringCode : gatheringCodes) {
if (gatheringChannelCodeMap.get(gatheringCode.getGatheringChannelCode()) == null) {
gatheringChannelCodeMap.put(gatheringCode.getGatheringChannelCode(), new ArrayList<>());
}
if (userAccount.getCashDeposit() < gatheringCode.getGatheringAmount()) {
continue;
}
gatheringChannelCodeMap.get(gatheringCode.getGatheringChannelCode())
.add(gatheringCode.getGatheringAmount());
}
List<MerchantOrder> waitReceivingOrders = new ArrayList<>();
for (Entry<String, List<Double>> entry : gatheringChannelCodeMap.entrySet()) {
if (CollectionUtil.isEmpty(entry.getValue())) {
continue;
}
List<MerchantOrder> tmpOrders = merchantOrderRepo
.findTop10ByOrderStateAndGatheringAmountInAndGatheringChannelCodeOrderBySubmitTimeDesc(
Constant.商户订单状态_等待接单, entry.getValue(), entry.getKey());
waitReceivingOrders.addAll(tmpOrders);
}
Collections.sort(waitReceivingOrders, new Comparator<MerchantOrder>() {
@Override
public int compare(MerchantOrder o1, MerchantOrder o2) {
return o1.getSubmitTime().before(o2.getSubmitTime()) ? 1 : -1;
}
});
if (waitReceivingOrders.isEmpty()) {
return MyWaitReceivingOrderVO.convertFor(waitReceivingOrders);
}
return MyWaitReceivingOrderVO.convertFor(
waitReceivingOrders.subList(0, waitReceivingOrders.size() >= 10 ? 10 : waitReceivingOrders.size()));
}
@ParamValid
@Transactional
public MerchantOrderVO manualStartOrder(ManualStartOrderParam param) {
Merchant merchant = merchantRepo.findByMerchantNum(param.getMerchantNum());
if (merchant == null) {
throw new BizException(BizError.商户未接入);
}
String sign = param.getMerchantNum() + param.getOrderNo()
+ new DecimalFormat("###################.###########").format(param.getGatheringAmount())
+ param.getNotifyUrl() + merchant.getSecretKey();
sign = new Digester(DigestAlgorithm.MD5).digestHex(sign);
param.setSign(sign);
Integer orderEffectiveDuration = Constant.商户订单接单有效时长;
ReceiveOrderSetting setting = platformOrderSettingRepo.findTopByOrderByLatelyUpdateTime();
if (setting != null) {
orderEffectiveDuration = setting.getReceiveOrderEffectiveDuration();
}
MerchantOrder merchantOrder = param.convertToPo(merchant.getId(), orderEffectiveDuration);
MerchantOrderPayInfo payInfo = param.convertToPayInfoPo(merchantOrder.getId());
merchantOrder.setPayInfoId(payInfo.getId());
merchantOrderRepo.save(merchantOrder);
merchantOrderPayInfoRepo.save(payInfo);
//todo this is temporary code 这里要匹配有资源的用户接单
List<UserAccount> userAccounts = userAccountRepo.findAllByAccountType(Constant.账号类型_会员);
;
this.receiveOrder(userAccounts.get(RandomUtil.randomInt(0, userAccounts.size())).getId(), merchantOrder.getId());
return MerchantOrderVO.convertFor(merchantOrder);
}
/**
* 接单
*/
@Lock(keys = "'receiveOrder_' + #orderId")
@Transactional
public void receiveOrder(@NotBlank String userAccountId, @NotBlank String orderId) {
List<GatheringCode> gatheringCodes = gatheringCodeRepo.findByUserAccountId(userAccountId);
if (CollectionUtil.isEmpty(gatheringCodes)) {
throw new BizException(BizError.未设置收款码无法接单);
}
MerchantOrder platformOrder = merchantOrderRepo.getOne(orderId);
if (platformOrder == null) {
throw new BizException(BizError.商户订单不存在);
}
if (!Constant.商户订单状态_等待接单.equals(platformOrder.getOrderState())) {
throw new BizException(BizError.订单已被接或已取消);
}
String gatheringCodeStorageId = getGatheringCodeStorageId(userAccountId,
platformOrder.getGatheringChannelCode(), platformOrder.getGatheringAmount());
//支付宝和微信才有收款码
if (StrUtil.isBlank(gatheringCodeStorageId) && !platformOrder.getGatheringChannelCode().equals(Constant.支付渠道_银行卡) ) {
throw new BizException(BizError.无法接单找不到对应金额的收款码);
}
// 校验用户是否达到接单上限,若达到上限,则不能接单
ReceiveOrderSetting setting = platformOrderSettingRepo.findTopByOrderByLatelyUpdateTime();
if (setting != null && setting.getReceiveOrderUpperLimit() != null) {
List<MyWaitConfirmOrderVO> waitConfirmOrders = findMyWaitConfirmOrder(userAccountId);
if (waitConfirmOrders.size() >= setting.getReceiveOrderUpperLimit()) {
throw new BizException(BizError.已达到接单数量上限);
}
}
UserAccount userAccount = userAccountRepo.getOne(userAccountId);
if (setting != null && setting.getCashDepositMinimumRequire() != null) {
if (userAccount.getCashDeposit() < setting.getCashDepositMinimumRequire()) {
throw new BizException(BizError.未达到接单保证金最低要求);
}
}
Double cashDeposit = NumberUtil.round(userAccount.getCashDeposit() - platformOrder.getGatheringAmount(), 4)
.doubleValue();
if (cashDeposit < 0) {
throw new BizException(BizError.保证金不足无法接单);
}
userAccount.setCashDeposit(cashDeposit);
userAccountRepo.save(userAccount);
Integer orderEffectiveDuration = Constant.商户订单支付有效时长;
if (setting != null && setting.getOrderPayEffectiveDuration() != null) {
orderEffectiveDuration = setting.getOrderPayEffectiveDuration();
}
platformOrder.updateReceived(userAccount.getId(), gatheringCodeStorageId);
platformOrder.updateUsefulTime(
DateUtil.offset(platformOrder.getReceivedTime(), DateField.MINUTE, orderEffectiveDuration));
merchantOrderRepo.save(platformOrder);
accountChangeLogRepo.save(AccountChangeLog.buildWithReceiveOrderDeduction(userAccount, platformOrder));
}
@Transactional(readOnly = true)
public PageResult<MerchantOrderVO> findMerchantOrderByPage(MerchantOrderQueryCondParam param) {
Specification<MerchantOrder> spec = new Specification<MerchantOrder>() {
/**
*
*/
private static final long serialVersionUID = 1L;
public Predicate toPredicate(Root<MerchantOrder> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
List<Predicate> predicates = new ArrayList<Predicate>();
if (StrUtil.isNotBlank(param.getOrderNo())) {
predicates.add(builder.equal(root.get("orderNo"), param.getOrderNo()));
}
if (StrUtil.isNotBlank(param.getPlatformName())) {
predicates.add(
builder.equal(root.join("merchant", JoinType.INNER).get("name"), param.getPlatformName()));
}
if (StrUtil.isNotBlank(param.getGatheringChannelCode())) {
predicates.add(builder.equal(root.get("gatheringChannelCode"), param.getGatheringChannelCode()));
}
if (StrUtil.isNotBlank(param.getOrderState())) {
predicates.add(builder.equal(root.get("orderState"), param.getOrderState()));
}
if (StrUtil.isNotBlank(param.getReceiverUserName())) {
predicates.add(builder.equal(root.join("userAccount", JoinType.INNER).get("userName"),
param.getReceiverUserName()));
}
if (param.getSubmitStartTime() != null) {
predicates.add(builder.greaterThanOrEqualTo(root.get("submitTime").as(Date.class),
DateUtil.beginOfDay(param.getSubmitStartTime())));
}
if (param.getSubmitEndTime() != null) {
predicates.add(builder.lessThanOrEqualTo(root.get("submitTime").as(Date.class),
DateUtil.endOfDay(param.getSubmitEndTime())));
}
if (param.getReceiveOrderStartTime() != null) {
predicates.add(builder.greaterThanOrEqualTo(root.get("receivedTime").as(Date.class),
DateUtil.beginOfDay(param.getReceiveOrderStartTime())));
}
if (param.getReceiveOrderEndTime() != null) {
predicates.add(builder.lessThanOrEqualTo(root.get("receivedTime").as(Date.class),
DateUtil.endOfDay(param.getReceiveOrderEndTime())));
}
return predicates.size() > 0 ? builder.and(predicates.toArray(new Predicate[predicates.size()])) : null;
}
};
Page<MerchantOrder> result = merchantOrderRepo.findAll(spec,
PageRequest.of(param.getPageNum() - 1, param.getPageSize(), Sort.by(Sort.Order.desc("submitTime"))));
PageResult<MerchantOrderVO> pageResult = new PageResult<>(MerchantOrderVO.convertFor(result.getContent()),
param.getPageNum(), param.getPageSize(), result.getTotalElements());
return pageResult;
}
@Transactional(readOnly = true)
public PageResult<ReceiveOrderRecordVO> findMyReceiveOrderRecordByPage(MyReceiveOrderRecordQueryCondParam param) {
Specification<MerchantOrder> spec = new Specification<MerchantOrder>() {
/**
*
*/
private static final long serialVersionUID = 1L;
public Predicate toPredicate(Root<MerchantOrder> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
List<Predicate> predicates = new ArrayList<Predicate>();
if (StrUtil.isNotBlank(param.getGatheringChannelCode())) {
predicates.add(builder.equal(root.get("gatheringChannelCode"), param.getGatheringChannelCode()));
}
if (StrUtil.isNotBlank(param.getReceiverUserName())) {
predicates.add(builder.equal(root.join("receivedAccount", JoinType.INNER).get("userName"),
param.getReceiverUserName()));
}
if (param.getReceiveOrderTime() != null) {
predicates.add(builder.greaterThanOrEqualTo(root.get("receivedTime").as(Date.class),
DateUtil.beginOfDay(param.getReceiveOrderTime())));
predicates.add(builder.lessThanOrEqualTo(root.get("receivedTime").as(Date.class),
DateUtil.endOfDay(param.getReceiveOrderTime())));
}
return predicates.size() > 0 ? builder.and(predicates.toArray(new Predicate[predicates.size()])) : null;
}
};
Page<MerchantOrder> result = merchantOrderRepo.findAll(spec,
PageRequest.of(param.getPageNum() - 1, param.getPageSize(), Sort.by(Sort.Order.desc("submitTime"))));
PageResult<ReceiveOrderRecordVO> pageResult = new PageResult<>(
ReceiveOrderRecordVO.convertFor(result.getContent()), param.getPageNum(), param.getPageSize(),
result.getTotalElements());
return pageResult;
}
/**
* 取消订单
*/
@Transactional
public void cancelOrder(@NotBlank String id) {
MerchantOrder platformOrder = merchantOrderRepo.getOne(id);
if (!Constant.商户订单状态_等待接单.equals(platformOrder.getOrderState())) {
throw new BizException(BizError.只有等待接单状态的商户订单才能取消);
}
platformOrder.setOrderState(Constant.商户订单状态_人工取消);
platformOrder.setDealTime(new Date());
merchantOrderRepo.save(platformOrder);
}
/**
* 商户取消订单
*/
@Transactional
public void merchatCancelOrder(@NotBlank String merchantId, @NotBlank String id) {
MerchantOrder platformOrder = merchantOrderRepo.getOne(id);
if (!merchantId.equals(platformOrder.getMerchantId())) {
throw new BizException(BizError.无权取消订单);
}
if (!Constant.商户订单状态_等待接单.equals(platformOrder.getOrderState())) {
throw new BizException(BizError.只有等待接单状态的商户订单才能取消);
}
platformOrder.setOrderState(Constant.商户订单状态_商户取消订单);
platformOrder.setDealTime(new Date());
merchantOrderRepo.save(platformOrder);
}
@Transactional
public void orderTimeoutDeal() {
Date now = new Date();
List<MerchantOrder> orders = merchantOrderRepo.findByOrderStateAndUsefulTimeLessThan(Constant.商户订单状态_等待接单, now);
for (MerchantOrder order : orders) {
order.setDealTime(now);
order.setOrderState(Constant.商户订单状态_超时取消);
merchantOrderRepo.save(order);
}
}
@ParamValid
@Transactional
public StartOrderSuccessVO startOrder(StartOrderParam param) {
Merchant merchant = merchantRepo.findByMerchantNum(param.getMerchantNum());
if (merchant == null) {
throw new BizException(BizError.商户未接入);
}
boolean unknownPayTypeFlag = true;
List<DictItemVO> payTypes = DictHolder.findDictItem("gatheringChannel");
for (DictItemVO payType : payTypes) {
if (payType.getDictItemCode().equals(param.getPayType())) {
unknownPayTypeFlag = false;
}
}
if (unknownPayTypeFlag) {
throw new BizException(BizError.不支持该支付类型);
}
String sign = param.getMerchantNum() + param.getOrderNo()
+ new DecimalFormat("###################.###########").format(param.getAmount()) + param.getNotifyUrl()
+ merchant.getSecretKey();
sign = new Digester(DigestAlgorithm.MD5).digestHex(sign);
if (!sign.equals(param.getSign())) {
throw new BizException(BizError.签名不正确);
}
Integer orderEffectiveDuration = Constant.商户订单接单有效时长;
ReceiveOrderSetting setting = platformOrderSettingRepo.findTopByOrderByLatelyUpdateTime();
if (setting != null) {
orderEffectiveDuration = setting.getReceiveOrderEffectiveDuration();
}
MerchantOrder merchantOrder = param.convertToPo(merchant.getId(), orderEffectiveDuration);
MerchantOrderPayInfo payInfo = param.convertToPayInfoPo(merchantOrder.getId());
merchantOrder.setPayInfoId(payInfo.getId());
merchantOrderRepo.save(merchantOrder);
merchantOrderPayInfoRepo.save(payInfo);
//todo this is temporary code 这里要匹配有资源的用户接单
List<UserAccount> userAccounts = userAccountRepo.findAllByAccountType(Constant.账号类型_会员);
;
this.receiveOrder(userAccounts.get(RandomUtil.randomInt(0, userAccounts.size())).getId(), merchantOrder.getId());
return StartOrderSuccessVO.convertFor(merchantOrder.getOrderNo());
}
/**
* 支付成功异步通知
*/
@Transactional
public String paySuccessAsynNotice(@NotBlank String merchantOrderId) {
MerchantOrderPayInfo payInfo = merchantOrderPayInfoRepo.findByMerchantOrderId(merchantOrderId);
if (Constant.商户订单支付通知状态_通知成功.equals(payInfo.getNoticeState())) {
log.warn("商户订单支付已通知成功,无需重复通知;商户订单id为{}", merchantOrderId);
return Constant.商户订单通知成功返回值;
}
Merchant merchant = merchantRepo.findByMerchantNum(payInfo.getMerchantNum());
if (merchant == null) {
throw new BizException(BizError.商户未接入);
}
String sign = Constant.商户订单支付成功 + payInfo.getMerchantNum() + payInfo.getOrderNo()
+ new DecimalFormat("###################.###########").format(payInfo.getAmount())
+ merchant.getSecretKey();
sign = new Digester(DigestAlgorithm.MD5).digestHex(sign);
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("merchantNum", payInfo.getMerchantNum());
paramMap.put("orderNo", payInfo.getOrderNo());
paramMap.put("platformOrderNo", payInfo.getMerchantOrder().getOrderNo());
paramMap.put("amount", payInfo.getAmount());
paramMap.put("attch", payInfo.getAttch());
paramMap.put("state", Constant.商户订单支付成功);
paramMap.put("payTime",
DateUtil.format(payInfo.getMerchantOrder().getConfirmTime(), DatePattern.NORM_DATETIME_PATTERN));
paramMap.put("sign", sign);
String result = "fail";
// 通知3次
for (int i = 0; i < 3; i++) {
try {
result = HttpUtil.get(payInfo.getNotifyUrl(), paramMap, 2500);
if (Constant.商户订单通知成功返回值.equals(result)) {
break;
}
} catch (Exception e) {
result = e.getMessage();
log.error(MessageFormat.format("商户订单支付成功异步通知地址请求异常,id为{0}", merchantOrderId), e);
}
}
payInfo.setNoticeState(
Constant.商户订单通知成功返回值.equals(result) ? Constant.商户订单支付通知状态_通知成功 : Constant.商户订单支付通知状态_通知失败);
merchantOrderPayInfoRepo.save(payInfo);
return result;
}
@Transactional(readOnly = true)
public PageResult<ReceiveOrderRecordVO> findLowerLevelAccountReceiveOrderRecordByPage(
LowerLevelAccountReceiveOrderQueryCondParam param) {
UserAccount currentAccount = userAccountRepo.getOne(param.getCurrentAccountId());
UserAccount lowerLevelAccount = currentAccount;
if (StrUtil.isNotBlank(param.getUserName())) {
lowerLevelAccount = userAccountRepo.findByUserName(param.getUserName());
if (lowerLevelAccount == null) {
throw new BizException(BizError.用户名不存在);
}
// 说明该用户名对应的账号不是当前账号的下级账号
if (!lowerLevelAccount.getAccountLevelPath().startsWith(currentAccount.getAccountLevelPath())) {
throw new BizException(BizError.不是上级账号无权查看该账号及下级的接单记录);
}
}
String lowerLevelAccountId = lowerLevelAccount.getId();
String lowerLevelAccountLevelPath = lowerLevelAccount.getAccountLevelPath();
Specification<MerchantOrder> spec = new Specification<MerchantOrder>() {
/**
*
*/
private static final long serialVersionUID = 1L;
public Predicate toPredicate(Root<MerchantOrder> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
List<Predicate> predicates = new ArrayList<Predicate>();
if (StrUtil.isNotBlank(param.getUserName())) {
predicates.add(builder.equal(root.get("receivedAccountId"), lowerLevelAccountId));
} else {
predicates.add(builder.like(root.join("receivedAccount", JoinType.INNER).get("accountLevelPath"),
lowerLevelAccountLevelPath + "%"));
}
if (StrUtil.isNotBlank(param.getOrderState())) {
predicates.add(builder.equal(root.get("orderState"), param.getOrderState()));
}
if (StrUtil.isNotBlank(param.getGatheringChannelCode())) {
predicates.add(builder.equal(root.get("gatheringChannelCode"), param.getGatheringChannelCode()));
}
if (param.getStartTime() != null) {
predicates.add(builder.greaterThanOrEqualTo(root.get("receivedTime").as(Date.class),
DateUtil.beginOfDay(param.getStartTime())));
}
if (param.getEndTime() != null) {
predicates.add(builder.lessThanOrEqualTo(root.get("receivedTime").as(Date.class),
DateUtil.endOfDay(param.getEndTime())));
}
return predicates.size() > 0 ? builder.and(predicates.toArray(new Predicate[predicates.size()])) : null;
}
};
Page<MerchantOrder> result = merchantOrderRepo.findAll(spec,
PageRequest.of(param.getPageNum() - 1, param.getPageSize(), Sort.by(Sort.Order.desc("submitTime"))));
PageResult<ReceiveOrderRecordVO> pageResult = new PageResult<>(
ReceiveOrderRecordVO.convertFor(result.getContent()), param.getPageNum(), param.getPageSize(),
result.getTotalElements());
return pageResult;
}
}
......@@ -8,6 +8,7 @@ import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import me.zohar.runscore.dictconfig.DictHolder;
import me.zohar.runscore.gatheringcode.domain.GatheringCode;
import me.zohar.runscore.merchant.domain.MerchantOrder;
@Data
......@@ -58,6 +59,8 @@ public class OrderGatheringCodeVO {
private String gatheringCodeUrl;
private GatheringCode gatheringCode;
/**
* 同步通知地址
*/
......@@ -75,4 +78,5 @@ public class OrderGatheringCodeVO {
return vo;
}
}
......@@ -32,6 +32,7 @@ public class LoginLog {
/**
* 登录系统
*/
@Column(name="`system`")
private String system;
/**
......
......@@ -3,6 +3,8 @@ package me.zohar.runscore.useraccount.repo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import java.util.List;
import me.zohar.runscore.useraccount.domain.UserAccount;
......@@ -12,4 +14,5 @@ public interface UserAccountRepo extends JpaRepository<UserAccount, String>, Jpa
Long countByInviterId(String inviterId);
List<UserAccount> findAllByAccountType(String accountType);
}
......@@ -19,6 +19,11 @@ public class ApiController {
@Autowired
private MerchantOrderService platformOrderService;
/**
* 商户开单,获取支付方式,返回银行卡信息或者支付码信息
* @param param
* @return
*/
@PostMapping("/startOrder")
@ResponseBody
public Result startOrder(StartOrderParam param) {
......
......@@ -15,11 +15,12 @@ public class StartOrderTest {
*/
public static void main(String[] args) {
String merchantNum = "201906001";
String merchantOrderNo = "20190629023134U936283877";
String merchantNum = "1001";
String merchantOrderNo = "20190629023134U936283878";
Double amount = 100d;
String notifyUrl = "http://xhbc10.com/index.php/Pay/Paynotify";
String secretKey = "l54x9426o68962464";
//String returnUrl = "http://xhbc10.com/index.php/Pay/Paynotify";
String secretKey = "456";
String sign = merchantNum + merchantOrderNo
+ new DecimalFormat("###################.###########").format(amount) + notifyUrl + secretKey;
System.out.println(sign);
......
......@@ -135,9 +135,12 @@ var gatheringCodeVM = new Vue({
that.editGatheringCode = {
gatheringChannelCode : '',
state : '',
fixedGatheringAmount : true,
fixedGatheringAmount : false,
gatheringAmount : '',
payee : ''
payee : '',
bankAddress:'',
bankCode:'',
bankUsername:''
};
that.showEditGatheringCodePageInner();
that.initFileUploadWidget();
......@@ -187,24 +190,24 @@ var gatheringCodeVM = new Vue({
});
return;
}
if (editGatheringCode.fixedGatheringAmount == null) {
layer.alert('请选择是否固定收款金额', {
title : '提示',
icon : 7,
time : 3000
});
return;
}
if (editGatheringCode.fixedGatheringAmount) {
if (editGatheringCode.gatheringAmount == null || editGatheringCode.gatheringAmount == '') {
layer.alert('请输入收款金额', {
title : '提示',
icon : 7,
time : 3000
});
return;
}
}
// if (editGatheringCode.fixedGatheringAmount == null) {
// layer.alert('请选择是否固定收款金额', {
// title : '提示',
// icon : 7,
// time : 3000
// });
// return;
// }
// if (editGatheringCode.fixedGatheringAmount) {
// if (editGatheringCode.gatheringAmount == null || editGatheringCode.gatheringAmount == '') {
// layer.alert('请输入收款金额', {
// title : '提示',
// icon : 7,
// time : 3000
// });
// return;
// }
// }
if (editGatheringCode.payee == null || editGatheringCode.payee == '') {
layer.alert('请选择收款人', {
title : '提示',
......@@ -214,11 +217,12 @@ var gatheringCodeVM = new Vue({
return;
}
if ($('.gathering-code-pic').fileinput('getPreview').content.length != 0) {
if ($('.gathering-code-pic').fileinput('getPreview').content.length != 0 || editGatheringCode.gatheringChannelCode =='bankcard') {
that.addOrUpdateGatheringCodeInner();
} else {
var filesCount = $('.gathering-code-pic').fileinput('getFilesCount');
if (filesCount == 0) {
console.log(editGatheringCode.gatheringChannelCode);
if (filesCount == 0 ) {
layer.alert('请选择要上传的图片', {
title : '提示',
icon : 7,
......
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>收款码</title>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/popper.js/1.12.5/umd/popper.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/js/bootstrap.min.js"></script>
<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
<script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
<script src="https://cdn.bootcss.com/dayjs/1.7.8/dayjs.min.js"></script>
<script src="https://cdn.bootcss.com/layer/2.3/layer.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/5.0.1/css/fileinput.min.css" media="all" rel="stylesheet" type="text/css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/5.0.1/js/fileinput.min.js"></script>
<script src="/js/common/common.js"></script>
<link href="/css/common/common.css" rel="stylesheet" type="text/css">
<style type="text/css">
.account-change {
background-color: #fff;;
margin-bottom: 1rem;
display: flex;
padding-left: 1.2rem;
padding-right: 0.2rem;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>收款码</title>
<link rel="stylesheet"
href="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/popper.js/1.12.5/umd/popper.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/js/bootstrap.min.js"></script>
<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
<script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
<script src="https://cdn.bootcss.com/dayjs/1.7.8/dayjs.min.js"></script>
<script src="https://cdn.bootcss.com/layer/2.3/layer.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/5.0.1/css/fileinput.min.css"
media="all" rel="stylesheet" type="text/css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/5.0.1/js/fileinput.min.js"></script>
<script src="/js/common/common.js"></script>
<link href="/css/common/common.css" rel="stylesheet" type="text/css">
<style type="text/css">
.account-change {
background-color: #fff;;
margin-bottom: 1rem;
display: flex;
padding-left: 1.2rem;
padding-right: 0.2rem;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
.account-change-body {
flex: 4;
display: flex;
flex-direction: column;
}
.account-change-body {
flex: 4;
display: flex;
flex-direction: column;
}
.account-change-body-item label {
text-align: end;
width: 5rem;
margin-right: 0.5rem;
}
.account-change-body-item label {
text-align: end;
width: 5rem;
margin-right: 0.5rem;
}
.account-change-body-item span {
min-width: 5rem;
display: inline-block;
}
.account-change-body-item span {
min-width: 5rem;
display: inline-block;
}
.account-change-body-item button {
width: 48%;
}
.account-change-body-item button {
width: 48%;
}
.account-change-body-item-highlight {
color: #c3606a;
}
.account-change-body-item-highlight {
color: #c3606a;
}
.page-link {
color: #007bff !important
}
</style>
.page-link {
color: #007bff !important
}
</style>
</head>
<body>
<div th:replace="common/header::html"></div>
<div id="gatheringCode" v-cloak>
<div class="page-body" style="background: #f2f2f2;" v-show="showGatheringCodeFlag">
<button type="button" style="margin-top: 0.3rem;" class="btn btn-outline-info btn-lg btn-block" v-on:click="showEditGatheringCodePage()">添加收款码</button>
<div class="input-group" style="padding-bottom: 0.3rem; padding-top: 0.3rem;">
<select class="form-control" style="width: 2.2rem; height: 3rem;" v-model="state">
<option value="">状态</option>
<option v-for="dictItem in gatheringCodeStateDictItems" :value="dictItem.dictItemCode">{{dictItem.dictItemName}}</option>
</select> <select class="form-control" style="width: 6.2rem; height: 3rem;" v-model="gatheringChannelCode">
<option value="">收款渠道</option>
<option v-for="dictItem in gatheringChannelDictItems" :value="dictItem.dictItemCode">{{dictItem.dictItemName}}</option>
</select>
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" v-on:click="query">查询</button>
</div>
</div>
<div class="account-change" v-for="gatheringCode in gatheringCodes">
<div class="account-change-body">
<div class="account-change-body-item">
<label>创建时间:</label> <span>{{gatheringCode.createTime}}</span>
</div>
<div class="account-change-body-item">
<label>收款渠道:</label> <span>{{gatheringCode.gatheringChannelName}}</span><label>状态:</label> <span>{{gatheringCode.stateName}}</span>
</div>
<div class="account-change-body-item">
<label> 收款金额: </label> <span class="account-change-body-item-highlight">{{gatheringCode.fixedGatheringAmount ? gatheringCode.gatheringAmount + '元' : '不固定'}}</span><label>收款人:</label> <span class="account-change-body-item-highlight">{{gatheringCode.payee}}</span>
</div>
<div class="account-change-body-item">
<button class="btn btn-outline-info btn-lg" type="button" v-on:click="showEditGatheringCodePage(gatheringCode.id)">编辑</button>
<button class="btn btn-outline-danger btn-lg" type="button" v-on:click="delGatheringCode(gatheringCode.id)">删除</button>
</div>
</div>
</div>
<div style="padding-left: 13rem;">
<ul class="pagination">
<li class="page-item"><a class="page-link" v-show="totalPage > 0 && pageNum > 1" v-on:click="prePage">上一页</a></li>
<li class="page-item"><a class="page-link" v-show="pageNum >= 1 && pageNum < totalPage" v-on:click="nextPage">下一页</a></li>
</ul>
</div>
</div>
<div class="page-body" style="background: #f2f2f2;" v-show="showEditGatheringCodeFlag">
<div class="container" style="margin-top: 1.3rem;">
<form>
<div class="form-group">
<label>收款渠道:</label> <select class="form-control" v-model="editGatheringCode.gatheringChannelCode" @change="alert(editGatheringCode.gatheringChannelCode);">
<option value="">请选择</option>
<option v-for="dictItem in gatheringChannelDictItems" :value="dictItem.dictItemCode">{{dictItem.dictItemName}}</option>
</select>
</div>
<div class="form-group">
<label>状态:</label> <select class="form-control" v-model="editGatheringCode.state">
<option value="">请选择</option>
<option v-for="dictItem in gatheringCodeStateDictItems" :value="dictItem.dictItemCode">{{dictItem.dictItemName}}</option>
</select>
</div>
<!--<div class="form-group">
<label> <span> 收款金额:</span>
<div class="custom-control custom-checkbox custom-control-inline" v-on:click="switchGatheringAmountMode">
<input type="checkbox" id="fixedGatheringAmount" class="custom-control-input" v-model="editGatheringCode.fixedGatheringAmount">
<label for="fixedGatheringAmount" class="custom-control-label">固定收款金额</label>
</div>
</label> <input type="number" class="form-control" v-model="editGatheringCode.gatheringAmount" :disabled="!editGatheringCode.fixedGatheringAmount">
</div>-->
<div class="form-group">
<label>收款人:</label> <input type="text" class="form-control" v-model="editGatheringCode.payee">
</div>
<div class="form-group" v-show="editGatheringCode.gatheringChannelCode == 'bankcard'" style=""><label>银行卡号:</label> <input type="text" class="form-control"> <label>开户行:</label> <input type="text" class="form-control"> <label>卡姓名:</label> <input type="text" class="form-control"></div>
<div class="form-group" v-show="editGatheringCode.gatheringChannelCode != 'bankcard'">
<label>收款码:</label> <input type="file" class="form-control gathering-code-pic">
</div>
<button type="button" class="btn btn-danger btn-lg btn-block" v-on:click="addOrUpdateGatheringCode">保存</button>
<button type="button" class="btn btn-light btn-lg btn-block" v-on:click="hideEditGatheringCodePage">返回</button>
</form>
<div th:replace="common/header::html"></div>
<div id="gatheringCode" v-cloak>
<div class="page-body" style="background: #f2f2f2;" v-show="showGatheringCodeFlag">
<button type="button" style="margin-top: 0.3rem;"
class="btn btn-outline-info btn-lg btn-block"
v-on:click="showEditGatheringCodePage()">添加收款码
</button>
<div class="input-group" style="padding-bottom: 0.3rem; padding-top: 0.3rem;">
<select class="form-control" style="width: 2.2rem; height: 3rem;" v-model="state">
<option value="">状态</option>
<option v-for="dictItem in gatheringCodeStateDictItems"
:value="dictItem.dictItemCode">{{dictItem.dictItemName}}
</option>
</select> <select class="form-control" style="width: 6.2rem; height: 3rem;"
v-model="gatheringChannelCode">
<option value="">收款渠道</option>
<option v-for="dictItem in gatheringChannelDictItems" :value="dictItem.dictItemCode">
{{dictItem.dictItemName}}
</option>
</select>
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" v-on:click="query">查询
</button>
</div>
</div>
<div class="account-change" v-for="gatheringCode in gatheringCodes">
<div class="account-change-body">
<div class="account-change-body-item">
<label>创建时间:</label> <span>{{gatheringCode.createTime}}</span>
</div>
<div class="account-change-body-item">
<label>收款渠道:</label> <span>{{gatheringCode.gatheringChannelName}}</span><label>状态:</label>
<span>{{gatheringCode.stateName}}</span>
</div>
<div class="account-change-body-item">
<label> 收款金额: </label> <span class="account-change-body-item-highlight">{{gatheringCode.fixedGatheringAmount ? gatheringCode.gatheringAmount + '元' : '不固定'}}</span><label>收款人:</label>
<span class="account-change-body-item-highlight">{{gatheringCode.payee}}</span>
</div>
<div class="account-change-body-item">
<button class="btn btn-outline-info btn-lg" type="button"
v-on:click="showEditGatheringCodePage(gatheringCode.id)">编辑
</button>
<button class="btn btn-outline-danger btn-lg" type="button"
v-on:click="delGatheringCode(gatheringCode.id)">删除
</button>
</div>
</div>
</div>
<div style="padding-left: 13rem;">
<ul class="pagination">
<li class="page-item"><a class="page-link" v-show="totalPage > 0 && pageNum > 1"
v-on:click="prePage">上一页</a></li>
<li class="page-item"><a class="page-link"
v-show="pageNum >= 1 && pageNum < totalPage"
v-on:click="nextPage">下一页</a></li>
</ul>
</div>
</div>
<div class="page-body" style="background: #f2f2f2;" v-show="showEditGatheringCodeFlag">
<div class="container" style="margin-top: 1.3rem;">
<form>
<div class="form-group">
<label>收款渠道:</label> <select class="form-control"
v-model="editGatheringCode.gatheringChannelCode">
<option value="">请选择</option>
<option v-for="dictItem in gatheringChannelDictItems"
:value="dictItem.dictItemCode">{{dictItem.dictItemName}}
</option>
</select>
</div>
<div class="form-group">
<label>状态:</label> <select class="form-control"
v-model="editGatheringCode.state">
<option value="">请选择</option>
<option v-for="dictItem in gatheringCodeStateDictItems"
:value="dictItem.dictItemCode">{{dictItem.dictItemName}}
</option>
</select>
</div>
<!--<div class="form-group">
<label> <span> 收款金额:</span>
<div class="custom-control custom-checkbox custom-control-inline" v-on:click="switchGatheringAmountMode">
<input type="checkbox" id="fixedGatheringAmount" class="custom-control-input" v-model="editGatheringCode.fixedGatheringAmount">
<label for="fixedGatheringAmount" class="custom-control-label">固定收款金额</label>
</div>
</label> <input type="number" class="form-control" v-model="editGatheringCode.gatheringAmount" :disabled="!editGatheringCode.fixedGatheringAmount">
</div>-->
<div class="form-group">
<label>收款人:</label> <input type="text" class="form-control"
v-model="editGatheringCode.payee">
</div>
<div class="form-group"
v-show="editGatheringCode.gatheringChannelCode == 'bankcard'" style="">
<label>银行卡号:</label>
<input type="text" class="form-control" v-model="editGatheringCode.bankCode">
<label>开户行:</label>
<input type="text" class="form-control" v-model="editGatheringCode.bankAddress">
<label>卡户主:</label>
<input type="text" class="form-control" v-model="editGatheringCode.bankUsername">
</div>
<div class="form-group"
v-show="editGatheringCode.gatheringChannelCode != 'bankcard'">
<label>收款码:</label> <input type="file" class="form-control gathering-code-pic">
</div>
<button type="button" class="btn btn-danger btn-lg btn-block"
v-on:click="addOrUpdateGatheringCode">保存
</button>
<button type="button" class="btn btn-light btn-lg btn-block"
v-on:click="hideEditGatheringCodePage">返回
</button>
</form>
</div>
</div>
</div>
<div th:replace="common/footer::html"></div>
<script type="text/javascript" src="/js/gathering-code.js"></script>
</div>
</div>
</div>
<div th:replace="common/footer::html"></div>
<script type="text/javascript" src="/js/gathering-code.js"></script>
</body>
</html>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论