Commit eb7b1af06ed4b483f64670c48835e117bb130b85
1 parent
e2a07d8f
upgrade after testing
Showing
10 changed files
with
94 additions
and
124 deletions
cashier-pipeline/src/main/java/com/diligrp/cashier/pipeline/client/CardPaymentHttpClient.java
| @@ -68,7 +68,7 @@ public class CardPaymentHttpClient extends ServiceEndpointSupport { | @@ -68,7 +68,7 @@ public class CardPaymentHttpClient extends ServiceEndpointSupport { | ||
| 68 | LocalDateTime now = LocalDateTime.now(); | 68 | LocalDateTime now = LocalDateTime.now(); |
| 69 | HttpResult result = send(uri, payload); | 69 | HttpResult result = send(uri, payload); |
| 70 | if (result.statusCode == 200) { | 70 | if (result.statusCode == 200) { |
| 71 | - LOG.debug("Received from card payment pipeline: {}\n{}", request.getPaymentId(), result.responseText); | 71 | + LOG.debug("Card payment response received: {}\n{}", request.getPaymentId(), result.responseText); |
| 72 | Map<String, Object> response = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {}); | 72 | Map<String, Object> response = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {}); |
| 73 | if ("200".equals(response.get("code"))) { | 73 | if ("200".equals(response.get("code"))) { |
| 74 | Map<String, Object> data = (Map<String, Object>) response.get("data"); | 74 | Map<String, Object> data = (Map<String, Object>) response.get("data"); |
| @@ -99,7 +99,7 @@ public class CardPaymentHttpClient extends ServiceEndpointSupport { | @@ -99,7 +99,7 @@ public class CardPaymentHttpClient extends ServiceEndpointSupport { | ||
| 99 | LocalDateTime now = LocalDateTime.now(); | 99 | LocalDateTime now = LocalDateTime.now(); |
| 100 | HttpResult result = send(uri, payload); | 100 | HttpResult result = send(uri, payload); |
| 101 | if (result.statusCode == 200) { | 101 | if (result.statusCode == 200) { |
| 102 | - LOG.debug("Received from card payment pipeline: {}\n", request.getRefundId(), result.responseText); | 102 | + LOG.debug("Card refund response received: {}\n{}", request.getRefundId(), result.responseText); |
| 103 | Map<String, Object> response = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {}); | 103 | Map<String, Object> response = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {}); |
| 104 | if ("200".equals(response.get("code"))) { | 104 | if ("200".equals(response.get("code"))) { |
| 105 | return new OnlineRefundResponse(request.getRefundId(), null, now, | 105 | return new OnlineRefundResponse(request.getRefundId(), null, now, |
| @@ -121,7 +121,7 @@ public class CardPaymentHttpClient extends ServiceEndpointSupport { | @@ -121,7 +121,7 @@ public class CardPaymentHttpClient extends ServiceEndpointSupport { | ||
| 121 | LOG.debug("Sending list user card request: {}\n{}", userId, payload); | 121 | LOG.debug("Sending list user card request: {}\n{}", userId, payload); |
| 122 | HttpResult result = send(uri, payload); | 122 | HttpResult result = send(uri, payload); |
| 123 | if (result.statusCode == 200) { | 123 | if (result.statusCode == 200) { |
| 124 | - LOG.debug("Received from card payment pipeline: {}\n{}", userId, result.responseText); | 124 | + LOG.debug("List user card response received: {}\n{}", userId, result.responseText); |
| 125 | Map<String, Object> response = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {}); | 125 | Map<String, Object> response = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {}); |
| 126 | if ("200".equals(response.get("code"))) { | 126 | if ("200".equals(response.get("code"))) { |
| 127 | List<UserCardDTO> userCards = new ArrayList<>(); | 127 | List<UserCardDTO> userCards = new ArrayList<>(); |
cashier-pipeline/src/main/java/com/diligrp/cashier/pipeline/client/RcbOnlineHttpClient.java
| @@ -11,7 +11,6 @@ | @@ -11,7 +11,6 @@ | ||
| 11 | import com.diligrp.cashier.shared.service.ServiceEndpointSupport; | 11 | import com.diligrp.cashier.shared.service.ServiceEndpointSupport; |
| 12 | import com.diligrp.cashier.shared.util.*; | 12 | import com.diligrp.cashier.shared.util.*; |
| 13 | import com.fasterxml.jackson.core.type.TypeReference; | 13 | import com.fasterxml.jackson.core.type.TypeReference; |
| 14 | - import jakarta.annotation.Resource; | ||
| 15 | import org.slf4j.Logger; | 14 | import org.slf4j.Logger; |
| 16 | import org.slf4j.LoggerFactory; | 15 | import org.slf4j.LoggerFactory; |
| 17 | import org.springframework.dao.DataAccessException; | 16 | import org.springframework.dao.DataAccessException; |
| @@ -38,11 +37,6 @@ public class RcbOnlineHttpClient extends ServiceEndpointSupport { | @@ -38,11 +37,6 @@ public class RcbOnlineHttpClient extends ServiceEndpointSupport { | ||
| 38 | 37 | ||
| 39 | private static final Logger LOG = LoggerFactory.getLogger(RcbOnlineHttpClient.class); | 38 | private static final Logger LOG = LoggerFactory.getLogger(RcbOnlineHttpClient.class); |
| 40 | 39 | ||
| 41 | - // 微信API BASE URL | ||
| 42 | - private static final String WECHAT_BASE_URL = "https://api.weixin.qq.com"; | ||
| 43 | - // code2session接口: 根据登录凭证code获取登录信息 | ||
| 44 | - private static final String CODE_TO_SESSION = "/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code"; | ||
| 45 | - | ||
| 46 | private static final int STATUS_OK = 200; | 40 | private static final int STATUS_OK = 200; |
| 47 | 41 | ||
| 48 | private final String uri; | 42 | private final String uri; |
| @@ -89,7 +83,7 @@ public class RcbOnlineHttpClient extends ServiceEndpointSupport { | @@ -89,7 +83,7 @@ public class RcbOnlineHttpClient extends ServiceEndpointSupport { | ||
| 89 | LOG.error("Failed to send rcb MiniPro prepay request: {}", result.statusCode); | 83 | LOG.error("Failed to send rcb MiniPro prepay request: {}", result.statusCode); |
| 90 | throw new PaymentPipelineException(ErrorCode.SYSTEM_UNKNOWN_ERROR, "调用小程序预支付接口失败: " + result.statusCode); | 84 | throw new PaymentPipelineException(ErrorCode.SYSTEM_UNKNOWN_ERROR, "调用小程序预支付接口失败: " + result.statusCode); |
| 91 | } | 85 | } |
| 92 | - LOG.debug("Received from rcb MiniPro pipeline: {}\n{}", request.getPaymentId(), result.responseText); | 86 | + LOG.debug("Rcb MiniPro prepay received: {}\n{}", request.getPaymentId(), result.responseText); |
| 93 | 87 | ||
| 94 | Map<String, String> data = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {}); | 88 | Map<String, String> data = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {}); |
| 95 | String resultCode = data.get("resultCode"); | 89 | String resultCode = data.get("resultCode"); |
| @@ -117,13 +111,13 @@ public class RcbOnlineHttpClient extends ServiceEndpointSupport { | @@ -117,13 +111,13 @@ public class RcbOnlineHttpClient extends ServiceEndpointSupport { | ||
| 117 | 111 | ||
| 118 | params.put("sign", RcbSignatureUtils.sign(params, key)); | 112 | params.put("sign", RcbSignatureUtils.sign(params, key)); |
| 119 | String payload = JsonUtils.toJsonString(params); | 113 | String payload = JsonUtils.toJsonString(params); |
| 120 | - LOG.info("Sending rcb query prepay order state request: {}", request.getPaymentId()); | 114 | + LOG.info("Sending query rcb prepay order request: {}", request.getPaymentId()); |
| 121 | HttpResult result = send(uri + "/cposp/pay/orderQuery", payload); | 115 | HttpResult result = send(uri + "/cposp/pay/orderQuery", payload); |
| 122 | if (result.statusCode != STATUS_OK) { | 116 | if (result.statusCode != STATUS_OK) { |
| 123 | - LOG.error("Failed to query rcb prepay order state: {}", result.statusCode); | 117 | + LOG.error("Failed to query rcb prepay order: {}", result.statusCode); |
| 124 | throw new PaymentPipelineException(ErrorCode.SYSTEM_UNKNOWN_ERROR, "查询支付状态失败: " + result.statusCode); | 118 | throw new PaymentPipelineException(ErrorCode.SYSTEM_UNKNOWN_ERROR, "查询支付状态失败: " + result.statusCode); |
| 125 | } | 119 | } |
| 126 | - LOG.debug("Received from rcb online pipeline: {}\n{}", request.getPaymentId(), result.responseText); | 120 | + LOG.debug("Query rcb prepay order response received: {}\n{}", request.getPaymentId(), result.responseText); |
| 127 | 121 | ||
| 128 | Map<String, String> data = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {}); | 122 | Map<String, String> data = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {}); |
| 129 | String signature = data.remove("sign"); | 123 | String signature = data.remove("sign"); |
| @@ -175,7 +169,7 @@ public class RcbOnlineHttpClient extends ServiceEndpointSupport { | @@ -175,7 +169,7 @@ public class RcbOnlineHttpClient extends ServiceEndpointSupport { | ||
| 175 | LOG.error("Failed to close rcb prepay order: {}", request.getPaymentId()); | 169 | LOG.error("Failed to close rcb prepay order: {}", request.getPaymentId()); |
| 176 | throw new PaymentPipelineException(ErrorCode.SYSTEM_UNKNOWN_ERROR, "关闭支付订单失败: " + result.statusCode); | 170 | throw new PaymentPipelineException(ErrorCode.SYSTEM_UNKNOWN_ERROR, "关闭支付订单失败: " + result.statusCode); |
| 177 | } | 171 | } |
| 178 | - LOG.debug("Received from rcb online pipeline: {}\n{}", request.getPaymentId(), result.responseText); | 172 | + LOG.debug("Close rcb prepay order response received: {}\n{}", request.getPaymentId(), result.responseText); |
| 179 | 173 | ||
| 180 | Map<String, String> data = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {}); | 174 | Map<String, String> data = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {}); |
| 181 | String resultCode = data.get("resultCode"); | 175 | String resultCode = data.get("resultCode"); |
| @@ -212,7 +206,7 @@ public class RcbOnlineHttpClient extends ServiceEndpointSupport { | @@ -212,7 +206,7 @@ public class RcbOnlineHttpClient extends ServiceEndpointSupport { | ||
| 212 | LOG.error("Failed to send rcb refund request: {}", request.getRefundId()); | 206 | LOG.error("Failed to send rcb refund request: {}", request.getRefundId()); |
| 213 | throw new PaymentPipelineException(ErrorCode.SYSTEM_UNKNOWN_ERROR, "发送退款请求失败: " + result.statusCode); | 207 | throw new PaymentPipelineException(ErrorCode.SYSTEM_UNKNOWN_ERROR, "发送退款请求失败: " + result.statusCode); |
| 214 | } | 208 | } |
| 215 | - LOG.debug("Received from rcb online pipeline: {}\n{}", request.getRefundId(), result.responseText); | 209 | + LOG.debug("Rcb payment refund response received: {}\n{}", request.getRefundId(), result.responseText); |
| 216 | 210 | ||
| 217 | Map<String, String> data = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {}); | 211 | Map<String, String> data = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {}); |
| 218 | String resultCode = data.get("resultCode"); | 212 | String resultCode = data.get("resultCode"); |
| @@ -252,7 +246,7 @@ public class RcbOnlineHttpClient extends ServiceEndpointSupport { | @@ -252,7 +246,7 @@ public class RcbOnlineHttpClient extends ServiceEndpointSupport { | ||
| 252 | LOG.error("Failed to get rcb batch no, statusCode: {}", result.statusCode); | 246 | LOG.error("Failed to get rcb batch no, statusCode: {}", result.statusCode); |
| 253 | throw new PaymentPipelineException(ErrorCode.SYSTEM_UNKNOWN_ERROR, "获取签到批次号: " + result.statusCode); | 247 | throw new PaymentPipelineException(ErrorCode.SYSTEM_UNKNOWN_ERROR, "获取签到批次号: " + result.statusCode); |
| 254 | } | 248 | } |
| 255 | - LOG.debug("Received from rcb online pipeline: {}", result.responseText); | 249 | + LOG.debug("Rcb signIn response received: {}", result.responseText); |
| 256 | 250 | ||
| 257 | Map<String, String> data = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {}); | 251 | Map<String, String> data = JsonUtils.fromJsonString(result.responseText, new TypeReference<>() {}); |
| 258 | String resultCode = data.get("resultCode"); | 252 | String resultCode = data.get("resultCode"); |
| @@ -262,13 +256,13 @@ public class RcbOnlineHttpClient extends ServiceEndpointSupport { | @@ -262,13 +256,13 @@ public class RcbOnlineHttpClient extends ServiceEndpointSupport { | ||
| 262 | stringRedisTemplate.opsForValue().set(key, batchNo, 36 * 60 * 60, TimeUnit.SECONDS); | 256 | stringRedisTemplate.opsForValue().set(key, batchNo, 36 * 60 * 60, TimeUnit.SECONDS); |
| 263 | return batchNo; | 257 | return batchNo; |
| 264 | } else { | 258 | } else { |
| 265 | - LOG.error("Failed to rcb sign in, errorCode: {}, resultMessage: {}", resultCode, resultMessage); | ||
| 266 | - throw new PaymentPipelineException(ErrorCode.SERVICE_ACCESS_ERROR, "签到接口调用失败"); | 259 | + LOG.error("Failed to rcb signIn: {}", result.responseText); |
| 260 | + throw new PaymentPipelineException(ErrorCode.SERVICE_ACCESS_ERROR, "签到接口调用失败: " + resultMessage); | ||
| 267 | } | 261 | } |
| 268 | } catch (ServiceAccessException | PaymentPipelineException rex) { | 262 | } catch (ServiceAccessException | PaymentPipelineException rex) { |
| 269 | throw rex; | 263 | throw rex; |
| 270 | } catch (Exception ex) { | 264 | } catch (Exception ex) { |
| 271 | - LOG.error("Failed to get rcb sign in batchNo", ex); | 265 | + LOG.error("Failed to rcb signIn", ex); |
| 272 | throw new PaymentPipelineException(ErrorCode.SERVICE_ACCESS_ERROR, "获取签到批次号失败"); | 266 | throw new PaymentPipelineException(ErrorCode.SERVICE_ACCESS_ERROR, "获取签到批次号失败"); |
| 273 | } | 267 | } |
| 274 | } | 268 | } |
| @@ -326,57 +320,4 @@ public class RcbOnlineHttpClient extends ServiceEndpointSupport { | @@ -326,57 +320,4 @@ public class RcbOnlineHttpClient extends ServiceEndpointSupport { | ||
| 326 | } | 320 | } |
| 327 | return Optional.ofNullable(sslContext); | 321 | return Optional.ofNullable(sslContext); |
| 328 | } | 322 | } |
| 329 | - | ||
| 330 | - private static class AuthorizationSession { | ||
| 331 | - // 用户唯一标识 | ||
| 332 | - private String openid; | ||
| 333 | - // 会话密钥 | ||
| 334 | - private String session_key; | ||
| 335 | - // 用户在开放平台的唯一标识 | ||
| 336 | - private String unionid; | ||
| 337 | - // 错误码 | ||
| 338 | - private Integer errcode; | ||
| 339 | - // 错误信息 | ||
| 340 | - private String errmsg; | ||
| 341 | - | ||
| 342 | - public String getOpenid() { | ||
| 343 | - return openid; | ||
| 344 | - } | ||
| 345 | - | ||
| 346 | - public void setOpenid(String openid) { | ||
| 347 | - this.openid = openid; | ||
| 348 | - } | ||
| 349 | - | ||
| 350 | - public String getSession_key() { | ||
| 351 | - return session_key; | ||
| 352 | - } | ||
| 353 | - | ||
| 354 | - public void setSession_key(String session_key) { | ||
| 355 | - this.session_key = session_key; | ||
| 356 | - } | ||
| 357 | - | ||
| 358 | - public String getUnionid() { | ||
| 359 | - return unionid; | ||
| 360 | - } | ||
| 361 | - | ||
| 362 | - public void setUnionid(String unionid) { | ||
| 363 | - this.unionid = unionid; | ||
| 364 | - } | ||
| 365 | - | ||
| 366 | - public Integer getErrcode() { | ||
| 367 | - return errcode; | ||
| 368 | - } | ||
| 369 | - | ||
| 370 | - public void setErrcode(Integer errcode) { | ||
| 371 | - this.errcode = errcode; | ||
| 372 | - } | ||
| 373 | - | ||
| 374 | - public String getErrmsg() { | ||
| 375 | - return errmsg; | ||
| 376 | - } | ||
| 377 | - | ||
| 378 | - public void setErrmsg(String errmsg) { | ||
| 379 | - this.errmsg = errmsg; | ||
| 380 | - } | ||
| 381 | - } | ||
| 382 | } | 323 | } |
cashier-pipeline/src/main/java/com/diligrp/cashier/pipeline/core/DefaultTimeStrategy.java
| @@ -7,10 +7,10 @@ public class DefaultTimeStrategy implements ScanTimeStrategy { | @@ -7,10 +7,10 @@ public class DefaultTimeStrategy implements ScanTimeStrategy { | ||
| 7 | private final long[] prepayTimeArray = { 10 * ONE_MINUTE }; | 7 | private final long[] prepayTimeArray = { 10 * ONE_MINUTE }; |
| 8 | 8 | ||
| 9 | // 直接支付订单扫描时间策略 | 9 | // 直接支付订单扫描时间策略 |
| 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}; | 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 final long[] refundTimeArray = { 10 * ONE_MINUTE }; | 13 | + private final long[] refundTimeArray = { ONE_MINUTE, 2 * ONE_MINUTE, 2 * ONE_MINUTE, 5 * ONE_MINUTE }; |
| 14 | 14 | ||
| 15 | @Override | 15 | @Override |
| 16 | public long nextPrepayScanTime(int times) { | 16 | public long nextPrepayScanTime(int times) { |
cashier-shared/src/main/java/com/diligrp/cashier/shared/service/ThreadPoolService.java
| 1 | package com.diligrp.cashier.shared.service; | 1 | package com.diligrp.cashier.shared.service; |
| 2 | 2 | ||
| 3 | -import java.util.concurrent.ExecutorService; | ||
| 4 | -import java.util.concurrent.LinkedBlockingQueue; | ||
| 5 | -import java.util.concurrent.ThreadPoolExecutor; | ||
| 6 | -import java.util.concurrent.TimeUnit; | 3 | +import java.util.concurrent.*; |
| 7 | 4 | ||
| 8 | /** | 5 | /** |
| 9 | * 请谨慎使用此线程池工具类,通常建议根据特定的使用场景设置线程池参数,不建议使用统一的线程池配置 | 6 | * 请谨慎使用此线程池工具类,通常建议根据特定的使用场景设置线程池参数,不建议使用统一的线程池配置 |
| 10 | - * JDK的线程池类并不能很好区分"计算密集型"和"IO密集型"任务类型,并根据不同的任务类型去配置不同的参数 | 7 | + * JDK的线程池类并不能很好区分"计算密集型"和"IO密集型"任务类型,应该根据不同的任务类型去配置不同的参数 |
| 11 | */ | 8 | */ |
| 12 | public final class ThreadPoolService { | 9 | public final class ThreadPoolService { |
| 13 | 10 | ||
| @@ -15,7 +12,7 @@ public final class ThreadPoolService { | @@ -15,7 +12,7 @@ public final class ThreadPoolService { | ||
| 15 | 12 | ||
| 16 | private static final int CPU_MAX_POOL_SIZE = 100; | 13 | private static final int CPU_MAX_POOL_SIZE = 100; |
| 17 | 14 | ||
| 18 | - private static final int IO_MAX_POOL_SIZE = 1000; | 15 | +// private static final int IO_MAX_POOL_SIZE = 1000; |
| 19 | 16 | ||
| 20 | // CPU运算密集型任务的线程池实例 | 17 | // CPU运算密集型任务的线程池实例 |
| 21 | private static volatile ExecutorService cpuThreadPoll; | 18 | private static volatile ExecutorService cpuThreadPoll; |
| @@ -32,11 +29,11 @@ public final class ThreadPoolService { | @@ -32,11 +29,11 @@ public final class ThreadPoolService { | ||
| 32 | */ | 29 | */ |
| 33 | public static ExecutorService getCpuThreadPoll() { | 30 | public static ExecutorService getCpuThreadPoll() { |
| 34 | if (cpuThreadPoll == null) { | 31 | if (cpuThreadPoll == null) { |
| 32 | + | ||
| 35 | synchronized (ThreadPoolService.class) { | 33 | synchronized (ThreadPoolService.class) { |
| 36 | if (cpuThreadPoll == null) { | 34 | if (cpuThreadPoll == null) { |
| 37 | - cpuThreadPoll = new ThreadPoolExecutor(CPU_CORE_NUM + 1, CPU_MAX_POOL_SIZE, | ||
| 38 | - 20, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100), | ||
| 39 | - new ThreadPoolExecutor.AbortPolicy()); | 35 | + cpuThreadPoll = new ThreadPoolExecutor(CPU_CORE_NUM + 1, CPU_MAX_POOL_SIZE, 20, |
| 36 | + TimeUnit.SECONDS, new LinkedBlockingQueue<>(100), new LazyRejectedExecutionHandler()); | ||
| 40 | } | 37 | } |
| 41 | } | 38 | } |
| 42 | } | 39 | } |
| @@ -51,12 +48,29 @@ public final class ThreadPoolService { | @@ -51,12 +48,29 @@ public final class ThreadPoolService { | ||
| 51 | if (ioThreadPoll == null) { | 48 | if (ioThreadPoll == null) { |
| 52 | synchronized (ThreadPoolService.class) { | 49 | synchronized (ThreadPoolService.class) { |
| 53 | if (ioThreadPoll == null) { | 50 | if (ioThreadPoll == null) { |
| 54 | - ioThreadPoll = new ThreadPoolExecutor(CPU_CORE_NUM + 1, IO_MAX_POOL_SIZE, | ||
| 55 | - 20, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1000), | ||
| 56 | - new ThreadPoolExecutor.AbortPolicy()); | 51 | + ioThreadPoll = Executors.newVirtualThreadPerTaskExecutor(); |
| 52 | + | ||
| 53 | +// ioThreadPoll = new ThreadPoolExecutor(CPU_CORE_NUM + 1, IO_MAX_POOL_SIZE, 20, | ||
| 54 | +// TimeUnit.SECONDS, new LinkedBlockingQueue<>(1000), new LazyRejectedExecutionHandler()); | ||
| 57 | } | 55 | } |
| 58 | } | 56 | } |
| 59 | } | 57 | } |
| 60 | return ioThreadPoll; | 58 | return ioThreadPoll; |
| 61 | } | 59 | } |
| 60 | + | ||
| 61 | + private static class LazyRejectedExecutionHandler implements RejectedExecutionHandler { | ||
| 62 | + @Override | ||
| 63 | + public void rejectedExecution(Runnable task, ThreadPoolExecutor executor) { | ||
| 64 | + boolean success = false; | ||
| 65 | + try { | ||
| 66 | + success = executor.getQueue().offer(task, 15, TimeUnit.SECONDS); | ||
| 67 | + } catch (InterruptedException ex) { | ||
| 68 | + Thread.currentThread().interrupt(); | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + if (!success) { | ||
| 72 | + throw new RejectedExecutionException("task queue is full"); | ||
| 73 | + } | ||
| 74 | + } | ||
| 75 | + } | ||
| 62 | } | 76 | } |
cashier-trade/src/main/java/com/diligrp/cashier/trade/manager/PaymentResultManager.java
| @@ -86,7 +86,7 @@ public class PaymentResultManager { | @@ -86,7 +86,7 @@ public class PaymentResultManager { | ||
| 86 | try { | 86 | try { |
| 87 | listener.onEvent(refundEvent); | 87 | listener.onEvent(refundEvent); |
| 88 | } catch (Exception ex) { | 88 | } catch (Exception ex) { |
| 89 | - LOG.error("Failed to notify trade refund result", ex); | 89 | + LOG.error("Failed to notify payment refund result", ex); |
| 90 | } | 90 | } |
| 91 | } | 91 | } |
| 92 | } | 92 | } |
| @@ -95,13 +95,13 @@ public class PaymentResultManager { | @@ -95,13 +95,13 @@ public class PaymentResultManager { | ||
| 95 | ThreadPoolService.getIoThreadPoll().submit(() -> { | 95 | ThreadPoolService.getIoThreadPoll().submit(() -> { |
| 96 | try { | 96 | try { |
| 97 | String payload = JsonUtils.toJsonString(refundResult); | 97 | String payload = JsonUtils.toJsonString(refundResult); |
| 98 | - LOG.info("Notifying online trade refund result: {}", payload); | 98 | + LOG.info("Notifying online payment refund result: {}", payload); |
| 99 | ServiceEndpointSupport.HttpResult httpResult = new NotifyHttpClient(uri).send(payload); | 99 | ServiceEndpointSupport.HttpResult httpResult = new NotifyHttpClient(uri).send(payload); |
| 100 | if (httpResult.statusCode != 200) { | 100 | if (httpResult.statusCode != 200) { |
| 101 | - LOG.error("Failed to notify trade refund result"); | 101 | + LOG.error("Failed to notify payment refund result"); |
| 102 | } | 102 | } |
| 103 | } catch (Exception ex) { | 103 | } catch (Exception ex) { |
| 104 | - LOG.error("Failed to notify trade refund result", ex); | 104 | + LOG.error("Failed to notify payment refund result", ex); |
| 105 | } | 105 | } |
| 106 | }); | 106 | }); |
| 107 | } | 107 | } |
cashier-trade/src/main/java/com/diligrp/cashier/trade/manager/TaskMessageConsumer.java
| @@ -35,7 +35,7 @@ public class TaskMessageConsumer { | @@ -35,7 +35,7 @@ public class TaskMessageConsumer { | ||
| 35 | ? properties.getContentEncoding() : StandardCharsets.UTF_8.name(); | 35 | ? properties.getContentEncoding() : StandardCharsets.UTF_8.name(); |
| 36 | try { | 36 | try { |
| 37 | String body = new String(packet, charSet); | 37 | String body = new String(packet, charSet); |
| 38 | - LOG.info("Receiving async delay task message: {}", body); | 38 | + LOG.debug("Receiving async delay task message: {}", body); |
| 39 | TaskMessage task = TaskMessage.fromJson(body); | 39 | TaskMessage task = TaskMessage.fromJson(body); |
| 40 | int times = NumberUtils.str2Int(task.getParams(), Integer.MAX_VALUE); | 40 | int times = NumberUtils.str2Int(task.getParams(), Integer.MAX_VALUE); |
| 41 | if (task.getType() == TaskMessage.TYPE_CASHIER_ORDER_SCAN) { | 41 | if (task.getType() == TaskMessage.TYPE_CASHIER_ORDER_SCAN) { |
cashier-trade/src/main/java/com/diligrp/cashier/trade/manager/TaskMessageSender.java
| @@ -19,11 +19,6 @@ public class TaskMessageSender { | @@ -19,11 +19,6 @@ public class TaskMessageSender { | ||
| 19 | 19 | ||
| 20 | private static final Logger LOG = LoggerFactory.getLogger(TaskMessageSender.class); | 20 | private static final Logger LOG = LoggerFactory.getLogger(TaskMessageSender.class); |
| 21 | 21 | ||
| 22 | - private static final long ONE_MINUTE = 60 * 1000; | ||
| 23 | - | ||
| 24 | - private static final long TEN_MINUTES = 10 * ONE_MINUTE; | ||
| 25 | - | ||
| 26 | - private static final long ONE_SECOND = 1000; | ||
| 27 | 22 | ||
| 28 | @Resource | 23 | @Resource |
| 29 | private RabbitTemplate rabbitTemplate; | 24 | private RabbitTemplate rabbitTemplate; |
| @@ -33,7 +28,7 @@ public class TaskMessageSender { | @@ -33,7 +28,7 @@ public class TaskMessageSender { | ||
| 33 | */ | 28 | */ |
| 34 | public void sendDelayTaskMessage(TaskMessage task, long delayInMillis) { | 29 | public void sendDelayTaskMessage(TaskMessage task, long delayInMillis) { |
| 35 | if (delayInMillis < 0) { | 30 | if (delayInMillis < 0) { |
| 36 | - LOG.info("No need send scan order message: {}", task); | 31 | + LOG.debug("No need send scan order message: {}", task); |
| 37 | return; | 32 | return; |
| 38 | } | 33 | } |
| 39 | 34 | ||
| @@ -47,7 +42,7 @@ public class TaskMessageSender { | @@ -47,7 +42,7 @@ public class TaskMessageSender { | ||
| 47 | properties.setHeader("x-delay", String.valueOf(delayInMillis)); | 42 | properties.setHeader("x-delay", String.valueOf(delayInMillis)); |
| 48 | String payload = JsonUtils.toJsonString(task); | 43 | String payload = JsonUtils.toJsonString(task); |
| 49 | Message message = new Message(payload.getBytes(StandardCharsets.UTF_8), properties); | 44 | Message message = new Message(payload.getBytes(StandardCharsets.UTF_8), properties); |
| 50 | - LOG.info("Sending async delay task message: {}", task.getPayload()); | 45 | + LOG.debug("Sending async delay task message: {}", task.getPayload()); |
| 51 | rabbitTemplate.send(Constants.PAYMENT_DELAY_EXCHANGE, Constants.PAYMENT_DELAY_KEY, message); | 46 | rabbitTemplate.send(Constants.PAYMENT_DELAY_EXCHANGE, Constants.PAYMENT_DELAY_KEY, message); |
| 52 | } catch (Exception ex) { | 47 | } catch (Exception ex) { |
| 53 | LOG.error("Failed to send async delay task message: {}", task.getPayload(), ex); | 48 | LOG.error("Failed to send async delay task message: {}", task.getPayload(), ex); |
cashier-trade/src/main/java/com/diligrp/cashier/trade/service/impl/CashierAssistantServiceImpl.java
| @@ -10,7 +10,9 @@ import com.diligrp.cashier.pipeline.service.IPaymentPipelineManager; | @@ -10,7 +10,9 @@ import com.diligrp.cashier.pipeline.service.IPaymentPipelineManager; | ||
| 10 | import com.diligrp.cashier.pipeline.type.PaymentState; | 10 | import com.diligrp.cashier.pipeline.type.PaymentState; |
| 11 | import com.diligrp.cashier.trade.Constants; | 11 | import com.diligrp.cashier.trade.Constants; |
| 12 | import com.diligrp.cashier.trade.dao.IOnlinePaymentDao; | 12 | import com.diligrp.cashier.trade.dao.IOnlinePaymentDao; |
| 13 | +import com.diligrp.cashier.trade.domain.TaskMessage; | ||
| 13 | import com.diligrp.cashier.trade.domain.TradeStateDTO; | 14 | import com.diligrp.cashier.trade.domain.TradeStateDTO; |
| 15 | +import com.diligrp.cashier.trade.manager.TaskMessageSender; | ||
| 14 | import com.diligrp.cashier.trade.model.OnlinePayment; | 16 | import com.diligrp.cashier.trade.model.OnlinePayment; |
| 15 | import com.diligrp.cashier.trade.model.TradeOrder; | 17 | import com.diligrp.cashier.trade.model.TradeOrder; |
| 16 | import com.diligrp.cashier.trade.service.ICashierAssistantService; | 18 | import com.diligrp.cashier.trade.service.ICashierAssistantService; |
| @@ -45,11 +47,14 @@ public class CashierAssistantServiceImpl implements ICashierAssistantService { | @@ -45,11 +47,14 @@ public class CashierAssistantServiceImpl implements ICashierAssistantService { | ||
| 45 | private TradeAssistantServiceImpl tradeAssistantService; | 47 | private TradeAssistantServiceImpl tradeAssistantService; |
| 46 | 48 | ||
| 47 | @Resource | 49 | @Resource |
| 50 | + private TaskMessageSender taskMessageSender; | ||
| 51 | + | ||
| 52 | + @Resource | ||
| 48 | private RedissonClient redissonClient; | 53 | private RedissonClient redissonClient; |
| 49 | 54 | ||
| 50 | @Override | 55 | @Override |
| 51 | public void scanCashierTradeOrder(String tradeId, int times) { | 56 | public void scanCashierTradeOrder(String tradeId, int times) { |
| 52 | - LOG.debug("scanCashierTradeOrder{}: processing cashier trade order {}", times, tradeId); | 57 | + LOG.info("scanCashierTradeOrder{}: processing cashier order {}", times, tradeId); |
| 53 | String lockKey = String.format(Constants.TRADE_LOCK_REDIS_KEY, tradeId); | 58 | String lockKey = String.format(Constants.TRADE_LOCK_REDIS_KEY, tradeId); |
| 54 | RLock lock = redissonClient.getLock(lockKey); | 59 | RLock lock = redissonClient.getLock(lockKey); |
| 55 | try { | 60 | try { |
| @@ -64,12 +69,11 @@ public class CashierAssistantServiceImpl implements ICashierAssistantService { | @@ -64,12 +69,11 @@ public class CashierAssistantServiceImpl implements ICashierAssistantService { | ||
| 64 | // 在线支付通道才能关闭订单, 园区卡支付不支持 | 69 | // 在线支付通道才能关闭订单, 园区卡支付不支持 |
| 65 | if (pipeline instanceof OnlinePipeline<?> onlinePipeline) { | 70 | if (pipeline instanceof OnlinePipeline<?> onlinePipeline) { |
| 66 | OnlinePrepayOrder order = new OnlinePrepayOrder(payment.getPaymentId(), payment.getOutTradeNo()); | 71 | OnlinePrepayOrder order = new OnlinePrepayOrder(payment.getPaymentId(), payment.getOutTradeNo()); |
| 67 | - // 微信服务商模式,还需子商户 | ||
| 68 | OnlinePaymentResponse response = onlinePipeline.queryPrepayResponse(order); | 72 | OnlinePaymentResponse response = onlinePipeline.queryPrepayResponse(order); |
| 69 | if (!PaymentState.isFinished(response.getState().getCode())) { | 73 | if (!PaymentState.isFinished(response.getState().getCode())) { |
| 70 | try { | 74 | try { |
| 71 | onlinePipeline.closePrepayOrder(order); | 75 | onlinePipeline.closePrepayOrder(order); |
| 72 | - LOG.info("scanCashierTradeOrder: close online prepay order {}", payment.getPaymentId()); | 76 | + LOG.debug("scanCashierTradeOrder: close online prepay order {}", payment.getPaymentId()); |
| 73 | response = new OnlinePaymentResponse(response.getPaymentId(), response.getOutTradeNo(), | 77 | response = new OnlinePaymentResponse(response.getPaymentId(), response.getOutTradeNo(), |
| 74 | response.getOutPayType(), response.getPayerId(), response.getWhen(), | 78 | response.getOutPayType(), response.getPayerId(), response.getWhen(), |
| 75 | PaymentState.FAILED, "自动关闭超时的支付订单"); | 79 | PaymentState.FAILED, "自动关闭超时的支付订单"); |
| @@ -85,7 +89,9 @@ public class CashierAssistantServiceImpl implements ICashierAssistantService { | @@ -85,7 +89,9 @@ public class CashierAssistantServiceImpl implements ICashierAssistantService { | ||
| 85 | if (!TradeState.isFinished(trade.getState())) { | 89 | if (!TradeState.isFinished(trade.getState())) { |
| 86 | TradeStateDTO tradeStateDTO = TradeStateDTO.of(trade.getTradeId(), TradeState.CLOSED, trade.getVersion(), now); | 90 | TradeStateDTO tradeStateDTO = TradeStateDTO.of(trade.getTradeId(), TradeState.CLOSED, trade.getVersion(), now); |
| 87 | tradeAssistantService.proceedTradeOrder(tradeStateDTO); | 91 | tradeAssistantService.proceedTradeOrder(tradeStateDTO); |
| 88 | - LOG.info("scanCashierTradeOrder: close cashier trade order {}", tradeId); | 92 | + LOG.debug("scanCashierTradeOrder: close cashier order {}", tradeId); |
| 93 | + } else { | ||
| 94 | + LOG.debug("scanCashierTradeOrder: cashier order {} already accomplished", trade.getTradeId()); | ||
| 89 | } | 95 | } |
| 90 | } finally { | 96 | } finally { |
| 91 | if (lock.isHeldByCurrentThread()) { | 97 | if (lock.isHeldByCurrentThread()) { |
| @@ -96,10 +102,10 @@ public class CashierAssistantServiceImpl implements ICashierAssistantService { | @@ -96,10 +102,10 @@ public class CashierAssistantServiceImpl implements ICashierAssistantService { | ||
| 96 | 102 | ||
| 97 | @Override | 103 | @Override |
| 98 | public void scanCashierRefundOrder(String refundId, int times) { | 104 | public void scanCashierRefundOrder(String refundId, int times) { |
| 99 | - LOG.debug("scanCashierRefundOrder{}: processing online refund order {}", times, refundId); | 105 | + LOG.info("scanCashierRefundOrder{}: processing cashier refund order {}", times, refundId); |
| 100 | OnlinePayment refund = tradeAssistantService.findByRefundId(refundId); | 106 | OnlinePayment refund = tradeAssistantService.findByRefundId(refundId); |
| 101 | if (PaymentState.isFinished(refund.getState())) { | 107 | if (PaymentState.isFinished(refund.getState())) { |
| 102 | - LOG.debug("scanCashierRefundOrder{}: online refund order {} already accomplished", times, refundId); | 108 | + LOG.debug("scanCashierRefundOrder{}: cashier refund order {} already accomplished", times, refundId); |
| 103 | return; | 109 | return; |
| 104 | } | 110 | } |
| 105 | 111 | ||
| @@ -107,5 +113,10 @@ public class CashierAssistantServiceImpl implements ICashierAssistantService { | @@ -107,5 +113,10 @@ public class CashierAssistantServiceImpl implements ICashierAssistantService { | ||
| 107 | OnlineRefundOrder order = new OnlineRefundOrder(refundId, refund.getOutTradeNo()); | 113 | OnlineRefundOrder order = new OnlineRefundOrder(refundId, refund.getOutTradeNo()); |
| 108 | OnlineRefundResponse response = pipeline.queryRefundResponse(order); | 114 | OnlineRefundResponse response = pipeline.queryRefundResponse(order); |
| 109 | cashierPaymentService.notifyRefundResult(response); | 115 | cashierPaymentService.notifyRefundResult(response); |
| 116 | + if (!PaymentState.isFinished(response.getState().getCode())) { | ||
| 117 | + long delay = pipeline.getTimeStrategy().nextRefundScanTime(times + 1); | ||
| 118 | + TaskMessage message = new TaskMessage(TaskMessage.TYPE_CASHIER_REFUND_SCAN, refundId, String.valueOf(times + 1)); | ||
| 119 | + taskMessageSender.sendDelayTaskMessage(message, delay); | ||
| 120 | + } | ||
| 110 | } | 121 | } |
| 111 | } | 122 | } |
cashier-trade/src/main/java/com/diligrp/cashier/trade/service/impl/CashierPaymentServiceImpl.java
| @@ -5,6 +5,7 @@ import com.diligrp.cashier.assistant.service.impl.SnowflakeKeyManager; | @@ -5,6 +5,7 @@ import com.diligrp.cashier.assistant.service.impl.SnowflakeKeyManager; | ||
| 5 | import com.diligrp.cashier.pipeline.core.DiliCardPipeline; | 5 | import com.diligrp.cashier.pipeline.core.DiliCardPipeline; |
| 6 | import com.diligrp.cashier.pipeline.core.OnlinePipeline; | 6 | import com.diligrp.cashier.pipeline.core.OnlinePipeline; |
| 7 | import com.diligrp.cashier.pipeline.core.PaymentPipeline; | 7 | import com.diligrp.cashier.pipeline.core.PaymentPipeline; |
| 8 | +import com.diligrp.cashier.pipeline.core.ScanTimeStrategy; | ||
| 8 | import com.diligrp.cashier.pipeline.domain.*; | 9 | import com.diligrp.cashier.pipeline.domain.*; |
| 9 | import com.diligrp.cashier.pipeline.domain.card.CardPaymentRequest; | 10 | import com.diligrp.cashier.pipeline.domain.card.CardPaymentRequest; |
| 10 | import com.diligrp.cashier.pipeline.domain.card.CardPaymentResponse; | 11 | import com.diligrp.cashier.pipeline.domain.card.CardPaymentResponse; |
| @@ -104,19 +105,19 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | @@ -104,19 +105,19 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | ||
| 104 | /** | 105 | /** |
| 105 | * 收银台支付 | 106 | * 收银台支付 |
| 106 | * | 107 | * |
| 107 | - * @param cashierPayment - 支付信息 | 108 | + * @param payment - 支付信息 |
| 108 | * @return 支付状态 | 109 | * @return 支付状态 |
| 109 | */ | 110 | */ |
| 110 | @Override | 111 | @Override |
| 111 | @Transactional(rollbackFor = Exception.class) | 112 | @Transactional(rollbackFor = Exception.class) |
| 112 | - public OnlinePaymentStatus doPayment(CashierPayment cashierPayment) { | 113 | + public OnlinePaymentStatus doPayment(CashierPayment payment) { |
| 113 | // TODO: 接口防重复提交 | 114 | // TODO: 接口防重复提交 |
| 114 | - String lockKey = String.format(Constants.TRADE_LOCK_REDIS_KEY, cashierPayment.getTradeId()); | 115 | + String lockKey = String.format(Constants.TRADE_LOCK_REDIS_KEY, payment.getTradeId()); |
| 115 | RLock lock = redissonClient.getLock(lockKey); | 116 | RLock lock = redissonClient.getLock(lockKey); |
| 116 | try { | 117 | try { |
| 117 | boolean locked = lock.tryLock(Constants.TRADE_LOCK_TIMEOUT, TimeUnit.SECONDS); | 118 | boolean locked = lock.tryLock(Constants.TRADE_LOCK_TIMEOUT, TimeUnit.SECONDS); |
| 118 | if (locked) { | 119 | if (locked) { |
| 119 | - TradeOrder trade = tradeAssistantService.findByTradeId(cashierPayment.getTradeId()); | 120 | + TradeOrder trade = tradeAssistantService.findByTradeId(payment.getTradeId()); |
| 120 | CashierType cashierType = CashierType.getByCode(trade.getType()); | 121 | CashierType cashierType = CashierType.getByCode(trade.getType()); |
| 121 | if (TradeState.isFinished(trade.getState())) { | 122 | if (TradeState.isFinished(trade.getState())) { |
| 122 | throw new TradePaymentException(ErrorCode.OPERATION_NOT_ALLOWED, "不能进行支付, 交易订单已经完成"); | 123 | throw new TradePaymentException(ErrorCode.OPERATION_NOT_ALLOWED, "不能进行支付, 交易订单已经完成"); |
| @@ -125,6 +126,7 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | @@ -125,6 +126,7 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | ||
| 125 | if (cashierType != CashierType.MINIPRO) { | 126 | if (cashierType != CashierType.MINIPRO) { |
| 126 | throw new TradePaymentException(ErrorCode.OPERATION_NOT_ALLOWED, "系统当前不支持的此收银台类型"); | 127 | throw new TradePaymentException(ErrorCode.OPERATION_NOT_ALLOWED, "系统当前不支持的此收银台类型"); |
| 127 | } | 128 | } |
| 129 | + LOG.info("Requesting cashier order payment: {}", payment.getTradeId()); | ||
| 128 | // 关闭支付中的支付订单, 避免一个交易订单存在多笔支付订单, 造成重复支付 | 130 | // 关闭支付中的支付订单, 避免一个交易订单存在多笔支付订单, 造成重复支付 |
| 129 | if (!tradeAssistantService.resetTradeOrder(trade)) { | 131 | if (!tradeAssistantService.resetTradeOrder(trade)) { |
| 130 | throw new TradePaymentException(ErrorCode.OPERATION_NOT_ALLOWED, "不能进行支付, 交易订单正在支付中"); | 132 | throw new TradePaymentException(ErrorCode.OPERATION_NOT_ALLOWED, "不能进行支付, 交易订单正在支付中"); |
| @@ -132,26 +134,26 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | @@ -132,26 +134,26 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | ||
| 132 | 134 | ||
| 133 | LocalDateTime now = LocalDateTime.now(); | 135 | LocalDateTime now = LocalDateTime.now(); |
| 134 | // 获取支付通道 | 136 | // 获取支付通道 |
| 135 | - PaymentPipeline<?> pipeline = paymentPipelineManager.findPipelineById( | ||
| 136 | - cashierPayment.getPipelineId(), PaymentPipeline.class); | 137 | + PaymentPipeline<?> pipeline = paymentPipelineManager.findPipelineById(payment.getPipelineId(), PaymentPipeline.class); |
| 137 | String paymentId = snowflakeKeyManager.getKeyGenerator(SnowflakeKey.PAYMENT_ID).nextId(); | 138 | String paymentId = snowflakeKeyManager.getKeyGenerator(SnowflakeKey.PAYMENT_ID).nextId(); |
| 138 | if (pipeline instanceof OnlinePipeline<?> onlinePipeline) { // 在线支付通道 | 139 | if (pipeline instanceof OnlinePipeline<?> onlinePipeline) { // 在线支付通道 |
| 139 | // 在线支付通道: 不同的收银台类型使用不同的支付方式(目前只支持小程序收银台) | 140 | // 在线支付通道: 不同的收银台类型使用不同的支付方式(目前只支持小程序收银台) |
| 140 | // 小程序收银台将使用在线支付通道的小程序支付 | 141 | // 小程序收银台将使用在线支付通道的小程序支付 |
| 141 | - MiniProPrepayRequest request = new MiniProPaymentConverter(trade, paymentId, now).convert(cashierPayment); | 142 | + MiniProPrepayRequest request = new MiniProPaymentConverter(trade, paymentId, now).convert(payment); |
| 142 | MiniProPrepayResponse response = onlinePipeline.sendMiniProPrepayRequest(request); | 143 | MiniProPrepayResponse response = onlinePipeline.sendMiniProPrepayRequest(request); |
| 143 | String outMchId = request.getString(com.diligrp.cashier.pipeline.Constants.PARAM_MCH_ID); | 144 | String outMchId = request.getString(com.diligrp.cashier.pipeline.Constants.PARAM_MCH_ID); |
| 144 | - OnlinePayment payment = OnlinePayment.builder().outMchId(outMchId).tradeId(trade.getTradeId()) | 145 | + OnlinePayment onlinePayment = OnlinePayment.builder().outMchId(outMchId).tradeId(trade.getTradeId()) |
| 145 | .type(TradeType.TRADE).paymentId(paymentId).channelId(onlinePipeline.supportedChannel()) | 146 | .type(TradeType.TRADE).paymentId(paymentId).channelId(onlinePipeline.supportedChannel()) |
| 146 | .payType(PaymentType.MINI_PRO).pipelineId(onlinePipeline.pipelineId()).goods(trade.getGoods()) | 147 | .payType(PaymentType.MINI_PRO).pipelineId(onlinePipeline.pipelineId()).goods(trade.getGoods()) |
| 147 | .amount(trade.getAmount()).payerId(request.getOpenId()).outTradeNo(response.getOutTradeNo()) | 148 | .amount(trade.getAmount()).payerId(request.getOpenId()).outTradeNo(response.getOutTradeNo()) |
| 148 | .outPayType(OutPaymentType.NOP).finishTime(null).state(response.getState()) | 149 | .outPayType(OutPaymentType.NOP).finishTime(null).state(response.getState()) |
| 149 | .notifyUrl(trade.getNotifyUrl()).description(null).version(0).createdTime(now).modifiedTime(now).build(); | 150 | .notifyUrl(trade.getNotifyUrl()).description(null).version(0).createdTime(now).modifiedTime(now).build(); |
| 150 | - onlinePaymentDao.insertOnlinePayment(payment); | 151 | + onlinePaymentDao.insertOnlinePayment(onlinePayment); |
| 152 | + LOG.debug("Cashier order payment result: {}:{}", response.getPaymentId(), response.getState().name()); | ||
| 151 | return response; | 153 | return response; |
| 152 | } else if (pipeline instanceof DiliCardPipeline cardPipeline) { // 园区卡支付通道 | 154 | } else if (pipeline instanceof DiliCardPipeline cardPipeline) { // 园区卡支付通道 |
| 153 | // 园区卡支付通道: 所有的收银台类型使用的是同一种园区卡支付流程 | 155 | // 园区卡支付通道: 所有的收银台类型使用的是同一种园区卡支付流程 |
| 154 | - CardPaymentRequest request = new CardPaymentConverter(trade, paymentId, now).convert(cashierPayment); | 156 | + CardPaymentRequest request = new CardPaymentConverter(trade, paymentId, now).convert(payment); |
| 155 | // 园区卡支付需要订单来源 | 157 | // 园区卡支付需要订单来源 |
| 156 | request.attach("source", SourceType.getIfNonNull(trade.getSource())); | 158 | request.attach("source", SourceType.getIfNonNull(trade.getSource())); |
| 157 | // 修改支付状态为支付中,防止重复支付 | 159 | // 修改支付状态为支付中,防止重复支付 |
| @@ -160,14 +162,14 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | @@ -160,14 +162,14 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | ||
| 160 | if (response.getState() == PaymentState.SUCCESS) { | 162 | if (response.getState() == PaymentState.SUCCESS) { |
| 161 | // 园区卡支付通道outMchId为市场ID | 163 | // 园区卡支付通道outMchId为市场ID |
| 162 | String outMchId = request.getString(com.diligrp.cashier.pipeline.Constants.PARAM_MCH_ID); | 164 | String outMchId = request.getString(com.diligrp.cashier.pipeline.Constants.PARAM_MCH_ID); |
| 163 | - OnlinePayment payment = OnlinePayment.builder().outMchId(outMchId).tradeId(trade.getTradeId()) | 165 | + OnlinePayment onlinePayment = OnlinePayment.builder().outMchId(outMchId).tradeId(trade.getTradeId()) |
| 164 | .type(TradeType.TRADE).paymentId(paymentId).channelId(cardPipeline.supportedChannel()) | 166 | .type(TradeType.TRADE).paymentId(paymentId).channelId(cardPipeline.supportedChannel()) |
| 165 | .payType(PaymentType.DIRECT).pipelineId(cardPipeline.pipelineId()).goods(trade.getGoods()) | 167 | .payType(PaymentType.DIRECT).pipelineId(cardPipeline.pipelineId()).goods(trade.getGoods()) |
| 166 | .amount(trade.getAmount()).payerId(response.getPayerId()).outTradeNo(response.getOutTradeNo()) | 168 | .amount(trade.getAmount()).payerId(response.getPayerId()).outTradeNo(response.getOutTradeNo()) |
| 167 | .outPayType(response.getOutPayType()).finishTime(response.getWhen()).state(response.getState()) | 169 | .outPayType(response.getOutPayType()).finishTime(response.getWhen()).state(response.getState()) |
| 168 | .notifyUrl(trade.getNotifyUrl()).description(response.getMessage()).version(0) | 170 | .notifyUrl(trade.getNotifyUrl()).description(response.getMessage()).version(0) |
| 169 | .createdTime(now).modifiedTime(now).build(); | 171 | .createdTime(now).modifiedTime(now).build(); |
| 170 | - onlinePaymentDao.insertOnlinePayment(payment); | 172 | + onlinePaymentDao.insertOnlinePayment(onlinePayment); |
| 171 | 173 | ||
| 172 | TradeStateDTO tradeStateDTO = TradeStateDTO.of(trade.getTradeId(), TradeState.SUCCESS, | 174 | TradeStateDTO tradeStateDTO = TradeStateDTO.of(trade.getTradeId(), TradeState.SUCCESS, |
| 173 | trade.getVersion(), now); | 175 | trade.getVersion(), now); |
| @@ -178,6 +180,7 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | @@ -178,6 +180,7 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | ||
| 178 | response.getPayerId(), response.getWhen(), response.getMessage()); | 180 | response.getPayerId(), response.getWhen(), response.getMessage()); |
| 179 | paymentResultManager.notifyPaymentResult(trade.getNotifyUrl(), paymentResult, 500); | 181 | paymentResultManager.notifyPaymentResult(trade.getNotifyUrl(), paymentResult, 500); |
| 180 | } | 182 | } |
| 183 | + LOG.debug("Cashier order payment result: {}:{}", response.getPaymentId(), response.getState().name()); | ||
| 181 | return response; | 184 | return response; |
| 182 | } else { | 185 | } else { |
| 183 | // 目前只有两类支付通道: CardPipeline和OnlinePipeline, 程序逻辑不应该到达此代码块 | 186 | // 目前只有两类支付通道: CardPipeline和OnlinePipeline, 程序逻辑不应该到达此代码块 |
| @@ -205,10 +208,10 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | @@ -205,10 +208,10 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | ||
| 205 | public void notifyPaymentResponse(OnlinePaymentResponse response) { | 208 | public void notifyPaymentResponse(OnlinePaymentResponse response) { |
| 206 | OnlinePayment payment = tradeAssistantService.findByPaymentId(response.getPaymentId()); | 209 | OnlinePayment payment = tradeAssistantService.findByPaymentId(response.getPaymentId()); |
| 207 | if (PaymentState.isFinished(payment.getState())) { | 210 | if (PaymentState.isFinished(payment.getState())) { |
| 208 | - LOG.warn("Duplicate process payment response: [{}:{}]", payment.getPaymentId(), response.getState()); | 211 | + LOG.warn("Duplicate process cashier payment response: [{}:{}]", payment.getPaymentId(), response.getState().name()); |
| 209 | return; | 212 | return; |
| 210 | } | 213 | } |
| 211 | - LOG.info("Processing payment response: [{},{}]", payment.getPaymentId(), response.getState()); | 214 | + LOG.info("Processing cashier payment response: [{},{}]", payment.getPaymentId(), response.getState().name()); |
| 212 | 215 | ||
| 213 | if (PaymentState.isFinished(response.getState().getCode())) { | 216 | if (PaymentState.isFinished(response.getState().getCode())) { |
| 214 | LocalDateTime now = LocalDateTime.now(); | 217 | LocalDateTime now = LocalDateTime.now(); |
| @@ -261,6 +264,7 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | @@ -261,6 +264,7 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | ||
| 261 | throw new TradePaymentException(ErrorCode.OPERATION_NOT_ALLOWED, "关闭交易订单失败: 无效的订单状态"); | 264 | throw new TradePaymentException(ErrorCode.OPERATION_NOT_ALLOWED, "关闭交易订单失败: 无效的订单状态"); |
| 262 | } | 265 | } |
| 263 | 266 | ||
| 267 | + LOG.info("Requesting close cashier trade order: {}", tradeId); | ||
| 264 | LocalDateTime now = LocalDateTime.now(); | 268 | LocalDateTime now = LocalDateTime.now(); |
| 265 | // 获取所有支付记录 | 269 | // 获取所有支付记录 |
| 266 | List<OnlinePayment> onlinePayments = onlinePaymentDao.listOnlinePayments(trade.getTradeId(), | 270 | List<OnlinePayment> onlinePayments = onlinePaymentDao.listOnlinePayments(trade.getTradeId(), |
| @@ -326,6 +330,7 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | @@ -326,6 +330,7 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | ||
| 326 | TradeType.TRADE.getCode(), PaymentState.SUCCESS.getCode()).stream().findFirst() | 330 | TradeType.TRADE.getCode(), PaymentState.SUCCESS.getCode()).stream().findFirst() |
| 327 | .orElseThrow(() -> new TradePaymentException(ErrorCode.OPERATION_NOT_ALLOWED, "不能进行交易退款: 无支付信息")); | 331 | .orElseThrow(() -> new TradePaymentException(ErrorCode.OPERATION_NOT_ALLOWED, "不能进行交易退款: 无支付信息")); |
| 328 | 332 | ||
| 333 | + LOG.info("Requesting cashier payment refund: {}", request.getTradeId()); | ||
| 329 | LocalDateTime now = LocalDateTime.now().withNano(0); | 334 | LocalDateTime now = LocalDateTime.now().withNano(0); |
| 330 | KeyGenerator refundIdKey = snowflakeKeyManager.getKeyGenerator(SnowflakeKey.PAYMENT_ID); | 335 | KeyGenerator refundIdKey = snowflakeKeyManager.getKeyGenerator(SnowflakeKey.PAYMENT_ID); |
| 331 | String refundId = refundIdKey.nextId(); | 336 | String refundId = refundIdKey.nextId(); |
| @@ -341,6 +346,7 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | @@ -341,6 +346,7 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | ||
| 341 | throw new TradePaymentException(ErrorCode.OPERATION_NOT_ALLOWED, "不支持的支付通道"); | 346 | throw new TradePaymentException(ErrorCode.OPERATION_NOT_ALLOWED, "不支持的支付通道"); |
| 342 | } | 347 | } |
| 343 | 348 | ||
| 349 | + LOG.debug("Cashier payment refund result: [{}:{}]", trade.getTradeId(), response.getState().name()); | ||
| 344 | OnlinePayment refund = OnlinePayment.builder().outMchId(payment.getOutMchId()).tradeId(payment.getTradeId()) | 350 | OnlinePayment refund = OnlinePayment.builder().outMchId(payment.getOutMchId()).tradeId(payment.getTradeId()) |
| 345 | .type(TradeType.REFUND).paymentId(refundId).channelId(payment.getChannelId()) | 351 | .type(TradeType.REFUND).paymentId(refundId).channelId(payment.getChannelId()) |
| 346 | .payType(payment.getPayType()).pipelineId(payment.getPipelineId()).goods(payment.getGoods() + "-退款") | 352 | .payType(payment.getPayType()).pipelineId(payment.getPipelineId()).goods(payment.getGoods() + "-退款") |
| @@ -356,8 +362,11 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | @@ -356,8 +362,11 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | ||
| 356 | tradeAssistantService.proceedTradeOrder(tradeState); | 362 | tradeAssistantService.proceedTradeOrder(tradeState); |
| 357 | } else if (!PaymentState.isFinished(response.getState().getCode())) { | 363 | } else if (!PaymentState.isFinished(response.getState().getCode())) { |
| 358 | // 固定周期后,查询退款状态,根据状态完成退款订单 | 364 | // 固定周期后,查询退款状态,根据状态完成退款订单 |
| 359 | - TaskMessage message = new TaskMessage(TaskMessage.TYPE_CASHIER_REFUND_SCAN, refundId, "1"); | ||
| 360 | - taskMessageSender.sendDelayTaskMessage(message, trade.getTimeout() * 1000); | 365 | + if (pipeline instanceof OnlinePipeline<?> onlinePipeline) { // 只有在线支付通道允许查询退款状态 |
| 366 | + long delay = onlinePipeline.getTimeStrategy().nextRefundScanTime(1); | ||
| 367 | + TaskMessage message = new TaskMessage(TaskMessage.TYPE_CASHIER_REFUND_SCAN, refundId, "1"); | ||
| 368 | + taskMessageSender.sendDelayTaskMessage(message, delay); | ||
| 369 | + } | ||
| 361 | } | 370 | } |
| 362 | 371 | ||
| 363 | return new OnlineRefundResult(refundId, payment.getPaymentId(), response.getState().getCode(), | 372 | return new OnlineRefundResult(refundId, payment.getPaymentId(), response.getState().getCode(), |
| @@ -369,14 +378,14 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | @@ -369,14 +378,14 @@ public class CashierPaymentServiceImpl implements ICashierPaymentService { | ||
| 369 | public void notifyRefundResult(OnlineRefundResponse response) { | 378 | public void notifyRefundResult(OnlineRefundResponse response) { |
| 370 | OnlinePayment refund = tradeAssistantService.findByRefundId(response.getRefundId()); | 379 | OnlinePayment refund = tradeAssistantService.findByRefundId(response.getRefundId()); |
| 371 | if (PaymentState.isFinished(refund.getState())) { | 380 | if (PaymentState.isFinished(refund.getState())) { |
| 372 | - LOG.warn("Duplicate process online refund order[{}:{}]", response.getRefundId(), response.getState()); | 381 | + LOG.warn("Duplicate process cashier refund response: [{}:{}]", response.getRefundId(), response.getState().name()); |
| 373 | return; | 382 | return; |
| 374 | } | 383 | } |
| 375 | if (!PaymentState.isFinished(response.getState().getCode())) { | 384 | if (!PaymentState.isFinished(response.getState().getCode())) { |
| 376 | - LOG.warn("Ignore online refund order[{}:{}]", response.getRefundId(), response.getState()); | 385 | + LOG.warn("Ignore cashier refund response: [{}:{}]", response.getRefundId(), response.getState().name()); |
| 377 | return; | 386 | return; |
| 378 | } | 387 | } |
| 379 | - LOG.info("Processing online refund order[{}:{}]", response.getRefundId(), response.getState()); | 388 | + LOG.info("Processing cashier refund response: [{}:{}]", response.getRefundId(), response.getState().name()); |
| 380 | 389 | ||
| 381 | LocalDateTime now = LocalDateTime.now(); | 390 | LocalDateTime now = LocalDateTime.now(); |
| 382 | TradeOrder trade = tradeAssistantService.findByTradeId(refund.getTradeId()); | 391 | TradeOrder trade = tradeAssistantService.findByTradeId(refund.getTradeId()); |
cashier-trade/src/main/java/com/diligrp/cashier/trade/service/impl/TradeAssistantServiceImpl.java
| @@ -65,7 +65,7 @@ public class TradeAssistantServiceImpl implements ITradeAssistantService { | @@ -65,7 +65,7 @@ public class TradeAssistantServiceImpl implements ITradeAssistantService { | ||
| 65 | List<OnlinePayment> onlinePayments = onlinePaymentDao.listOnlinePayments(trade.getTradeId(), TradeType.TRADE.getCode(), null); | 65 | List<OnlinePayment> onlinePayments = onlinePaymentDao.listOnlinePayments(trade.getTradeId(), TradeType.TRADE.getCode(), null); |
| 66 | for (OnlinePayment payment : onlinePayments) { | 66 | for (OnlinePayment payment : onlinePayments) { |
| 67 | if (!PaymentState.isFinished(payment.getState())) { | 67 | if (!PaymentState.isFinished(payment.getState())) { |
| 68 | - LOG.info("Trying to close payment order in process: {}", payment.getPaymentId()); | 68 | + LOG.debug("Trying to close payment order in process: {}", payment.getPaymentId()); |
| 69 | PaymentPipeline<?> pipeline = paymentPipelineManager.findPipelineById(payment.getPipelineId(), PaymentPipeline.class); | 69 | PaymentPipeline<?> pipeline = paymentPipelineManager.findPipelineById(payment.getPipelineId(), PaymentPipeline.class); |
| 70 | if (pipeline instanceof OnlinePipeline<?> onlinePipeline) { | 70 | if (pipeline instanceof OnlinePipeline<?> onlinePipeline) { |
| 71 | // 理论上只存在一条支付中的支付记录,否则后面的支付通道关闭失败时,会回滚前面支付记录的状态修改 | 71 | // 理论上只存在一条支付中的支付记录,否则后面的支付通道关闭失败时,会回滚前面支付记录的状态修改 |