Commit 086ee65ab40098f4dd6f4ff76af4e5859740c3bb

Authored by huanggang
1 parent 5103e910

trade refund supported

Showing 28 changed files with 303 additions and 125 deletions
cashier-boss/src/main/java/com/diligrp/cashier/boss/controller/CardPaymentController.java 0 → 100644
  1 +package com.diligrp.cashier.boss.controller;
  2 +
  3 +import com.diligrp.cashier.pipeline.core.DiliCardPipeline;
  4 +import com.diligrp.cashier.pipeline.service.IPaymentPipelineManager;
  5 +import com.diligrp.cashier.shared.domain.Message;
  6 +import jakarta.annotation.Resource;
  7 +import org.springframework.web.bind.annotation.RequestMapping;
  8 +import org.springframework.web.bind.annotation.RequestParam;
  9 +import org.springframework.web.bind.annotation.RestController;
  10 +
  11 +@RestController
  12 +@RequestMapping(value = "/card")
  13 +public class CardPaymentController {
  14 +
  15 + @Resource
  16 + private IPaymentPipelineManager paymentPipelineManager;
  17 +
  18 + @RequestMapping(value = "/payment/listUserCards")
  19 + public Message<?> listUserCards(@RequestParam("pipelineId") Long pipelineId, @RequestParam("userId") String userId) {
  20 + DiliCardPipeline cardPipeline = paymentPipelineManager.findPipelineById(pipelineId, DiliCardPipeline.class);
  21 + return Message.success(cardPipeline.getClient().listUserCards(userId));
  22 + }
  23 +}
... ...
cashier-boss/src/main/java/com/diligrp/cashier/boss/controller/CashierDeskController.java
... ... @@ -72,7 +72,7 @@ public class CashierDeskController {
72 72 return Message.success(response);
73 73 }
74 74  
75   - @RequestMapping(value = "/orderRefund.do")
  75 + @RequestMapping(value = "/orderRefund")
76 76 public Message<?> requestRefund(@RequestBody OnlineRefundDTO request) {
77 77 AssertUtils.notEmpty(request.getTradeId(), "tradeId missed");
78 78 AssertUtils.notNull(request.getAmount(), "amount missed");
... ...
cashier-boss/src/main/java/com/diligrp/cashier/boss/controller/WechatPaymentController.java
... ... @@ -156,7 +156,7 @@ public class WechatPaymentController {
156 156 RefundNotifyResponse response = JsonUtils.fromJsonString(payload, RefundNotifyResponse.class);
157 157 LocalDateTime when = DateUtils.parseDateTime(response.getSuccess_time(), WechatConstants.RFC3339_FORMAT);
158 158 PaymentState refundState = WechatStateUtils.getRefundState(response.getRefund_status());
159   - return OnlineRefundResponse.of(response.getOut_refund_no(), response.getRefund_id(), when,
  159 + return new OnlineRefundResponse(response.getOut_refund_no(), response.getRefund_id(), when,
160 160 refundState, response.getRefund_status());
161 161 }
162 162  
... ...
cashier-boss/src/main/java/com/diligrp/cashier/boss/domain/CashierOrderDTO.java
... ... @@ -23,6 +23,8 @@ public class CashierOrderDTO {
23 23 private String description;
24 24 // 附加数据
25 25 private String attach;
  26 + // 订单来源
  27 + private Integer source;
26 28  
27 29 public Long getMchId() {
28 30 return mchId;
... ... @@ -111,4 +113,12 @@ public class CashierOrderDTO {
111 113 public void setAttach(String attach) {
112 114 this.attach = attach;
113 115 }
  116 +
  117 + public Integer getSource() {
  118 + return source;
  119 + }
  120 +
  121 + public void setSource(Integer source) {
  122 + this.source = source;
  123 + }
114 124 }
... ...
cashier-boss/src/main/java/com/diligrp/cashier/boss/service/impl/CashierDeskServiceImpl.java
... ... @@ -10,6 +10,7 @@ import com.diligrp.cashier.boss.service.ICashierDeskService;
10 10 import com.diligrp.cashier.pipeline.core.PaymentPipeline;
11 11 import com.diligrp.cashier.pipeline.domain.OnlinePaymentStatus;
12 12 import com.diligrp.cashier.pipeline.service.IPaymentPipelineManager;
  13 +import com.diligrp.cashier.pipeline.type.PaymentState;
13 14 import com.diligrp.cashier.shared.ErrorCode;
14 15 import com.diligrp.cashier.shared.util.ObjectUtils;
15 16 import com.diligrp.cashier.trade.domain.*;
... ... @@ -97,10 +98,11 @@ public class CashierDeskServiceImpl implements ICashierDeskService {
97 98 @Override
98 99 public OnlinePaymentStatus doPayment(CashierPayment payment) {
99 100 OnlinePaymentStatus paymentStatus = cashierPaymentService.doPayment(payment);
100   - // 只要提交了收银台支付,无论是否支付成功,都使token失效,收银台页面将无法重新打开
101   - String token = CashierOrderToken.encode(Long.valueOf(payment.getTradeId()), cashierDeskProperties.getSecretKey());
102   - String tokenKey = String.format(Constants.TRADE_REDIS_KEY, token);
103   - stringRedisTemplate.delete(tokenKey);
  101 + // 收银台支付成功,都使token失效,收银台页面将无法重新打开
  102 + if (paymentStatus.getState() == PaymentState.SUCCESS) {
  103 + String tokenKey = String.format(Constants.TRADE_REDIS_KEY, payment.getTradeId());
  104 + stringRedisTemplate.delete(tokenKey);
  105 + }
104 106 return paymentStatus;
105 107 }
106 108  
... ...
cashier-boss/src/main/java/com/diligrp/cashier/boss/util/CashierOrderConverter.java
... ... @@ -3,6 +3,7 @@ package com.diligrp.cashier.boss.util;
3 3 import com.diligrp.cashier.boss.domain.CashierOrderDTO;
4 4 import com.diligrp.cashier.pipeline.type.CashierType;
5 5 import com.diligrp.cashier.shared.codec.IConverter;
  6 +import com.diligrp.cashier.shared.type.SourceType;
6 7 import com.diligrp.cashier.trade.domain.CashierOrder;
7 8  
8 9 public class CashierOrderConverter implements IConverter<CashierOrderDTO, CashierOrder> {
... ... @@ -22,6 +23,7 @@ public class CashierOrderConverter implements IConverter&lt;CashierOrderDTO, Cashie
22 23 cashierOrder.setRedirectUrl(cashierOrderDTO.getRedirectUrl());
23 24 cashierOrder.setDescription(cashierOrderDTO.getDescription());
24 25 cashierOrder.setAttach(cashierOrderDTO.getAttach());
  26 + cashierOrder.setSource(SourceType.getIfNonNull(cashierOrderDTO.getSource()));
25 27 return cashierOrder;
26 28 }
27 29 }
... ...
cashier-boss/src/main/java/com/diligrp/cashier/boss/util/CashierOrderConverter2.java
... ... @@ -3,6 +3,7 @@ package com.diligrp.cashier.boss.util;
3 3 import com.diligrp.cashier.pipeline.type.CashierType;
4 4 import com.diligrp.cashier.shared.codec.IConverter;
5 5 import com.diligrp.cashier.shared.spi.domain.CashierOrderBO;
  6 +import com.diligrp.cashier.shared.type.SourceType;
6 7 import com.diligrp.cashier.trade.domain.CashierOrder;
7 8  
8 9 public class CashierOrderConverter2 implements IConverter<CashierOrderBO, CashierOrder> {
... ... @@ -10,18 +11,19 @@ public class CashierOrderConverter2 implements IConverter&lt;CashierOrderBO, Cashie
10 11 public static IConverter<CashierOrderBO, CashierOrder> INSTANCE = new CashierOrderConverter2();
11 12  
12 13 @Override
13   - public CashierOrder convert(CashierOrderBO cashierOrderDTO) {
  14 + public CashierOrder convert(CashierOrderBO cashierOrderBO) {
14 15 CashierOrder cashierOrder = new CashierOrder();
15   - cashierOrder.setUserId(cashierOrderDTO.getUserId());
16   - cashierOrder.setType(CashierType.getByCode(cashierOrderDTO.getCashierType()));
17   - cashierOrder.setGoods(cashierOrderDTO.getGoods());
18   - cashierOrder.setAmount(cashierOrderDTO.getAmount());
19   - cashierOrder.setTimeout(cashierOrderDTO.getTimeout());
20   - cashierOrder.setOutTradeNo(cashierOrderDTO.getOutTradeNo());
21   - cashierOrder.setNotifyUrl(cashierOrderDTO.getNotifyUrl());
22   - cashierOrder.setRedirectUrl(cashierOrderDTO.getRedirectUrl());
23   - cashierOrder.setDescription(cashierOrderDTO.getDescription());
24   - cashierOrder.setAttach(cashierOrderDTO.getAttach());
  16 + cashierOrder.setUserId(cashierOrderBO.getUserId());
  17 + cashierOrder.setType(CashierType.getByCode(cashierOrderBO.getCashierType()));
  18 + cashierOrder.setGoods(cashierOrderBO.getGoods());
  19 + cashierOrder.setAmount(cashierOrderBO.getAmount());
  20 + cashierOrder.setTimeout(cashierOrderBO.getTimeout());
  21 + cashierOrder.setOutTradeNo(cashierOrderBO.getOutTradeNo());
  22 + cashierOrder.setNotifyUrl(cashierOrderBO.getNotifyUrl());
  23 + cashierOrder.setRedirectUrl(cashierOrderBO.getRedirectUrl());
  24 + cashierOrder.setDescription(cashierOrderBO.getDescription());
  25 + cashierOrder.setAttach(cashierOrderBO.getAttach());
  26 + cashierOrder.setSource(SourceType.getIfNonNull(cashierOrderBO.getSource()));
25 27 return cashierOrder;
26 28 }
27 29 }
... ...
cashier-pipeline/src/main/java/com/diligrp/cashier/pipeline/client/CardPaymentHttpClient.java
1 1 package com.diligrp.cashier.pipeline.client;
2 2  
3   -import com.diligrp.cashier.pipeline.domain.*;
  3 +import com.diligrp.cashier.pipeline.domain.OnlineRefundRequest;
  4 +import com.diligrp.cashier.pipeline.domain.OnlineRefundResponse;
4 5 import com.diligrp.cashier.pipeline.domain.card.CardPaymentRequest;
5 6 import com.diligrp.cashier.pipeline.domain.card.CardPaymentResponse;
  7 +import com.diligrp.cashier.pipeline.domain.card.UserCardDTO;
  8 +import com.diligrp.cashier.pipeline.exception.PaymentPipelineException;
  9 +import com.diligrp.cashier.pipeline.type.OutPaymentType;
6 10 import com.diligrp.cashier.pipeline.type.PaymentState;
  11 +import com.diligrp.cashier.shared.ErrorCode;
7 12 import com.diligrp.cashier.shared.service.ServiceEndpointSupport;
  13 +import com.diligrp.cashier.shared.type.SourceType;
  14 +import com.diligrp.cashier.shared.util.JsonUtils;
  15 +import com.fasterxml.jackson.core.type.TypeReference;
8 16 import org.slf4j.Logger;
9 17 import org.slf4j.LoggerFactory;
10 18  
  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;
  24 +
11 25 public class CardPaymentHttpClient extends ServiceEndpointSupport {
12 26  
13 27 private static final Logger LOG = LoggerFactory.getLogger(CardPaymentHttpClient.class);
14 28  
15   - private static final String QUERY_PAYMENT_URI = "/api/cardPayment/queryResult";
  29 + private static final String PAYMENT_URL = "/api/cashier/pay";
  30 +
  31 + private static final String REFUND_URL = "/api/cashier/refund";
16 32  
17   - private static final String LIST_CARD_URI = "/api/query/list";
  33 + private static final String LIST_CARD_URL = "/cashier/query/accountList";
18 34  
19 35 private final String baseUri;
20 36  
21   - public CardPaymentHttpClient(String baseUri) {
  37 + private final Long outMchId;
  38 +
  39 + private final Long accountId;
  40 +
  41 + public CardPaymentHttpClient(String baseUri, Long outMchId, Long accountId) {
22 42 this.baseUri = baseUri;
  43 + this.outMchId = outMchId;
  44 + this.accountId = accountId;
23 45 }
24 46  
25 47 public CardPaymentResponse sendPaymentRequest(CardPaymentRequest request) {
26   - return null;
27   - }
  48 + String uri = String.format("%s%s", baseUri, PAYMENT_URL);
  49 + SourceType sourceType = request.getObject("source", SourceType.class);
  50 + Map<String, Object> params = new LinkedHashMap<>();
  51 + params.put("mchId", outMchId); // 市场ID
  52 + params.put("accountId", accountId); // 市场ID
  53 + params.put("fromCardNo", request.getCardNo());
  54 + params.put("fromAccountId", request.getAccountId());
  55 + params.put("amount", request.getAmount());
  56 + params.put("serviceCost", 0);
  57 + params.put("password", request.getPassword());
  58 + params.put("outTradeNo", request.getPaymentId());
  59 + params.put("goodsDesc", request.getGoods());
  60 + params.put("description", request.getDescription());
  61 + if (sourceType != null) {
  62 + params.put("sourceId", sourceType.getCode());
  63 + params.put("sourceName", sourceType.getName());
  64 + }
  65 + String payload = JsonUtils.toJsonString(params);
28 66  
29   - public CardPaymentResponse queryPaymentResponse(OnlinePrepayOrder order) {
30   - return null;
  67 + LOG.debug("Sending card payment request: {}", payload);
  68 + LocalDateTime now = LocalDateTime.now();
  69 + HttpResult result = send(uri, payload);
  70 + if (result.statusCode == 200) {
  71 + LOG.debug("Received from card payment pipeline: {}", result.responseText);
  72 + Map<String, Object> response = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {});
  73 + if ("200".equals(response.get("code"))) {
  74 + String outTradeNo = (String) response.get("data");
  75 + return new CardPaymentResponse(request.getPaymentId(), outTradeNo,
  76 + OutPaymentType.DILICARD, String.valueOf(request.getAccountId()), now,
  77 + PaymentState.SUCCESS, "园区卡支付成功");
  78 + } else {
  79 + throw new PaymentPipelineException(ErrorCode.SERVICE_ACCESS_ERROR, "园区卡支付失败: " + response.get("message"));
  80 + }
  81 + }
  82 + throw new PaymentPipelineException(ErrorCode.SERVICE_ACCESS_ERROR, "园区卡支付失败: 支付通道调用失败");
31 83 }
32 84  
33 85 public OnlineRefundResponse sendRefundRequest(OnlineRefundRequest request) {
34   - return null;
  86 + String uri = String.format("%s%s", baseUri, REFUND_URL);
  87 + Map<String, Object> params = new LinkedHashMap<>();
  88 + params.put("refundId", request.getRefundId());
  89 + params.put("outTradeNo", request.getPaymentId());
  90 + params.put("amount", request.getAmount());
  91 + String payload = JsonUtils.toJsonString(params);
  92 +
  93 + LOG.debug("Sending card refund request: {}", payload);
  94 + LocalDateTime now = LocalDateTime.now();
  95 + HttpResult result = send(uri, payload);
  96 + if (result.statusCode == 200) {
  97 + LOG.debug("Received from card payment pipeline: {}", result.responseText);
  98 + Map<String, Object> response = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {});
  99 + if ("200".equals(response.get("code"))) {
  100 + return new OnlineRefundResponse(request.getRefundId(), null, now,
  101 + PaymentState.SUCCESS, "园区卡退款成功");
  102 + } else {
  103 + throw new PaymentPipelineException(ErrorCode.SERVICE_ACCESS_ERROR, "园区卡支付退款失败: " + response.get("message"));
  104 + }
  105 + }
  106 + throw new PaymentPipelineException(ErrorCode.SERVICE_ACCESS_ERROR, "园区卡支付退款失败: 支付通道调用失败");
35 107 }
36 108  
37   - private PaymentState paymentState(int stateCode) {
38   - return switch (stateCode) {
39   - case 4 -> PaymentState.SUCCESS;
40   - case 5 -> PaymentState.FAILED;
41   - default -> PaymentState.PENDING;
42   - };
  109 + public List<UserCardDTO> listUserCards(String userId) {
  110 + String uri = String.format("%s%s", baseUri, LIST_CARD_URL);
  111 + Map<String, Object> params = new LinkedHashMap<>();
  112 + params.put("mchId", outMchId);
  113 + params.put("customerId", Long.parseLong(userId));
  114 + String payload = JsonUtils.toJsonString(params);
  115 +
  116 + LOG.debug("Sending list user card request: {}", payload);
  117 + HttpResult result = send(uri, payload);
  118 + if (result.statusCode == 200) {
  119 + LOG.debug("Received from card payment pipeline: {}", result.responseText);
  120 + Map<String, Object> response = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {});
  121 + if ("200".equals(response.get("code"))) {
  122 + List<UserCardDTO> userCards = new ArrayList<>();
  123 + Object data = response.get("data");
  124 + if (data != null) {
  125 + List<Map<String, Object>> cardList = JsonUtils.convertValue(data, new TypeReference<>() {});
  126 + for (Map<String, Object> card : cardList) {
  127 + UserCardDTO userCard = new UserCardDTO(convertLong(card.get("customerId")),
  128 + convertLong(card.get("accountId")), (String) card.get("cardNo"),
  129 + (String) card.get("customerName"), convertLong(card.get("amount")));
  130 + userCards.add(userCard);
  131 + }
  132 + }
  133 +
  134 + return userCards;
  135 + } else {
  136 + throw new PaymentPipelineException(ErrorCode.SERVICE_ACCESS_ERROR, "查询园区卡失败: " + response.get("message"));
  137 + }
  138 + }
  139 + throw new PaymentPipelineException(ErrorCode.SERVICE_ACCESS_ERROR, "查询园区卡失败: 支付通道调用失败");
43 140 }
44 141  
45 142 private Long convertLong(Object value) {
... ...
cashier-pipeline/src/main/java/com/diligrp/cashier/pipeline/client/WechatDirectHttpClient.java
... ... @@ -192,7 +192,7 @@ public class WechatDirectHttpClient extends WechatHttpClient {
192 192 Map<String, Object> response = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {});
193 193 LocalDateTime when = DateUtils.parseDateTime((String) response.get("success_time"), WechatConstants.RFC3339_FORMAT);
194 194 PaymentState state = WechatStateUtils.getRefundState((String) response.get("status"));
195   - return OnlineRefundResponse.of((String) response.get("out_refund_no"), (String) response.get("refund_id"),
  195 + return new OnlineRefundResponse((String) response.get("out_refund_no"), (String) response.get("refund_id"),
196 196 when, state, (String) response.get("status"));
197 197 } else {
198 198 LOG.info("send wechat refund failed: {}", result.statusCode);
... ... @@ -223,7 +223,7 @@ public class WechatDirectHttpClient extends WechatHttpClient {
223 223 Map<String, Object> response = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {});
224 224 LocalDateTime when = DateUtils.parseDateTime((String) response.get("success_time"), WechatConstants.RFC3339_FORMAT);
225 225 PaymentState state = WechatStateUtils.getRefundState((String) response.get("status"));
226   - return OnlineRefundResponse.of((String) response.get("out_refund_no"), (String) response.get("refund_id"),
  226 + return new OnlineRefundResponse((String) response.get("out_refund_no"), (String) response.get("refund_id"),
227 227 when, state, (String) response.get("user_received_account"));
228 228 } else if (result.statusCode == 404) {
229 229 throw new PaymentPipelineException(ErrorCode.OBJECT_NOT_FOUND, "发起微信退款查询失败: 退款单不存在");
... ...
cashier-pipeline/src/main/java/com/diligrp/cashier/pipeline/client/WechatPartnerHttpClient.java
... ... @@ -200,7 +200,7 @@ public class WechatPartnerHttpClient extends WechatHttpClient {
200 200 Map<String, Object> response = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {});
201 201 LocalDateTime when = DateUtils.parseDateTime((String) response.get("success_time"), WechatConstants.RFC3339_FORMAT);
202 202 PaymentState state = WechatStateUtils.getRefundState((String) response.get("status"));
203   - return OnlineRefundResponse.of((String) response.get("out_refund_no"), (String) response.get("refund_id"),
  203 + return new OnlineRefundResponse((String) response.get("out_refund_no"), (String) response.get("refund_id"),
204 204 when, state, (String) response.get("status"));
205 205 } else {
206 206 LOG.info("send wechat payment refund failed: {}", result.statusCode);
... ... @@ -234,7 +234,7 @@ public class WechatPartnerHttpClient extends WechatHttpClient {
234 234 Map<String, Object> response = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {});
235 235 LocalDateTime when = DateUtils.parseDateTime((String) response.get("success_time"), WechatConstants.RFC3339_FORMAT);
236 236 PaymentState state = WechatStateUtils.getRefundState((String) response.get("status"));
237   - return OnlineRefundResponse.of((String) response.get("out_refund_no"), (String) response.get("refund_id"),
  237 + return new OnlineRefundResponse((String) response.get("out_refund_no"), (String) response.get("refund_id"),
238 238 when, state, (String) response.get("user_received_account"));
239 239 } else if (result.statusCode == 404) {
240 240 throw new PaymentPipelineException(ErrorCode.OBJECT_NOT_FOUND, "发起微信退款查询失败: 退款单不存在");
... ...
cashier-pipeline/src/main/java/com/diligrp/cashier/pipeline/core/DefaultTimeStrategy.java
... ... @@ -4,13 +4,13 @@ import static com.diligrp.cashier.pipeline.Constants.*;
4 4  
5 5 public class DefaultTimeStrategy implements ScanTimeStrategy {
6 6 // 预支付订单扫描时间策略
7   - private long[] prepayTimeArray = { 10 * ONE_MINUTE };
  7 + private final long[] prepayTimeArray = { 10 * ONE_MINUTE };
8 8  
9 9 // 直接支付订单扫描时间策略
10   - private long[] paymentTimeArray = {5 * ONE_SECOND, 5 * ONE_SECOND, 5 * ONE_SECOND, 5 * ONE_SECOND, 5 * ONE_SECOND, 5 * ONE_SECOND, 5 * ONE_SECOND, 5 * ONE_SECOND, 10 * ONE_SECOND, 15 * ONE_SECOND};
  10 + private final long[] paymentTimeArray = {5 * ONE_SECOND, 5 * ONE_SECOND, 5 * ONE_SECOND, 5 * ONE_SECOND, 5 * ONE_SECOND, 5 * ONE_SECOND, 5 * ONE_SECOND, 5 * ONE_SECOND, 10 * ONE_SECOND, 15 * ONE_SECOND};
11 11  
12 12 // 退款订单扫描时间策略
13   - private long[] refundTimeArray = { 10 * ONE_MINUTE };
  13 + private final long[] refundTimeArray = { 10 * ONE_MINUTE };
14 14  
15 15 @Override
16 16 public long nextPrepayScanTime(int times) {
... ...
cashier-pipeline/src/main/java/com/diligrp/cashier/pipeline/core/DiliCardPipeline.java
... ... @@ -2,7 +2,6 @@ package com.diligrp.cashier.pipeline.core;
2 2  
3 3 import com.diligrp.cashier.pipeline.Constants;
4 4 import com.diligrp.cashier.pipeline.client.CardPaymentHttpClient;
5   -import com.diligrp.cashier.pipeline.domain.OnlinePrepayOrder;
6 5 import com.diligrp.cashier.pipeline.domain.OnlineRefundRequest;
7 6 import com.diligrp.cashier.pipeline.domain.OnlineRefundResponse;
8 7 import com.diligrp.cashier.pipeline.domain.card.CardPaymentRequest;
... ... @@ -10,6 +9,7 @@ import com.diligrp.cashier.pipeline.domain.card.CardPaymentResponse;
10 9 import com.diligrp.cashier.pipeline.exception.PaymentPipelineException;
11 10 import com.diligrp.cashier.pipeline.type.ChannelType;
12 11 import com.diligrp.cashier.shared.ErrorCode;
  12 +import com.diligrp.cashier.shared.util.AssertUtils;
13 13 import org.slf4j.Logger;
14 14 import org.slf4j.LoggerFactory;
15 15  
... ... @@ -26,8 +26,12 @@ public class DiliCardPipeline extends PaymentPipeline&lt;DiliCardPipeline.CardParam
26 26  
27 27 public DiliCardPipeline(long mchId, long pipelineId, String name, String uri, String params) throws Exception {
28 28 super(mchId, pipelineId, name, uri, params);
  29 + CardParams config = params();
  30 + AssertUtils.notNull(config.getOutMchId(), "园区卡支付缺少参数配置: outMchId");
  31 + AssertUtils.notNull(config.getAccountId(), "园区卡支付缺少参数配置: accountId");
  32 +
29 33 this.strategy = new DefaultTimeStrategy();
30   - this.client = new CardPaymentHttpClient(uri);
  34 + this.client = new CardPaymentHttpClient(uri, config.getOutMchId(), config.getAccountId());
31 35 }
32 36  
33 37 /**
... ... @@ -47,22 +51,6 @@ public class DiliCardPipeline extends PaymentPipeline&lt;DiliCardPipeline.CardParam
47 51 }
48 52  
49 53 /**
50   - * 查询支付订单状态
51   - */
52   - public CardPaymentResponse queryPaymentResponse(OnlinePrepayOrder request) {
53   - try {
54   - // 外部商户号设置为市场ID
55   - request.put(Constants.PARAM_MCH_ID, params().outMchId);
56   - return client.queryPaymentResponse(request);
57   - } catch (PaymentPipelineException | IllegalArgumentException pse) {
58   - throw pse;
59   - } catch (Exception ex) {
60   - LOG.error("Query card payment state request exception", ex);
61   - throw new PaymentPipelineException(ErrorCode.SYSTEM_UNKNOWN_ERROR, "查询地利支付状态失败");
62   - }
63   - }
64   -
65   - /**
66 54 * 退款申请
67 55 */
68 56 public OnlineRefundResponse sendRefundRequest(OnlineRefundRequest request) {
... ... @@ -92,20 +80,34 @@ public class DiliCardPipeline extends PaymentPipeline&lt;DiliCardPipeline.CardParam
92 80 return CardParams.class;
93 81 }
94 82  
  83 + public CardPaymentHttpClient getClient() {
  84 + return client;
  85 + }
  86 +
95 87 public static class CardParams extends PipelineParams {
96 88 // 园区卡所属市场
97   - private String outMchId;
  89 + private Long outMchId;
  90 + // 收款卡号
  91 + private Long accountId;
98 92  
99 93 public CardParams(String params) {
100 94 super(params);
101 95 }
102 96  
103   - public String getOutMchId() {
  97 + public Long getOutMchId() {
104 98 return outMchId;
105 99 }
106 100  
107   - public void setOutMchId(String outMchId) {
  101 + public void setOutMchId(Long outMchId) {
108 102 this.outMchId = outMchId;
109 103 }
  104 +
  105 + public Long getAccountId() {
  106 + return accountId;
  107 + }
  108 +
  109 + public void setAccountId(Long accountId) {
  110 + this.accountId = accountId;
  111 + }
110 112 }
111 113 }
... ...
cashier-pipeline/src/main/java/com/diligrp/cashier/pipeline/domain/OnlineRefundResponse.java
... ... @@ -15,16 +15,11 @@ public class OnlineRefundResponse {
15 15 // 退款完成时间
16 16 private final LocalDateTime when;
17 17 // 退款状态
18   - private final Integer state;
  18 + private final PaymentState state;
19 19 // 交易备注
20 20 private final String message;
21 21  
22   - public static OnlineRefundResponse of(String refundId, String outTradeNo, LocalDateTime when,
23   - PaymentState state, String message) {
24   - return new OnlineRefundResponse(refundId, outTradeNo, when, state.getCode(), message);
25   - }
26   -
27   - public OnlineRefundResponse(String refundId, String outTradeNo, LocalDateTime when, Integer state, String message) {
  22 + public OnlineRefundResponse(String refundId, String outTradeNo, LocalDateTime when, PaymentState state, String message) {
28 23 this.refundId = refundId;
29 24 this.outTradeNo = outTradeNo;
30 25 this.when = when;
... ... @@ -44,7 +39,7 @@ public class OnlineRefundResponse {
44 39 return when;
45 40 }
46 41  
47   - public Integer getState() {
  42 + public PaymentState getState() {
48 43 return state;
49 44 }
50 45  
... ...
cashier-pipeline/src/main/java/com/diligrp/cashier/pipeline/domain/card/CardPaymentRequest.java
... ... @@ -5,14 +5,19 @@ import com.diligrp.cashier.pipeline.domain.OnlinePaymentRequest;
5 5 import java.time.LocalDateTime;
6 6  
7 7 public class CardPaymentRequest extends OnlinePaymentRequest {
  8 + // 付款账号
8 9 private final Long accountId;
  10 + // 付款卡号
9 11 private final String cardNo;
  12 + // 密码
  13 + private final String password;
10 14  
11 15 public CardPaymentRequest(String paymentId, long amount, String goods, String description, LocalDateTime when,
12   - Long accountId, String cardNo) {
  16 + Long accountId, String cardNo, String password) {
13 17 super(paymentId, amount, goods, description, when);
14 18 this.accountId = accountId;
15 19 this.cardNo = cardNo;
  20 + this.password = password;
16 21 }
17 22  
18 23 public Long getAccountId() {
... ... @@ -22,4 +27,8 @@ public class CardPaymentRequest extends OnlinePaymentRequest {
22 27 public String getCardNo() {
23 28 return cardNo;
24 29 }
  30 +
  31 + public String getPassword() {
  32 + return password;
  33 + }
25 34 }
... ...
cashier-pipeline/src/main/java/com/diligrp/cashier/pipeline/domain/card/UserCardDTO.java
... ... @@ -12,20 +12,18 @@ public class UserCardDTO {
12 12 private String cardNo;
13 13 // 持卡人名称
14 14 private String name;
  15 + // 卡余额
  16 + private Long amount;
15 17  
16 18 public UserCardDTO() {
17 19 }
18 20  
19   - public UserCardDTO(Long accountId, String cardNo) {
20   - this.accountId = accountId;
21   - this.cardNo = cardNo;
22   - }
23   -
24   - public UserCardDTO(Long customerId, Long accountId, String cardNo, String name) {
  21 + public UserCardDTO(Long customerId, Long accountId, String cardNo, String name, Long amount) {
25 22 this.customerId = customerId;
26 23 this.accountId = accountId;
27 24 this.cardNo = cardNo;
28 25 this.name = name;
  26 + this.amount = amount;
29 27 }
30 28  
31 29 public Long getCustomerId() {
... ... @@ -59,4 +57,12 @@ public class UserCardDTO {
59 57 public void setName(String name) {
60 58 this.name = name;
61 59 }
  60 +
  61 + public Long getAmount() {
  62 + return amount;
  63 + }
  64 +
  65 + public void setAmount(Long amount) {
  66 + this.amount = amount;
  67 + }
62 68 }
... ...
cashier-pipeline/src/main/java/com/diligrp/cashier/pipeline/type/CashierType.java
... ... @@ -44,9 +44,7 @@ public enum CashierType implements IEnumType {
44 44  
45 45 public static CashierType getIfNonNull(Integer code) {
46 46 if (Objects.nonNull(code)) {
47   - Stream<CashierType> TYPES = Arrays.stream(CashierType.values());
48   - return TYPES.filter(type -> type.getCode() == code).findFirst()
49   - .orElseThrow(() -> new IllegalArgumentException("Invalid cashier desk"));
  47 + return getByCode(code);
50 48 }
51 49 return null;
52 50 }
... ...
cashier-pipeline/src/main/java/com/diligrp/cashier/pipeline/type/OutPaymentType.java
... ... @@ -3,6 +3,7 @@ package com.diligrp.cashier.pipeline.type;
3 3 import com.diligrp.cashier.pipeline.exception.PaymentPipelineException;
4 4 import com.diligrp.cashier.shared.ErrorCode;
5 5 import com.diligrp.cashier.shared.type.IEnumType;
  6 +import com.fasterxml.jackson.annotation.JsonValue;
6 7  
7 8 import java.util.Arrays;
8 9 import java.util.Optional;
... ... @@ -58,6 +59,7 @@ public enum OutPaymentType implements IEnumType {
58 59 }
59 60  
60 61 @Override
  62 + @JsonValue
61 63 public int getCode() {
62 64 return code;
63 65 }
... ...
cashier-shared/src/main/java/com/diligrp/cashier/shared/exception/PlatformServiceException.java
... ... @@ -30,10 +30,10 @@ public class PlatformServiceException extends RuntimeException {
30 30 super(message, ex);
31 31 }
32 32  
33   -// @Override
34   -// public Throwable fillInStackTrace() {
35   -// return stackTrace ? super.fillInStackTrace() : this;
36   -// }
  33 + @Override
  34 + public Throwable fillInStackTrace() {
  35 + return stackTrace ? super.fillInStackTrace() : this;
  36 + }
37 37  
38 38 public String getCode() {
39 39 return code;
... ...
cashier-shared/src/main/java/com/diligrp/cashier/shared/spi/domain/CashierOrderBO.java
... ... @@ -23,6 +23,8 @@ public class CashierOrderBO {
23 23 private String description;
24 24 // 附加数据
25 25 private String attach;
  26 + // 订单来源
  27 + private Integer source;
26 28  
27 29 public Long getMchId() {
28 30 return mchId;
... ... @@ -111,4 +113,12 @@ public class CashierOrderBO {
111 113 public void setAttach(String attach) {
112 114 this.attach = attach;
113 115 }
  116 +
  117 + public Integer getSource() {
  118 + return source;
  119 + }
  120 +
  121 + public void setSource(Integer source) {
  122 + this.source = source;
  123 + }
114 124 }
... ...
cashier-trade/src/main/java/com/diligrp/cashier/trade/type/SourceType.java renamed to cashier-shared/src/main/java/com/diligrp/cashier/shared/type/SourceType.java
1   -package com.diligrp.cashier.trade.type;
2   -
3   -import com.diligrp.cashier.shared.type.IEnumType;
  1 +package com.diligrp.cashier.shared.type;
4 2  
5 3 import java.util.Arrays;
6 4 import java.util.List;
  5 +import java.util.Objects;
7 6 import java.util.Optional;
8 7 import java.util.stream.Stream;
9 8  
... ... @@ -12,13 +11,7 @@ import java.util.stream.Stream;
12 11 */
13 12 public enum SourceType implements IEnumType {
14 13  
15   - PC("PC端", 1),
16   -
17   - MINIPRO("小程序端", 2),
18   -
19   - APP("APP端", 3),
20   -
21   - ATM("自助机", 4);
  14 + RTMARK("大润发商城", 10);
22 15  
23 16 private final String name;
24 17 private final int code;
... ... @@ -37,6 +30,17 @@ public enum SourceType implements IEnumType {
37 30 return TYPES.filter(type -> type.getCode() == code).findFirst();
38 31 }
39 32  
  33 + public static SourceType getByCode(int code) {
  34 + return getType(code).orElseThrow(() -> new IllegalArgumentException("系统暂不支持此订单来源"));
  35 + }
  36 +
  37 + public static SourceType getIfNonNull(Integer code) {
  38 + if (Objects.nonNull(code)) {
  39 + return getByCode(code);
  40 + }
  41 + return null;
  42 + }
  43 +
40 44 public static String getName(int code) {
41 45 return getType(code).map(SourceType::getName).orElse(null);
42 46 }
... ...
cashier-trade/src/main/java/com/diligrp/cashier/trade/domain/CashierOrder.java
1 1 package com.diligrp.cashier.trade.domain;
2 2  
3 3 import com.diligrp.cashier.pipeline.type.CashierType;
  4 +import com.diligrp.cashier.shared.type.SourceType;
4 5  
5 6 public class CashierOrder {
6 7 // 业务系统用户标识
... ... @@ -23,6 +24,8 @@ public class CashierOrder {
23 24 private String description;
24 25 // 附加数据
25 26 private String attach;
  27 + // 订单来源
  28 + private SourceType source;
26 29  
27 30 public String getUserId() {
28 31 return userId;
... ... @@ -103,4 +106,12 @@ public class CashierOrder {
103 106 public void setAttach(String attach) {
104 107 this.attach = attach;
105 108 }
  109 +
  110 + public SourceType getSource() {
  111 + return source;
  112 + }
  113 +
  114 + public void setSource(SourceType source) {
  115 + this.source = source;
  116 + }
106 117 }
... ...
cashier-trade/src/main/java/com/diligrp/cashier/trade/manager/TaskMessageSender.java
... ... @@ -33,7 +33,7 @@ public class TaskMessageSender {
33 33 */
34 34 public void sendDelayTaskMessage(TaskMessage task, long delayInMillis) {
35 35 if (delayInMillis < 0) {
36   - LOG.info("No need send scan order message[type={}]", task.getType());
  36 + LOG.info("No need send scan order message: {}", task);
37 37 return;
38 38 }
39 39  
... ...
cashier-trade/src/main/java/com/diligrp/cashier/trade/model/TradeOrder.java
1 1 package com.diligrp.cashier.trade.model;
2 2  
  3 +import com.diligrp.cashier.pipeline.type.CashierType;
3 4 import com.diligrp.cashier.shared.domain.BaseDO;
  5 +import com.diligrp.cashier.shared.type.SourceType;
4 6  
5 7 import java.time.LocalDateTime;
6 8  
... ... @@ -154,8 +156,8 @@ public class TradeOrder extends BaseDO {
154 156 return this;
155 157 }
156 158  
157   - public Builder type(Integer type) {
158   - TradeOrder.this.type = type;
  159 + public Builder type(CashierType type) {
  160 + TradeOrder.this.type = type.getCode();
159 161 return this;
160 162 }
161 163  
... ... @@ -204,8 +206,8 @@ public class TradeOrder extends BaseDO {
204 206 return this;
205 207 }
206 208  
207   - public Builder source(Integer source) {
208   - TradeOrder.this.source = source;
  209 + public Builder source(SourceType source) {
  210 + TradeOrder.this.source = source != null ? source.getCode() : null;
209 211 return this;
210 212 }
211 213  
... ...
cashier-trade/src/main/java/com/diligrp/cashier/trade/service/impl/CashierAssistantServiceImpl.java
... ... @@ -69,7 +69,7 @@ public class CashierAssistantServiceImpl implements ICashierAssistantService {
69 69 if (!PaymentState.isFinished(response.getState().getCode())) {
70 70 try {
71 71 onlinePipeline.closePrepayOrder(order);
72   - LOG.debug("scanCashierTradeOrder: close online prepay order {}", payment.getPaymentId());
  72 + LOG.info("scanCashierTradeOrder: close online prepay order {}", payment.getPaymentId());
73 73 response = new OnlinePaymentResponse(response.getPaymentId(), response.getOutTradeNo(),
74 74 response.getOutPayType(), response.getPayerId(), response.getWhen(),
75 75 PaymentState.FAILED, "自动关闭超时的支付订单");
... ... @@ -85,6 +85,7 @@ public class CashierAssistantServiceImpl implements ICashierAssistantService {
85 85 if (!TradeState.isFinished(trade.getState())) {
86 86 TradeStateDTO tradeStateDTO = TradeStateDTO.of(trade.getTradeId(), TradeState.CLOSED, trade.getVersion(), now);
87 87 tradeAssistantService.proceedTradeOrder(tradeStateDTO);
  88 + LOG.info("scanCashierTradeOrder: close cashier trade order {}", tradeId);
88 89 }
89 90 } finally {
90 91 if (lock.isHeldByCurrentThread()) {
... ...
cashier-trade/src/main/java/com/diligrp/cashier/trade/service/impl/CashierPaymentServiceImpl.java
... ... @@ -14,7 +14,7 @@ import com.diligrp.cashier.pipeline.type.OutPaymentType;
14 14 import com.diligrp.cashier.pipeline.type.PaymentState;
15 15 import com.diligrp.cashier.pipeline.type.PaymentType;
16 16 import com.diligrp.cashier.shared.ErrorCode;
17   -import com.diligrp.cashier.shared.util.DateUtils;
  17 +import com.diligrp.cashier.shared.type.SourceType;
18 18 import com.diligrp.cashier.trade.Constants;
19 19 import com.diligrp.cashier.trade.dao.IOnlinePaymentDao;
20 20 import com.diligrp.cashier.trade.dao.ITradeOrderDao;
... ... @@ -89,10 +89,10 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService {
89 89 int timeout = Objects.isNull(cashierOrder.getTimeout()) ? Constants.DEFAULT_TRADE_TIMEOUT : cashierOrder.getTimeout();
90 90 timeout = Math.min(Math.max(timeout, Constants.MIN_TRADE_TIMEOUT), Constants.MAX_TRADE_TIMEOUT);
91 91 TradeOrder tradeOrder = TradeOrder.builder().mchId(merchant.getMchId()).tradeId(tradeId)
92   - .type(cashierOrder.getType().getCode()).outTradeNo(cashierOrder.getOutTradeNo()).amount(cashierOrder.getAmount())
  92 + .type(cashierOrder.getType()).outTradeNo(cashierOrder.getOutTradeNo()).amount(cashierOrder.getAmount())
93 93 .maxAmount(cashierOrder.getAmount()).goods(cashierOrder.getGoods()).timeout(timeout).state(TradeState.PENDING.getCode())
94 94 .notifyUrl(cashierOrder.getNotifyUrl()).description(cashierOrder.getDescription()).attach(cashierOrder.getAttach())
95   - .source(0).version(0).createdTime(now).modifiedTime(now).build();
  95 + .source(cashierOrder.getSource()).version(0).createdTime(now).modifiedTime(now).build();
96 96 tradeOrderDao.insertTradeOrder(tradeOrder);
97 97  
98 98 // 兜底处理交易订单,根据支付结果选择关闭或完成交易订单
... ... @@ -152,6 +152,8 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService {
152 152 } else if (pipeline instanceof DiliCardPipeline cardPipeline) { // 园区卡支付通道
153 153 // 园区卡支付通道: 所有的收银台类型使用的是同一种园区卡支付流程
154 154 CardPaymentRequest request = new CardPaymentConverter(trade, paymentId, now).convert(cashierPayment);
  155 + // 园区卡支付需要订单来源
  156 + request.attach("source", SourceType.getIfNonNull(trade.getSource()));
155 157 // 修改支付状态为支付中,防止重复支付
156 158 CardPaymentResponse response = cardPipeline.sendPaymentRequest(request);
157 159 // 支付成功插入支付记录并修改交易订单状态,失败可以继续支付
... ... @@ -298,13 +300,9 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService {
298 300 // online模式下,如果本地支付申请没有明确的支付结果,将调用支付通道查询预支付订单状态
299 301 if (!PaymentState.isFinished(payment.getState()) && "online".equalsIgnoreCase(mode)) {
300 302 OnlinePrepayOrder order = new OnlinePrepayOrder(paymentId, payment.getOutTradeNo());
301   - PaymentPipeline<?> paymentPipeline = paymentPipelineManager.findPipelineById(payment.getPipelineId(), PaymentPipeline.class);
302   - if (paymentPipeline instanceof OnlinePipeline<?> pipeline) {
303   - OnlinePaymentResponse response = pipeline.queryPrepayResponse(order);
304   - return OnlinePaymentResult.of(trade.getTradeId(), paymentId, response.getState(), trade.getOutTradeNo(),
305   - response.getOutPayType(), response.getPayerId(), response.getWhen(), response.getMessage());
306   - } else if (paymentPipeline instanceof DiliCardPipeline pipeline) {
307   - CardPaymentResponse response = pipeline.queryPaymentResponse(order);
  303 + PaymentPipeline<?> pipeline = paymentPipelineManager.findPipelineById(payment.getPipelineId(), PaymentPipeline.class);
  304 + if (pipeline instanceof OnlinePipeline<?> onlinePipeline) {
  305 + OnlinePaymentResponse response = onlinePipeline.queryPrepayResponse(order);
308 306 return OnlinePaymentResult.of(trade.getTradeId(), paymentId, response.getState(), trade.getOutTradeNo(),
309 307 response.getOutPayType(), response.getPayerId(), response.getWhen(), response.getMessage());
310 308 }
... ... @@ -351,17 +349,18 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService {
351 349 .state(response.getState()).description(request.getDescription()).version(0).createdTime(now).modifiedTime(now).build();
352 350 onlinePaymentDao.insertOnlinePayment(refund);
353 351  
354   - if (PaymentState.SUCCESS.equalTo(response.getState())) {
  352 + if (response.getState() == PaymentState.SUCCESS) {
355 353 Long newAmount = trade.getAmount() - refund.getAmount();
356 354 TradeStateDTO tradeState = TradeStateDTO.of(trade.getTradeId(), newAmount, TradeState.REFUND, trade.getVersion(), now);
357 355 tradeAssistantService.proceedTradeOrder(tradeState);
358   - } else if (!PaymentState.isFinished(response.getState())) {
  356 + } else if (!PaymentState.isFinished(response.getState().getCode())) {
359 357 // 固定周期后,查询退款状态,根据状态完成退款订单
360 358 TaskMessage message = new TaskMessage(TaskMessage.TYPE_CASHIER_REFUND_SCAN, refundId, "1");
361 359 taskMessageSender.sendDelayTaskMessage(message, trade.getTimeout() * 1000);
362 360 }
363 361  
364   - return new OnlineRefundResult(refundId, payment.getPaymentId(), response.getState(), response.getWhen(), response.getMessage());
  362 + return new OnlineRefundResult(refundId, payment.getPaymentId(), response.getState().getCode(),
  363 + response.getWhen(), response.getMessage());
365 364 }
366 365  
367 366 @Override
... ... @@ -372,7 +371,7 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService {
372 371 LOG.warn("Duplicate process online refund order[{}:{}]", response.getRefundId(), response.getState());
373 372 return;
374 373 }
375   - if (!PaymentState.isFinished(response.getState())) {
  374 + if (!PaymentState.isFinished(response.getState().getCode())) {
376 375 LOG.warn("Ignore online refund order[{}:{}]", response.getRefundId(), response.getState());
377 376 return;
378 377 }
... ... @@ -385,14 +384,14 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService {
385 384 .description(response.getMessage()).version(refund.getVersion()).modifiedTime(now).build();
386 385 tradeAssistantService.proceedOnlinePayment(refundDTO);
387 386  
388   - if (PaymentState.SUCCESS.equalTo(response.getState())) {
  387 + if (response.getState() == PaymentState.SUCCESS) {
389 388 Long newAmount = trade.getAmount() - refund.getAmount();
390 389 TradeStateDTO tradeState = TradeStateDTO.of(trade.getTradeId(), newAmount, TradeState.REFUND, trade.getVersion(), now);
391 390 tradeAssistantService.proceedTradeOrder(tradeState);
392 391 }
393 392  
394 393 OnlineRefundResult refundResult = new OnlineRefundResult(response.getRefundId(), refund.getObjectId(),
395   - response.getState(), response.getWhen(), response.getMessage());
  394 + response.getState().getCode(), response.getWhen(), response.getMessage());
396 395 paymentResultManager.notifyRefundResult(refund.getNotifyUrl(), refundResult);
397 396 }
398 397  
... ... @@ -407,7 +406,8 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService {
407 406 if (pipeline instanceof OnlinePipeline<?> onlinePipeline) {
408 407 OnlineRefundOrder order = new OnlineRefundOrder(refundId, refund.getOutTradeNo());
409 408 OnlineRefundResponse response = onlinePipeline.queryRefundResponse(order);
410   - return new OnlineRefundResult(refundId, refund.getObjectId(), response.getState(), response.getWhen(), response.getMessage());
  409 + return new OnlineRefundResult(refundId, refund.getObjectId(), response.getState().getCode(),
  410 + response.getWhen(), response.getMessage());
411 411 }
412 412 }
413 413 return new OnlineRefundResult(refundId, refund.getObjectId(), refund.getState(), refund.getFinishTime(), refund.getDescription());
... ...
cashier-trade/src/main/java/com/diligrp/cashier/trade/type/SnowflakeKey.java
... ... @@ -7,6 +7,5 @@ public enum SnowflakeKey implements SnowflakeKeyManager.SnowflakeKey {
7 7 PAYMENT_ID,
8 8 MALL_BIZ_ORDER_ID,
9 9 MALL_BIZ_PAYMENT_ID,
10   - MALL_BIZ_REFUND_ID,
11   - ;
  10 + MALL_BIZ_REFUND_ID;
12 11 }
... ...
cashier-trade/src/main/java/com/diligrp/cashier/trade/util/CardPaymentConverter.java
... ... @@ -2,10 +2,9 @@ package com.diligrp.cashier.trade.util;
2 2  
3 3 import com.diligrp.cashier.pipeline.domain.card.CardPaymentRequest;
4 4 import com.diligrp.cashier.shared.codec.IConverter;
  5 +import com.diligrp.cashier.shared.util.AssertUtils;
5 6 import com.diligrp.cashier.trade.domain.CashierPayment;
6   -import com.diligrp.cashier.trade.model.OnlinePayment;
7 7 import com.diligrp.cashier.trade.model.TradeOrder;
8   -import org.springframework.util.Assert;
9 8  
10 9 import java.time.LocalDateTime;
11 10 import java.util.Map;
... ... @@ -16,6 +15,8 @@ public class CardPaymentConverter implements IConverter&lt;CashierPayment, CardPaym
16 15  
17 16 private static final String PARAM_CARD_NO = "cardNo";
18 17  
  18 + private static final String PARAM_PASSWORD = "password";
  19 +
19 20 private final TradeOrder tradeOrder;
20 21  
21 22 private final String paymentId;
... ... @@ -31,13 +32,15 @@ public class CardPaymentConverter implements IConverter&lt;CashierPayment, CardPaym
31 32 @Override
32 33 public CardPaymentRequest convert(CashierPayment payment) {
33 34 Map<String, Object> params = payment.getParams();
34   - Assert.notNull(params, "params missed");
35   - Long accountId = (Long) payment.getParams().get(PARAM_ACCOUNT_ID);
  35 + AssertUtils.notNull(params, "params missed");
  36 + Long accountId = ((Number) payment.getParams().get(PARAM_ACCOUNT_ID)).longValue();
36 37 String cardNo = (String) params.get(PARAM_CARD_NO);
37   - Assert.notNull(accountId, "params.accountId missed");
38   - Assert.notNull(cardNo, "params.cardNo missed");
  38 + String password = (String) params.get(PARAM_PASSWORD);
  39 + AssertUtils.notNull(accountId, "params.accountId missed");
  40 + AssertUtils.notEmpty(cardNo, "params.cardNo missed");
  41 + AssertUtils.notEmpty(password, "params.password missed");
39 42  
40 43 return new CardPaymentRequest(paymentId, tradeOrder.getMaxAmount(),
41   - tradeOrder.getGoods(), tradeOrder.getDescription(), when, accountId, cardNo);
  44 + tradeOrder.getGoods(), tradeOrder.getDescription(), when, accountId, cardNo, password);
42 45 }
43 46 }
... ...
scripts/cashier-data.sql
... ... @@ -8,4 +8,4 @@ INSERT INTO `dili_cashier`.upay_wechat_param(pipeline_id, mch_id, app_id, app_se
8 8 VALUES(10011, '1679223106', 'wxca99d56a6ab15f29', '9c254c0ab932b3c30292a05679a688f7', '60C2877836D1D618D2E40186995BB00299D92F44','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', 'RSfFvEBBQiHz8GZyDcP2eSUlZJgKjdxk', 2, now());
9 9 -- 根据环境配置不同的uri
10 10 INSERT INTO `dili_cashier`.upay_payment_pipeline(mch_id, pipeline_id, channel_id, type, name, uri, param, state, created_time, modified_time)
11   -VALUES (1001, 10012, 19, 2, '中瑞园区卡支付通道', 'http://10.28.3.9:8081', null, 1, now(), now());
  11 +VALUES (1001, 10012, 19, 2, '中瑞园区卡支付通道', 'http://gateway.dev.nong12.com/pay-service', '{"outMchId": 9, "accountId": 118924}', 1, now(), now());
... ...