package com.talentcard.server.business.portal;
|
|
import java.util.LinkedHashMap;
|
import java.util.Map;
|
import java.util.List;
|
|
import com.talentcard.server.business.auth.TalentAuthService;
|
import com.talentcard.server.business.auth.TalentSessionPrincipal;
|
import com.talentcard.server.business.payment.HuifuPaymentService;
|
import com.talentcard.server.business.payment.PaymentReconciliationService;
|
import com.talentcard.server.business.payment.PaymentReconciliationService.PendingPaymentConfirmation;
|
import com.talentcard.server.business.payment.PaymentReconciliationService.PendingPaymentState;
|
import com.talentcard.server.common.ApiResponse;
|
import com.talentcard.server.common.BusinessException;
|
import com.talentcard.server.common.ErrorCode;
|
import jakarta.validation.Valid;
|
import org.springframework.http.HttpHeaders;
|
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestHeader;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RestController;
|
|
@RestController
|
@RequestMapping("/api/app/pending-orders")
|
public class PendingOrderPortalController {
|
private final PendingOrderPortalService pendingOrderPortalService;
|
private final HuifuPaymentService huifuPaymentService;
|
private final PaymentReconciliationService paymentReconciliationService;
|
private final TalentAuthService talentAuthService;
|
|
public PendingOrderPortalController(PendingOrderPortalService pendingOrderPortalService, HuifuPaymentService huifuPaymentService,
|
PaymentReconciliationService paymentReconciliationService, TalentAuthService talentAuthService) {
|
this.pendingOrderPortalService = pendingOrderPortalService;
|
this.huifuPaymentService = huifuPaymentService;
|
this.paymentReconciliationService = paymentReconciliationService;
|
this.talentAuthService = talentAuthService;
|
}
|
|
@GetMapping("/{orderNo}")
|
public ApiResponse<Map<String, Object>> detail(@PathVariable String orderNo, @RequestParam Long talentId) {
|
return ApiResponse.success(pendingOrderPortalService.detail(orderNo, talentId));
|
}
|
|
@GetMapping("/{orderNo}/coupons")
|
public ApiResponse<List<Map<String, Object>>> coupons(@PathVariable String orderNo, @RequestParam Long talentId) {
|
return ApiResponse.success(pendingOrderPortalService.coupons(orderNo, talentId));
|
}
|
|
@PostMapping("/{orderNo}/coupon")
|
public ApiResponse<Map<String, Object>> chooseCoupon(@PathVariable String orderNo, @Valid @RequestBody PendingOrderCouponRequest request) {
|
return ApiResponse.success(pendingOrderPortalService.chooseCoupon(orderNo, request));
|
}
|
|
@PostMapping("/{orderNo}/cancel")
|
public ApiResponse<Map<String, Object>> cancel(
|
@PathVariable String orderNo,
|
@Valid @RequestBody PendingOrderCancelRequest request,
|
@RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authorization
|
) {
|
ensureSessionTalent(authorization, request.talentId());
|
return ApiResponse.success(pendingOrderPortalService.cancel(orderNo, request.talentId()));
|
}
|
|
@PostMapping("/{orderNo}/pay")
|
public ApiResponse<Map<String, Object>> pay(@PathVariable String orderNo, @Valid @RequestBody PendingOrderPaymentRequest request) {
|
throw new BusinessException(ErrorCode.CONFLICT, "支付接口已升级,请使用支付发起接口");
|
}
|
|
@PostMapping("/{orderNo}/payment")
|
public ApiResponse<Map<String, Object>> createPayment(
|
@PathVariable String orderNo,
|
@Valid @RequestBody PendingOrderPaymentRequest request,
|
@RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authorization,
|
@RequestHeader(value = "X-Idempotency-Key", required = false) String idempotencyKey
|
) {
|
ensureSessionTalent(authorization, request.talentId());
|
return ApiResponse.success(huifuPaymentService.beginMiniProgramPayment(orderNo, request.talentId(), request.priceVersion(), idempotencyKey));
|
}
|
|
@GetMapping("/{orderNo}/payment")
|
public ApiResponse<Map<String, Object>> paymentStatus(
|
@PathVariable String orderNo,
|
@RequestParam Long talentId,
|
@RequestParam(required = false) String paymentNo,
|
@RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authorization
|
) {
|
ensureSessionTalent(authorization, talentId);
|
return ApiResponse.success(huifuPaymentService.paymentStatus(orderNo, talentId, paymentNo));
|
}
|
|
/**
|
* 放弃支付:客户端在收银台里点了关闭时调用,服务端立刻尝试关单。
|
*
|
* <p>只触发关单、绝不结算:客户端说「我放弃了」只当作信号,钱收没收下一律以通道回执为准。
|
*/
|
@PostMapping("/{orderNo}/payment/abandon")
|
public ApiResponse<Map<String, Object>> abandonPayment(
|
@PathVariable String orderNo,
|
@Valid @RequestBody PendingOrderAbandonRequest request,
|
@RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authorization
|
) {
|
ensureSessionTalent(authorization, request.talentId());
|
PendingPaymentConfirmation confirmation =
|
paymentReconciliationService.abandonPendingPayments(orderNo, request.paymentNo());
|
Map<String, Object> result = new LinkedHashMap<>();
|
result.put("paymentNo", confirmation.paymentNo());
|
// 关单有结论(关掉了/通道拒绝关单但仍然允许继续)就是 CANCELLED;
|
// 通道说还在处理中就是 PAYMENT_PROCESSING——后台会接着关,客户端按可等待渲染。
|
result.put("paymentStatus", confirmation.state() == PendingPaymentState.UNCONFIRMED
|
? "PAYMENT_PROCESSING" : "CANCELLED");
|
return ApiResponse.success(result);
|
}
|
|
private void ensureSessionTalent(String authorization, Long talentId) {
|
TalentSessionPrincipal principal = talentAuthService.authenticate(authorization);
|
if (!principal.talentId().equals(talentId)) throw new BusinessException(ErrorCode.FORBIDDEN, "无权操作其他人才用户的订单");
|
}
|
}
|