feat(hjc): 阶段2 订单支付闭环 - 下单后发起微信Native支付并回推一站式
- HjcOrderController: POST /api/hjc/order/pay(复用 payment.createPayment 取codeUrl)、PUT /api/hjc/order/mark-paid(幂等置已付+触发一站式推送) - HjcBizService.markPaid: 置 payStatus=1/orderStatus=1/payTime,支付成功即 pushOrderToOneStop - 出向推送在 base-url 未配置时不发起HTTP,仅记日志待重试
This commit is contained in:
@@ -11,8 +11,13 @@ import com.gxwebsoft.hjc.entity.HjcEnterprise;
|
|||||||
import com.gxwebsoft.hjc.entity.HjcOrder;
|
import com.gxwebsoft.hjc.entity.HjcOrder;
|
||||||
import com.gxwebsoft.hjc.param.HjcOrderParam;
|
import com.gxwebsoft.hjc.param.HjcOrderParam;
|
||||||
import com.gxwebsoft.hjc.service.HjcBidProjectService;
|
import com.gxwebsoft.hjc.service.HjcBidProjectService;
|
||||||
|
import com.gxwebsoft.hjc.service.HjcBizService;
|
||||||
import com.gxwebsoft.hjc.service.HjcEnterpriseService;
|
import com.gxwebsoft.hjc.service.HjcEnterpriseService;
|
||||||
import com.gxwebsoft.hjc.service.HjcOrderService;
|
import com.gxwebsoft.hjc.service.HjcOrderService;
|
||||||
|
import com.gxwebsoft.payment.dto.PaymentRequest;
|
||||||
|
import com.gxwebsoft.payment.dto.PaymentResponse;
|
||||||
|
import com.gxwebsoft.payment.enums.PaymentType;
|
||||||
|
import com.gxwebsoft.payment.service.PaymentService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@@ -22,6 +27,7 @@ import java.math.BigDecimal;
|
|||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 汇吉采标书订单(下单 + 我的订单 + 后台订单)
|
* 汇吉采标书订单(下单 + 我的订单 + 后台订单)
|
||||||
@@ -39,6 +45,10 @@ public class HjcOrderController extends BaseController {
|
|||||||
private HjcBidProjectService hjcBidProjectService;
|
private HjcBidProjectService hjcBidProjectService;
|
||||||
@Resource
|
@Resource
|
||||||
private HjcEnterpriseService hjcEnterpriseService;
|
private HjcEnterpriseService hjcEnterpriseService;
|
||||||
|
@Resource
|
||||||
|
private PaymentService paymentService;
|
||||||
|
@Resource
|
||||||
|
private HjcBizService hjcBizService;
|
||||||
|
|
||||||
@Operation(summary = "下单(创建待支付订单)")
|
@Operation(summary = "下单(创建待支付订单)")
|
||||||
@PostMapping("/create")
|
@PostMapping("/create")
|
||||||
@@ -99,6 +109,65 @@ public class HjcOrderController extends BaseController {
|
|||||||
return success("下单成功", order);
|
return success("下单成功", order);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "发起支付(微信Native扫码,返回codeUrl)")
|
||||||
|
@PostMapping("/pay")
|
||||||
|
public ApiResult<?> pay(@RequestBody Map<String, Object> body) {
|
||||||
|
Integer userId = getLoginUserId();
|
||||||
|
if (userId == null) {
|
||||||
|
return fail("用户未登录");
|
||||||
|
}
|
||||||
|
String orderNo = body.get("orderNo") == null ? null : String.valueOf(body.get("orderNo"));
|
||||||
|
if (orderNo == null) {
|
||||||
|
return fail("订单号不能为空");
|
||||||
|
}
|
||||||
|
HjcOrder order = hjcOrderService.getByOrderNo(orderNo);
|
||||||
|
if (order == null) {
|
||||||
|
return fail("订单不存在");
|
||||||
|
}
|
||||||
|
if (order.getPayStatus() != null && order.getPayStatus() == 1) {
|
||||||
|
return fail("订单已支付");
|
||||||
|
}
|
||||||
|
HjcEnterprise enterprise = hjcEnterpriseService.getByUserId(userId);
|
||||||
|
if (enterprise == null || !enterprise.getId().equals(order.getEnterpriseId())) {
|
||||||
|
return fail("无权操作该订单");
|
||||||
|
}
|
||||||
|
PaymentRequest request = new PaymentRequest();
|
||||||
|
request.setTenantId(order.getTenantId());
|
||||||
|
request.setUserId(userId);
|
||||||
|
request.setPaymentType(PaymentType.WECHAT_NATIVE);
|
||||||
|
request.setAmount(order.getTotalAmount());
|
||||||
|
request.setSubject(truncate(order.getProjectName(), 127));
|
||||||
|
request.setOrderNo(order.getOrderNo());
|
||||||
|
try {
|
||||||
|
PaymentResponse resp = paymentService.createPayment(request);
|
||||||
|
return success("发起支付成功", resp);
|
||||||
|
} catch (com.gxwebsoft.payment.exception.PaymentException e) {
|
||||||
|
return fail("发起支付失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "标记订单已支付(支付成功后调用,幂等),并触发一站式推送")
|
||||||
|
@PutMapping("/mark-paid")
|
||||||
|
public ApiResult<?> markPaid(@RequestBody Map<String, Object> body) {
|
||||||
|
Integer userId = getLoginUserId();
|
||||||
|
if (userId == null) {
|
||||||
|
return fail("用户未登录");
|
||||||
|
}
|
||||||
|
String orderNo = body.get("orderNo") == null ? null : String.valueOf(body.get("orderNo"));
|
||||||
|
if (orderNo == null) {
|
||||||
|
return fail("订单号不能为空");
|
||||||
|
}
|
||||||
|
HjcOrder order = hjcOrderService.getByOrderNo(orderNo);
|
||||||
|
if (order == null) {
|
||||||
|
return fail("订单不存在");
|
||||||
|
}
|
||||||
|
HjcEnterprise enterprise = hjcEnterpriseService.getByUserId(userId);
|
||||||
|
if (enterprise == null || !enterprise.getId().equals(order.getEnterpriseId())) {
|
||||||
|
return fail("无权操作该订单");
|
||||||
|
}
|
||||||
|
return success("已支付", hjcBizService.markPaid(orderNo));
|
||||||
|
}
|
||||||
|
|
||||||
@Operation(summary = "我的订单")
|
@Operation(summary = "我的订单")
|
||||||
@GetMapping("/my")
|
@GetMapping("/my")
|
||||||
public ApiResult<?> my() {
|
public ApiResult<?> my() {
|
||||||
@@ -136,4 +205,11 @@ public class HjcOrderController extends BaseController {
|
|||||||
private String firstNotBlank(String a, String b) {
|
private String firstNotBlank(String a, String b) {
|
||||||
return a != null && !a.trim().isEmpty() ? a : b;
|
return a != null && !a.trim().isEmpty() ? a : b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String truncate(String s, int max) {
|
||||||
|
if (s == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return s.length() > max ? s.substring(0, max) : s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,11 @@ public interface HjcBizService {
|
|||||||
*/
|
*/
|
||||||
void pushOrderToOneStop(HjcOrder order);
|
void pushOrderToOneStop(HjcOrder order);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付成功后标记订单已支付(幂等),并触发一站式推送
|
||||||
|
*/
|
||||||
|
HjcOrder markPaid(String orderNo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重试失败的推送(幂等)
|
* 重试失败的推送(幂等)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ public class HjcBizServiceImpl implements HjcBizService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void retryPendingPush() {
|
public void retryPendingPush() {
|
||||||
List<HjcOrderPushLog> pending = hjcOrderPushLogService.list(new LambdaQueryWrapper<HjcOrderPushLog>()
|
List<HjcOrderPushLog> pending = hjcOrderPushLogService.list(new LambdaQueryWrapper<HjcOrderPushLog>()
|
||||||
.in(HjcOrderPushLog::getPushStatus, 0, 2)
|
.in(HjcOrderPushLog::getPushStatus, 0, 2)
|
||||||
@@ -123,10 +124,38 @@ public class HjcBizServiceImpl implements HjcBizService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public HjcOrder markPaid(String orderNo) {
|
||||||
|
HjcOrder order = hjcOrderService.getByOrderNo(orderNo);
|
||||||
|
if (order == null) {
|
||||||
|
throw new RuntimeException("订单不存在");
|
||||||
|
}
|
||||||
|
if (order.getPayStatus() != null && order.getPayStatus() == 1) {
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
order.setPayStatus(1);
|
||||||
|
order.setOrderStatus(1);
|
||||||
|
order.setPayTime(LocalDateTime.now());
|
||||||
|
hjcOrderService.updateById(order);
|
||||||
|
// 支付成功后触发一站式推送
|
||||||
|
pushOrderToOneStop(order);
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
|
||||||
private void doPush(HjcOrder order, HjcOrderPushLog logEntity) {
|
private void doPush(HjcOrder order, HjcOrderPushLog logEntity) {
|
||||||
try {
|
try {
|
||||||
CreatePurchaseDetails body = buildCreatePurchaseDetails(order);
|
CreatePurchaseDetails body = buildCreatePurchaseDetails(order);
|
||||||
String payload = objectMapper.writeValueAsString(body);
|
String payload = objectMapper.writeValueAsString(body);
|
||||||
|
logEntity.setPayload(payload);
|
||||||
|
if (StrUtil.isBlank(oneStopBaseUrl)) {
|
||||||
|
logEntity.setAttemptCount(logEntity.getAttemptCount() + 1);
|
||||||
|
logEntity.setPushStatus(2);
|
||||||
|
logEntity.setErrorMsg("一站式base-url未配置");
|
||||||
|
logEntity.setNextRetryTime(LocalDateTime.now().plusMinutes(30));
|
||||||
|
hjcOrderPushLogService.updateById(logEntity);
|
||||||
|
return;
|
||||||
|
}
|
||||||
String ts = HjcOneStopAuthUtil.timestamp();
|
String ts = HjcOneStopAuthUtil.timestamp();
|
||||||
String sign = HjcOneStopAuthUtil.sign(ts);
|
String sign = HjcOneStopAuthUtil.sign(ts);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user