支付相关

localizer
ljw 2025-10-22 16:09:10 +08:00
parent e5bc14b9d7
commit 6da4776db7
9 changed files with 116 additions and 100 deletions

View File

@ -6,7 +6,6 @@ import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import org.simpleframework.xml.Transient;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@ -78,7 +77,7 @@ public class GoodsInfoEntity {
private String memo;
/**
* 1--> 2-->
* in--> out-->
*/
private String moneyWay;

View File

@ -0,0 +1,19 @@
package com.njzscloud.supervisory.order.contant;
import com.njzscloud.common.core.ienum.DictStr;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* money_way
*
*/
@Getter
@RequiredArgsConstructor
public enum MoneyWay implements DictStr {
IN("in", "入场计费"),
OUT("out", "出场计费"),
;
private final String val;
private final String txt;
}

View File

@ -12,7 +12,8 @@ import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public enum SettlementWay implements DictStr {
MONTH("month", "月结"),
BALANCE("balance", "余额")
BALANCE("balance", "余额"),
CASH("cash", "现付")
;
private final String val;
private final String txt;

View File

@ -72,4 +72,9 @@ public class OrderGoodsEntity {
*/
private BigDecimal taxRate;
/**
* in--> out-->
*/
private String moneyWay;
}

View File

@ -274,6 +274,8 @@ public class OrderPagingResult {
*/
private MoneyStrategy moneyStrategy;
private String moneyWay;
/**
* Id
*/

View File

@ -117,9 +117,9 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
.setAssignmentTransTime(transCompanyId == null ? null : LocalDateTime.now());
this.save(orderInfoEntity);
if (transCompanyId != null) {
/*if (transCompanyId != null) {
settleForTransCompany(this.getById(orderInfoEntity.getId()), 0);
}
}*/
Long orderId = orderInfoEntity.getId();
OrderCategory orderCategory = addOrderInfoParam.getOrderCategory();
@ -629,16 +629,15 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
Assert.isNull(orderInfo.getDriverId(), () -> Exceptions.clierr("当前订单已分配司机,无需重复分配"));
Assert.isTrue(orderInfo.getOrderStatus() == OrderStatus.DaiPaiDan, () -> Exceptions.clierr("当前订单状态,无法分配司机"));
// 查询订单及相关支付上下文
/*PaymentContextResult ctx = paymentContext(orderInfo.getId());
if (PaymentWay.COMPANY.getVal().equals(orderInfo.getPaymentCategory()) &&
SettlementWay.BALANCE.getVal().equals(ctx.getSettlementWay())) {
// 当该笔订单支付方式为公司支付,并且支付方式为余额支付时,需在分配之前查询当前清运公司余额是否充足,
// 如果不足则提示余额不足,不允许在派司机
PaymentContextResult ctx = paymentContext(orderInfo.getId());
if (SettlementWay.BALANCE.getVal().equals(ctx.getSettlementWay())) {
// 如果该笔订单的清运公司支付方式为余额支付时,需在分配之前查询当前清运公司余额是否充足,
// 不足则提示余额不足,不允许在派司机
if (ctx.getCompanyBalance().compareTo(BigDecimal.ZERO) < 0) {
// 已经是负数,禁止再次支付
throw Exceptions.clierr("公司账户余额不足");
}
}*/
}
baseMapper.busyDriver(driverId, Boolean.TRUE);
this.updateById(new OrderInfoEntity()
@ -662,8 +661,8 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
.setAssignmentTransTime(LocalDateTime.now())
.setOrderStatus(OrderStatus.DaiPaiDan)
);
OrderInfoEntity orderInfoEntity = this.getById(orderInfoId);
settleForTransCompany(orderInfoEntity, 0);
// OrderInfoEntity orderInfoEntity = this.getById(orderInfoId);
// settleForTransCompany(orderInfoEntity, 0);
return true;
}
@ -709,15 +708,35 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
Assert.isTrue(orderInfo.getAuditStatus() == AuditStatus.TongGuo, () -> Exceptions.clierr("当前订单未审核完成,无法开始运输"));
Long orderInfoId = orderInfo.getId();
// 判断支付方式,如果为公司支付,在此处直接扣减
// handleCompanyPay(orderInfo);
OrderGoodsEntity entity = orderGoodsService.getById(orderInfo.getGoodsId());
Assert.notNull(entity, () -> Exceptions.clierr("产品不存在"));
if (MoneyWay.IN.getVal().equals(entity.getMoneyWay())) {
// 当计费方式为入场计费时,并且是需要公司支付,我们需要再此次添加订单付费项,并计算好费用
settleForTransCompany(orderInfo, entity, 0);
// 处理公司支付
handleCompanyPay(orderInfo);
// 更新订单支付状态为已支付
this.updateById(new OrderInfoEntity()
.setId(orderInfoId)
.setCargoPhoto(startTransportOrderParam.getCargoPhoto())
.setOrderStatus(OrderStatus.QingYunZhong)
.setTransTime(LocalDateTime.now())
.setPaymentStatus(PaymentStatus.YiZhiFu)
.setPaymentCategory(PaymentWay.COMPANY.getVal())
.setPayTime(LocalDateTime.now())
);
} else {
this.updateById(new OrderInfoEntity()
.setId(orderInfoId)
.setCargoPhoto(startTransportOrderParam.getCargoPhoto())
.setOrderStatus(OrderStatus.QingYunZhong)
.setTransTime(LocalDateTime.now())
);
}
this.updateById(new OrderInfoEntity()
.setId(orderInfoId)
.setCargoPhoto(startTransportOrderParam.getCargoPhoto())
.setOrderStatus(OrderStatus.QingYunZhong)
.setTransTime(LocalDateTime.now())
);
Long truckId = orderInfo.getTruckId();
Assert.notNull(truckId, () -> Exceptions.clierr("订单未分配车辆"));
BizTruckEntity truckInfo = baseMapper.getTruckInfo(truckId);
@ -751,8 +770,8 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
public void handleCompanyPay(OrderInfoEntity orderInfo) {
PaymentContextResult ctx = paymentContext(orderInfo.getId());
if (PaymentWay.COMPANY.getVal().equals(orderInfo.getPaymentCategory())) {
// 验证资金账户信息
if (!SettlementWay.CASH.getVal().equals(ctx.getSettlementWay())) {
/*// 验证资金账户信息
if (ctx.getCompanyAccountId() == null) {
throw Exceptions.clierr("公司资金账户不存在");
}
@ -766,7 +785,7 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
// 已经是负数,禁止再次支付
throw Exceptions.clierr("公司账户余额不足");
}
}
}*/
BigDecimal oldBalance = ctx.getCompanyBalance();
BigDecimal newBalance = oldBalance.subtract(ctx.getSettleMoney());
@ -793,7 +812,6 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
log.info("公司账户扣减成功用户ID{},扣减金额:{},余额:{} -> {},结算方式:{}",
ctx.getCompanyUserId(), ctx.getSettleMoney(), oldBalance, newBalance, ctx.getSettlementWay());
}
}
@ -1040,7 +1058,25 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
// 1) 复制“产品”到 order_expense_items
// 2) 从 expense_items_config 读取可用付费项并按 scope 过滤all / customer_type=QiYe|GeTi / customer 包含 trans_company_id
// 3) 合并集合,计算 total_money 与 settle_money并批量落库。
// settleForTransCompany(orderInfoEntity, settleWeight);
OrderGoodsEntity entity = orderGoodsService.getById(orderInfoEntity.getGoodsId());
Assert.notNull(entity, () -> Exceptions.clierr("产品不存在"));
// 出厂付费
if (MoneyWay.OUT.getVal().equals(entity.getMoneyWay())) {
// 计算费用
settleForTransCompany(orderInfoEntity, entity, settleWeight);
// 扣费
handleCompanyPay(orderInfoEntity);
// 更新订单支付状态为已支付
this.updateById(new OrderInfoEntity()
.setId(orderInfoEntity.getId())
.setPaymentStatus(PaymentStatus.YiZhiFu)
.setPaymentCategory(PaymentWay.COMPANY.getVal())
.setPayTime(LocalDateTime.now())
);
}
} finally {
// 关闭 GPS
BizTruckEntity truckInfo = baseMapper.getTruckInfo(truckId);
@ -1056,10 +1092,8 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
* 3. total_money=quantity*unit_pricesettle_money=total_money+discount_money+revise_money
*/
@Transactional(rollbackFor = Exception.class)
public void settleForTransCompany(OrderInfoEntity orderInfoEntity, Integer settleWeight) {
public void settleForTransCompany(OrderInfoEntity orderInfoEntity, OrderGoodsEntity orderGoods, Integer settleWeight) {
Long orderId = orderInfoEntity.getId();
OrderGoodsEntity orderGoods = orderGoodsService.getById(orderInfoEntity.getGoodsId());
Assert.notNull(orderGoods, () -> Exceptions.clierr("订单产品不存在"));
// 数量口径:计费策略=按车(Che) 时数量=1否则数量=settleWeight
int quantityByStrategy = (orderGoods.getMoneyStrategy() == MoneyStrategy.Che) ? 1 : settleWeight;

View File

@ -8,7 +8,6 @@ import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.google.common.base.Strings;
import com.njzscloud.common.core.ex.ExceptionMsg;
import com.njzscloud.common.core.ex.Exceptions;
import com.njzscloud.common.core.utils.R;
@ -23,7 +22,6 @@ import com.njzscloud.supervisory.money.service.MoneyAccountService;
import com.njzscloud.supervisory.money.service.MoneyChangeDetailService;
import com.njzscloud.supervisory.order.contant.PaymentStatus;
import com.njzscloud.supervisory.order.contant.PaymentWay;
import com.njzscloud.supervisory.order.contant.SettlementWay;
import com.njzscloud.supervisory.wxPay.dto.RefundRequestDto;
import com.njzscloud.supervisory.order.pojo.entity.OrderExpenseItemsEntity;
import com.njzscloud.supervisory.order.pojo.entity.OrderInfoEntity;
@ -70,10 +68,9 @@ public class PaymentController {
@PostMapping("/pay")
@Transactional(rollbackFor = Exception.class)
public R<?> pay(@RequestBody PaymentParam paymentParam) {
// 入参校验:支付方式、订单ID、支付清单不能为空
// 入参校验:结算金额、订单ID、支付清单不能为空
if (paymentParam == null
|| paymentParam.getOrderId() == null
|| Strings.isNullOrEmpty(paymentParam.getPaymentCategory())
|| paymentParam.getSettleTotalMoney() == null
|| paymentParam.getSettleTotalMoney().signum() < 0
|| paymentParam.getItems() == null) {
@ -91,13 +88,6 @@ public class PaymentController {
throw Exceptions.clierr("支付清单项不合法id/名称/金额)");
}
// 校验支付方式
if (paymentParam.getPaymentCategory() == null ||
!(PaymentWay.WX.getVal().equals(paymentParam.getPaymentCategory()) ||
PaymentWay.COMPANY.getVal().equals(paymentParam.getPaymentCategory()))) {
throw Exceptions.clierr("支付方式不合法");
}
// 校验数据库中结算金额是否与请求一致
for (PaymentItemParam it : paymentParam.getItems()) {
OrderExpenseItemsEntity entity = orderExpenseItemsService.getById(it.getId());
@ -123,65 +113,35 @@ public class PaymentController {
throw Exceptions.clierr("结算总金额与实际总金额不一致");
}
// 根据支付方式处理
if (PaymentWay.COMPANY.getVal().equals(paymentParam.getPaymentCategory())) {
// 公司支付:根据订单 trans_company_id -> biz_company.user_id -> money_account
if (null == ctx.getTransCompanyId()) {
throw Exceptions.clierr("订单未关联清运公司,无法公司支付");
}
// 根据结算方式判断是否需要检查余额
if (SettlementWay.BALANCE.getVal().equals(ctx.getSettlementWay())) {
// 余额结算:允许本次支付后余额为负数,但仅限于余额首次变为负数
if (ctx.getCompanyBalance() == null) {
ctx.setCompanyBalance(BigDecimal.ZERO);
}
if (ctx.getCompanyBalance().compareTo(BigDecimal.ZERO) < 0) {
// 已经是负数,禁止再次支付
throw Exceptions.clierr("公司账户余额不足");
}
}
try {
// 构建微信支付请求
String outTradeNo = generateOutTradeNo(ctx.getSn());
WxPayUnifiedOrderRequest wxRequest = new WxPayUnifiedOrderRequest();
wxRequest.setOutTradeNo(outTradeNo);
wxRequest.setBody("订单支付-" + ctx.getSn());
wxRequest.setTotalFee(ctx.getSettleMoney().multiply(new BigDecimal("100")).intValue()); // 转换为分
wxRequest.setOpenid(getCurrentUserOpenid(paymentParam.getWxCode()));
wxRequest.setTradeType("JSAPI");
wxRequest.setSpbillCreateIp(RequestHolder.getClientIP());
wxRequest.setNotifyUrl(properties.getNotifyUrl()); // 需要配置实际的回调地址
// 3. 更新订单支付状态为已支付
// 调用微信支付服务
WxPayMpOrderResult result = (WxPayMpOrderResult) wechatPayService.createJsapiOrder(wxRequest);
// 更新订单状态为待支付
orderInfoService.lambdaUpdate()
.eq(OrderInfoEntity::getId, paymentParam.getOrderId())
.set(OrderInfoEntity::getPaymentStatus, PaymentStatus.YiZhiFu)
.set(OrderInfoEntity::getPaymentCategory, paymentParam.getPaymentCategory())
.set(OrderInfoEntity::getPayTime, LocalDateTime.now())
.set(OrderInfoEntity::getPaymentStatus, PaymentStatus.WeiZhiFu)
.set(OrderInfoEntity::getPaymentCategory, PaymentWay.WX.getVal())
.set(OrderInfoEntity::getOutTradeNo, outTradeNo)
.update();
log.info("订单支付成功订单ID{},支付方式:{},支付金额:{}",
paymentParam.getOrderId(), paymentParam.getPaymentCategory(), ctx.getSettleMoney());
} else if (PaymentWay.WX.getVal().equals(paymentParam.getPaymentCategory())) {
try {
// 构建微信支付请求
String outTradeNo = generateOutTradeNo(ctx.getSn());
WxPayUnifiedOrderRequest wxRequest = new WxPayUnifiedOrderRequest();
wxRequest.setOutTradeNo(outTradeNo);
wxRequest.setBody("订单支付-" + ctx.getSn());
wxRequest.setTotalFee(ctx.getSettleMoney().multiply(new BigDecimal("100")).intValue()); // 转换为分
wxRequest.setOpenid(getCurrentUserOpenid(paymentParam.getWxCode()));
wxRequest.setTradeType("JSAPI");
wxRequest.setSpbillCreateIp(RequestHolder.getClientIP());
wxRequest.setNotifyUrl(properties.getNotifyUrl()); // 需要配置实际的回调地址
log.info("微信支付订单创建成功生产级SDK订单ID{},微信订单号:{}", paymentParam.getOrderId(), outTradeNo);
// 调用微信支付服务
WxPayMpOrderResult result = (WxPayMpOrderResult) wechatPayService.createJsapiOrder(wxRequest);
// 更新订单状态为待支付
orderInfoService.lambdaUpdate()
.eq(OrderInfoEntity::getId, paymentParam.getOrderId())
.set(OrderInfoEntity::getPaymentStatus, PaymentStatus.WeiZhiFu)
.set(OrderInfoEntity::getPaymentCategory, paymentParam.getPaymentCategory())
.set(OrderInfoEntity::getOutTradeNo, outTradeNo)
.update();
log.info("微信支付订单创建成功生产级SDK订单ID{},微信订单号:{}", paymentParam.getOrderId(), outTradeNo);
return R.success(result);
} catch (WxPayException e) {
log.error("微信支付订单创建失败订单ID{},错误信息:{}", paymentParam.getOrderId(), e.getMessage(), e);
WxPayNotifyResponse.fail(e.getMessage());
}
return R.success(result);
} catch (WxPayException e) {
log.error("微信支付订单创建失败订单ID{},错误信息:{}", paymentParam.getOrderId(), e.getMessage(), e);
WxPayNotifyResponse.fail(e.getMessage());
}
return R.success();

View File

@ -20,12 +20,6 @@ public class PaymentParam {
*/
private Long orderId;
/**
* wx / company
*/
private String paymentCategory;
/**
* >= 0
*/

View File

@ -140,10 +140,12 @@
j.license_end_time,
g.idcard trans_idcard,
g.idcard_start_time trans_idcard_start_time,
g.idcard_end_time trans_idcard_end_time
g.idcard_end_time trans_idcard_end_time,
gi.money_way
FROM order_info a
LEFT JOIN order_cargo_place b ON b.id = a.cargo_place_id
LEFT JOIN order_goods c ON c.id = a.goods_id
LEFT JOIN goods_info gi ON gi.id = c.origin_goods_id
LEFT JOIN order_car_in_out d ON d.id = a.car_in_out_id
LEFT JOIN biz_truck e ON e.id = a.truck_id
LEFT JOIN biz_driver f ON f.id = a.driver_id