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,10 +17,7 @@ import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory; 17 import org.slf4j.LoggerFactory;
18 18
19 import java.time.LocalDateTime; 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 public class CardPaymentHttpClient extends ServiceEndpointSupport { 22 public class CardPaymentHttpClient extends ServiceEndpointSupport {
26 23
@@ -47,6 +44,7 @@ public class CardPaymentHttpClient extends ServiceEndpointSupport { @@ -47,6 +44,7 @@ public class CardPaymentHttpClient extends ServiceEndpointSupport {
47 public CardPaymentResponse sendPaymentRequest(CardPaymentRequest request) { 44 public CardPaymentResponse sendPaymentRequest(CardPaymentRequest request) {
48 String uri = String.format("%s%s", baseUri, PAYMENT_URL); 45 String uri = String.format("%s%s", baseUri, PAYMENT_URL);
49 SourceType sourceType = request.getObject("source", SourceType.class); 46 SourceType sourceType = request.getObject("source", SourceType.class);
  47 + String attach = request.getString("attach");
50 Map<String, Object> params = new LinkedHashMap<>(); 48 Map<String, Object> params = new LinkedHashMap<>();
51 params.put("mchId", outMchId); // 市场ID 49 params.put("mchId", outMchId); // 市场ID
52 params.put("accountId", accountId); // 市场ID 50 params.put("accountId", accountId); // 市场ID
@@ -58,10 +56,13 @@ public class CardPaymentHttpClient extends ServiceEndpointSupport { @@ -58,10 +56,13 @@ public class CardPaymentHttpClient extends ServiceEndpointSupport {
58 params.put("outTradeNo", request.getPaymentId()); 56 params.put("outTradeNo", request.getPaymentId());
59 params.put("goodsDesc", request.getGoods()); 57 params.put("goodsDesc", request.getGoods());
60 params.put("description", request.getDescription()); 58 params.put("description", request.getDescription());
61 - if (sourceType != null) { 59 + if (Objects.nonNull(sourceType)) {
62 params.put("sourceId", sourceType.getCode()); 60 params.put("sourceId", sourceType.getCode());
63 params.put("sourceName", sourceType.getName()); 61 params.put("sourceName", sourceType.getName());
64 } 62 }
  63 + if (Objects.nonNull(attach)) {
  64 + params.put("attach", attach);
  65 + }
65 String payload = JsonUtils.toJsonString(params); 66 String payload = JsonUtils.toJsonString(params);
66 67
67 LOG.info("Sending card payment request: {}\n{}", request.getPaymentId(), payload); 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,6 +178,7 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService {
178 CardPaymentRequest request = new CardPaymentConverter(trade, paymentId, now).convert(payment); 178 CardPaymentRequest request = new CardPaymentConverter(trade, paymentId, now).convert(payment);
179 // 园区卡支付需要订单来源 179 // 园区卡支付需要订单来源
180 request.attach("source", SourceType.getIfNonNull(trade.getSource())); 180 request.attach("source", SourceType.getIfNonNull(trade.getSource()));
  181 + request.attach("attach", trade.getAttach());
181 // 修改支付状态为支付中,防止重复支付 182 // 修改支付状态为支付中,防止重复支付
182 CardPaymentResponse response = cardPipeline.sendPaymentRequest(request); 183 CardPaymentResponse response = cardPipeline.sendPaymentRequest(request);
183 // 支付成功插入支付记录并修改交易订单状态,失败可以继续支付 184 // 支付成功插入支付记录并修改交易订单状态,失败可以继续支付
@@ -339,59 +340,68 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { @@ -339,59 +340,68 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService {
339 @Override 340 @Override
340 @Transactional(rollbackFor = Exception.class) 341 @Transactional(rollbackFor = Exception.class)
341 public OnlineRefundResult sendRefundRequest(OnlineRefundDTO request) { 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 @Override 407 @Override