Commit 05f0cda49f2cc6064025a4c98a567ef560b660ff

Authored by huanggang
1 parent 9ea129ba

issue fixed after prod testing

cashier-pipeline/src/main/java/com/diligrp/cashier/pipeline/client/CardPaymentHttpClient.java
... ... @@ -17,10 +17,7 @@ import org.slf4j.Logger;
17 17 import org.slf4j.LoggerFactory;
18 18  
19 19 import java.time.LocalDateTime;
20   -import java.util.ArrayList;
21   -import java.util.LinkedHashMap;
22   -import java.util.List;
23   -import java.util.Map;
  20 +import java.util.*;
24 21  
25 22 public class CardPaymentHttpClient extends ServiceEndpointSupport {
26 23  
... ... @@ -47,6 +44,7 @@ public class CardPaymentHttpClient extends ServiceEndpointSupport {
47 44 public CardPaymentResponse sendPaymentRequest(CardPaymentRequest request) {
48 45 String uri = String.format("%s%s", baseUri, PAYMENT_URL);
49 46 SourceType sourceType = request.getObject("source", SourceType.class);
  47 + String attach = request.getString("attach");
50 48 Map<String, Object> params = new LinkedHashMap<>();
51 49 params.put("mchId", outMchId); // 市场ID
52 50 params.put("accountId", accountId); // 市场ID
... ... @@ -58,10 +56,13 @@ public class CardPaymentHttpClient extends ServiceEndpointSupport {
58 56 params.put("outTradeNo", request.getPaymentId());
59 57 params.put("goodsDesc", request.getGoods());
60 58 params.put("description", request.getDescription());
61   - if (sourceType != null) {
  59 + if (Objects.nonNull(sourceType)) {
62 60 params.put("sourceId", sourceType.getCode());
63 61 params.put("sourceName", sourceType.getName());
64 62 }
  63 + if (Objects.nonNull(attach)) {
  64 + params.put("attach", attach);
  65 + }
65 66 String payload = JsonUtils.toJsonString(params);
66 67  
67 68 LOG.info("Sending card payment request: {}\n{}", request.getPaymentId(), payload);
... ...
cashier-trade/src/main/java/com/diligrp/cashier/trade/service/impl/CashierPaymentServiceImpl.java
... ... @@ -178,6 +178,7 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService {
178 178 CardPaymentRequest request = new CardPaymentConverter(trade, paymentId, now).convert(payment);
179 179 // 园区卡支付需要订单来源
180 180 request.attach("source", SourceType.getIfNonNull(trade.getSource()));
  181 + request.attach("attach", trade.getAttach());
181 182 // 修改支付状态为支付中,防止重复支付
182 183 CardPaymentResponse response = cardPipeline.sendPaymentRequest(request);
183 184 // 支付成功插入支付记录并修改交易订单状态,失败可以继续支付
... ... @@ -339,59 +340,68 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService {
339 340 @Override
340 341 @Transactional(rollbackFor = Exception.class)
341 342 public OnlineRefundResult sendRefundRequest(OnlineRefundDTO request) {
342   - TradeOrder trade = tradeAssistantService.findByTradeId(request.getTradeId());
343   - if (!TradeState.forRefund(trade.getState())) {
344   - throw new TradePaymentException(ErrorCode.INVALID_OBJECT_STATE, "不能进行交易退款: 无效的交易状态");
345   - }
346   - if (trade.getAmount() < request.getAmount()) {
347   - throw new TradePaymentException(ErrorCode.OPERATION_NOT_ALLOWED, "申请退费金额超过原支付金额");
348   - }
349   - // 理论上只会存在一条支付完成的支付订单
350   - OnlinePayment payment = onlinePaymentDao.listOnlinePayments(trade.getTradeId(),
351   - TradeType.TRADE.getCode(), PaymentState.SUCCESS.getCode()).stream().findFirst()
352   - .orElseThrow(() -> new TradePaymentException(ErrorCode.OPERATION_NOT_ALLOWED, "不能进行交易退款: 无支付信息"));
353   -
354   - LOG.info("Requesting cashier payment refund: {}", request.getTradeId());
355   - LocalDateTime now = LocalDateTime.now().withNano(0);
356   - KeyGenerator refundIdKey = snowflakeKeyManager.getKeyGenerator(SnowflakeKey.PAYMENT_ID);
357   - String refundId = refundIdKey.nextId();
358   - PaymentPipeline<?> pipeline = paymentPipelineManager.findPipelineById(payment.getPipelineId(), PaymentPipeline.class);
359   - OnlineRefundRequest refundRequest = OnlineRefundRequest.of(refundId, payment.getPaymentId(), payment.getOutTradeNo(),
360   - trade.getMaxAmount(), request.getAmount(), request.getDescription(), now);
361   - OnlineRefundResponse response;
362   - if (pipeline instanceof OnlinePipeline<?> onlinePipeline) {
363   - response = onlinePipeline.sendRefundRequest(refundRequest);
364   - } else if (pipeline instanceof DiliCardPipeline cardPipeline) {
365   - response = cardPipeline.sendRefundRequest(refundRequest);
366   - } else {
367   - throw new TradePaymentException(ErrorCode.OPERATION_NOT_ALLOWED, "不支持的支付通道");
368   - }
  343 + String lockKey = String.format(Constants.TRADE_LOCK_REDIS_KEY, request.getTradeId());
  344 + RLock lock = redissonClient.getLock(lockKey);
  345 + try {
  346 + lock.lock();
  347 + TradeOrder trade = tradeAssistantService.findByTradeId(request.getTradeId());
  348 + if (!TradeState.forRefund(trade.getState())) {
  349 + throw new TradePaymentException(ErrorCode.INVALID_OBJECT_STATE, "不能进行交易退款: 无效的交易状态");
  350 + }
  351 + if (trade.getAmount() < request.getAmount()) {
  352 + throw new TradePaymentException(ErrorCode.OPERATION_NOT_ALLOWED, "申请退费金额超过原支付金额");
  353 + }
  354 + // 理论上只会存在一条支付完成的支付订单
  355 + OnlinePayment payment = onlinePaymentDao.listOnlinePayments(trade.getTradeId(),
  356 + TradeType.TRADE.getCode(), PaymentState.SUCCESS.getCode()).stream().findFirst()
  357 + .orElseThrow(() -> new TradePaymentException(ErrorCode.OPERATION_NOT_ALLOWED, "不能进行交易退款: 无支付信息"));
  358 +
  359 + LOG.info("Requesting cashier payment refund: {}", request.getTradeId());
  360 + LocalDateTime now = LocalDateTime.now().withNano(0);
  361 + KeyGenerator refundIdKey = snowflakeKeyManager.getKeyGenerator(SnowflakeKey.PAYMENT_ID);
  362 + String refundId = refundIdKey.nextId();
  363 + PaymentPipeline<?> pipeline = paymentPipelineManager.findPipelineById(payment.getPipelineId(), PaymentPipeline.class);
  364 + OnlineRefundRequest refundRequest = OnlineRefundRequest.of(refundId, payment.getPaymentId(), payment.getOutTradeNo(),
  365 + trade.getMaxAmount(), request.getAmount(), request.getDescription(), now);
  366 + OnlineRefundResponse response;
  367 + if (pipeline instanceof OnlinePipeline<?> onlinePipeline) {
  368 + response = onlinePipeline.sendRefundRequest(refundRequest);
  369 + } else if (pipeline instanceof DiliCardPipeline cardPipeline) {
  370 + response = cardPipeline.sendRefundRequest(refundRequest);
  371 + } else {
  372 + throw new TradePaymentException(ErrorCode.OPERATION_NOT_ALLOWED, "不支持的支付通道");
  373 + }
369 374  
370   - LOG.debug("Cashier payment refund result: [{}:{}]", trade.getTradeId(), response.getState().name());
371   - OnlinePayment refund = OnlinePayment.builder().outMchId(payment.getOutMchId()).tradeId(payment.getTradeId())
372   - .type(TradeType.REFUND).paymentId(refundId).channelId(payment.getChannelId())
373   - .payType(payment.getPayType()).pipelineId(payment.getPipelineId()).goods(payment.getGoods() + "-退款")
374   - .amount(request.getAmount()).objectId(payment.getPaymentId()).payerId(payment.getPayerId())
375   - .outTradeNo(response.getOutTradeNo()).outPayType(payment.getOutPayType()).finishTime(response.getWhen())
376   - .state(response.getState()).notifyUrl(request.getNotifyUrl()).description(request.getDescription())
377   - .version(0).createdTime(now).modifiedTime(now).build();
378   - onlinePaymentDao.insertOnlinePayment(refund);
  375 + LOG.debug("Cashier payment refund result: [{}:{}]", trade.getTradeId(), response.getState().name());
  376 + OnlinePayment refund = OnlinePayment.builder().outMchId(payment.getOutMchId()).tradeId(payment.getTradeId())
  377 + .type(TradeType.REFUND).paymentId(refundId).channelId(payment.getChannelId())
  378 + .payType(payment.getPayType()).pipelineId(payment.getPipelineId()).goods(payment.getGoods() + "-退款")
  379 + .amount(request.getAmount()).objectId(payment.getPaymentId()).payerId(payment.getPayerId())
  380 + .outTradeNo(response.getOutTradeNo()).outPayType(payment.getOutPayType()).finishTime(response.getWhen())
  381 + .state(response.getState()).notifyUrl(request.getNotifyUrl()).description(request.getDescription())
  382 + .version(0).createdTime(now).modifiedTime(now).build();
  383 + onlinePaymentDao.insertOnlinePayment(refund);
  384 +
  385 + if (response.getState() == PaymentState.SUCCESS) {
  386 + Long newAmount = trade.getAmount() - refund.getAmount();
  387 + TradeStateDTO tradeState = TradeStateDTO.of(trade.getTradeId(), newAmount, TradeState.REFUND, trade.getVersion(), now);
  388 + tradeAssistantService.proceedTradeOrder(tradeState);
  389 + } else if (!PaymentState.isFinished(response.getState().getCode())) {
  390 + // 固定周期后,查询退款状态,根据状态完成退款订单
  391 + if (pipeline instanceof OnlinePipeline<?> onlinePipeline) { // 只有在线支付通道允许查询退款状态
  392 + Duration duration = onlinePipeline.getTimeStrategy().nextRefundScanTime(1);
  393 + TaskMessage message = new TaskMessage(TaskMessage.TYPE_CASHIER_REFUND_SCAN, refundId, "1");
  394 + taskMessageSender.sendDelayTaskMessage(message, duration);
  395 + }
  396 + }
379 397  
380   - if (response.getState() == PaymentState.SUCCESS) {
381   - Long newAmount = trade.getAmount() - refund.getAmount();
382   - TradeStateDTO tradeState = TradeStateDTO.of(trade.getTradeId(), newAmount, TradeState.REFUND, trade.getVersion(), now);
383   - tradeAssistantService.proceedTradeOrder(tradeState);
384   - } else if (!PaymentState.isFinished(response.getState().getCode())) {
385   - // 固定周期后,查询退款状态,根据状态完成退款订单
386   - if (pipeline instanceof OnlinePipeline<?> onlinePipeline) { // 只有在线支付通道允许查询退款状态
387   - Duration duration = onlinePipeline.getTimeStrategy().nextRefundScanTime(1);
388   - TaskMessage message = new TaskMessage(TaskMessage.TYPE_CASHIER_REFUND_SCAN, refundId, "1");
389   - taskMessageSender.sendDelayTaskMessage(message, duration);
  398 + return new OnlineRefundResult(refundId, payment.getPaymentId(), response.getState().getCode(),
  399 + response.getWhen(), response.getMessage());
  400 + } finally {
  401 + if (lock.isHeldByCurrentThread()) {
  402 + lock.unlock();
390 403 }
391 404 }
392   -
393   - return new OnlineRefundResult(refundId, payment.getPaymentId(), response.getState().getCode(),
394   - response.getWhen(), response.getMessage());
395 405 }
396 406  
397 407 @Override
... ...