OrderPayService.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. package com.izouma.nineth.service;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.izouma.nineth.config.Constants;
  4. import com.izouma.nineth.config.GeneralProperties;
  5. import com.izouma.nineth.domain.*;
  6. import com.izouma.nineth.dto.PayQuery;
  7. import com.izouma.nineth.dto.UserBankCard;
  8. import com.izouma.nineth.enums.MintOrderStatus;
  9. import com.izouma.nineth.enums.OrderStatus;
  10. import com.izouma.nineth.enums.PayMethod;
  11. import com.izouma.nineth.event.OrderNotifyEvent;
  12. import com.izouma.nineth.exception.BusinessException;
  13. import com.izouma.nineth.repo.*;
  14. import com.izouma.nineth.utils.SnowflakeIdWorker;
  15. import lombok.AllArgsConstructor;
  16. import lombok.extern.slf4j.Slf4j;
  17. import org.apache.commons.lang3.StringUtils;
  18. import org.apache.rocketmq.spring.core.RocketMQTemplate;
  19. import org.springframework.cache.annotation.Cacheable;
  20. import org.springframework.security.crypto.password.PasswordEncoder;
  21. import org.springframework.stereotype.Service;
  22. import java.math.BigDecimal;
  23. import java.time.LocalDateTime;
  24. import java.util.Map;
  25. import java.util.Objects;
  26. import java.util.Optional;
  27. import java.util.stream.Stream;
  28. @Service
  29. @Slf4j
  30. @AllArgsConstructor
  31. public class OrderPayService {
  32. private static String PAY_CHANNEL = Constants.PayChannel.SAND;
  33. private final OrderService orderService;
  34. private final OrderRepo orderRepo;
  35. private final MintOrderRepo mintOrderRepo;
  36. private final GiftOrderRepo giftOrderRepo;
  37. private final SandPayService sandPayService;
  38. private final HMPayService hmPayService;
  39. private final GeneralProperties generalProperties;
  40. private final UserBalanceService userBalanceService;
  41. private final RocketMQTemplate rocketMQTemplate;
  42. private final GiftOrderService giftOrderService;
  43. private final MintOrderService mintOrderService;
  44. private final UserRepo userRepo;
  45. private final SnowflakeIdWorker snowflakeIdWorker;
  46. private final RechargeOrderRepo rechargeOrderRepo;
  47. private final SysConfigService sysConfigService;
  48. private final PasswordEncoder passwordEncoder;
  49. private final PayEaseService payEaseService;
  50. private final UserBankCardRepo userBankCardRepo;
  51. public static void setPayChannel(String payChannel) {
  52. log.info("set pay channel {}", payChannel);
  53. if (Constants.PayChannel.HM.equals(payChannel) || Constants.PayChannel.SAND.equals(payChannel)) {
  54. PAY_CHANNEL = payChannel;
  55. }
  56. }
  57. @Cacheable(value = "payOrder", key = "'order#'+#orderId")
  58. public String payOrder(Long orderId) {
  59. Order order = orderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
  60. if (order.getStatus() != OrderStatus.NOT_PAID) {
  61. throw new BusinessException("订单状态错误");
  62. }
  63. switch (PAY_CHANNEL) {
  64. case Constants.PayChannel.SAND:
  65. return sandPayService.pay(orderId + "", order.getName(), order.getTotalPrice(),
  66. order.getCreatedAt().plusMinutes(3), "order");
  67. case Constants.PayChannel.HM:
  68. return hmPayService.requestAlipay(orderId + "", order.getTotalPrice(), order.getName(),
  69. HMPayService.getTimeout(order.getCreatedAt(), 180), Constants.OrderNotifyType.ORDER,
  70. generalProperties.getHost() + "/9th/orderDetail?id=" + orderId);
  71. }
  72. throw new BusinessException(Constants.PAY_ERR_MSG);
  73. }
  74. @Cacheable(value = "payOrder", key = "'order#'+#orderId")
  75. public String payOrderQuick(Long orderId) {
  76. Order order = orderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
  77. if (order.getStatus() != OrderStatus.NOT_PAID) {
  78. throw new BusinessException("订单状态错误");
  79. }
  80. return sandPayService.payQuick(orderId + "", order.getName(), order.getTotalPrice(),
  81. order.getCreatedAt().plusMinutes(3), Constants.OrderNotifyType.ORDER,
  82. generalProperties.getHost() + "/9th/home");
  83. }
  84. public void payOrderBalance(Long orderId, Long userId, String tradeCode) {
  85. Order order = orderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
  86. if (order.getStatus() != OrderStatus.NOT_PAID) {
  87. throw new BusinessException("订单状态错误");
  88. }
  89. checkTradeCode(userId, tradeCode, order.getUserId());
  90. BalanceRecord record = userBalanceService.balancePay(order.getUserId(), order.getTotalPrice(), orderId, order.getName());
  91. rocketMQTemplate.syncSend(generalProperties.getOrderNotifyTopic(),
  92. new OrderNotifyEvent(orderId, PayMethod.BALANCE, record.getId().toString(),
  93. System.currentTimeMillis()));
  94. }
  95. @Cacheable(value = "payOrder", key = "'order#'+#orderId")
  96. public Map<String, Object> payOrderAgreement(Long orderId, String bindCardId) {
  97. Order order = orderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
  98. if (order.getStatus() != OrderStatus.NOT_PAID) {
  99. throw new BusinessException("订单状态错误");
  100. }
  101. if (StringUtils.isEmpty(bindCardId)) {
  102. bindCardId = userBankCardRepo.findByUserId(order.getUserId())
  103. .stream().map(UserBankCard::getBindCardId).findFirst().orElse(null);
  104. }
  105. if (StringUtils.isEmpty(bindCardId)) {
  106. throw new BusinessException("请先绑定银行卡");
  107. }
  108. return payEaseService.pay(order.getName(), orderId.toString(), order.getTotalPrice(),
  109. order.getUserId().toString(), bindCardId, Constants.OrderNotifyType.ORDER);
  110. }
  111. public void confirmOrderAgreement(String requestId, String paymentOrderId, String code) {
  112. try {
  113. payEaseService.payConfirm(requestId, paymentOrderId, code);
  114. } catch (BusinessException e) {
  115. try {
  116. new Thread(() -> {
  117. orderService.cancel(Long.parseLong(requestId));
  118. }).start();
  119. } catch (Exception ee) {
  120. }
  121. throw e;
  122. }
  123. }
  124. @Cacheable(value = "payOrder", key = "'gift#'+#orderId")
  125. public String payGiftOrder(Long orderId) {
  126. GiftOrder order = giftOrderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
  127. if (order.getStatus() != OrderStatus.NOT_PAID) {
  128. throw new BusinessException("订单状态错误");
  129. }
  130. switch (PAY_CHANNEL) {
  131. case Constants.PayChannel.SAND:
  132. return sandPayService.pay(orderId + "", "转赠" + order.getAssetId(), order.getGasPrice(),
  133. order.getCreatedAt().plusMinutes(3), Constants.OrderNotifyType.GIFT);
  134. case Constants.PayChannel.HM:
  135. return hmPayService.requestAlipay(orderId + "", order.getGasPrice(),
  136. "转赠" + order.getAssetId(),
  137. HMPayService.getTimeout(order.getCreatedAt(), 180),
  138. Constants.OrderNotifyType.GIFT, generalProperties.getHost() + "/9th/home");
  139. }
  140. throw new BusinessException(Constants.PAY_ERR_MSG);
  141. }
  142. @Cacheable(value = "payOrder", key = "'gift#'+#orderId")
  143. public String payGiftQuick(Long orderId) {
  144. GiftOrder order = giftOrderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
  145. if (order.getStatus() != OrderStatus.NOT_PAID) {
  146. throw new BusinessException("订单状态错误");
  147. }
  148. return sandPayService.payQuick(orderId + "", "转赠" + order.getAssetId(), order.getGasPrice(),
  149. order.getCreatedAt().plusMinutes(3), Constants.OrderNotifyType.GIFT,
  150. generalProperties.getHost() + "/9th/home");
  151. }
  152. public void payGiftBalance(Long orderId, Long userId, String tradeCode) {
  153. GiftOrder order = giftOrderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
  154. if (order.getStatus() != OrderStatus.NOT_PAID) {
  155. throw new BusinessException("订单状态错误");
  156. }
  157. checkTradeCode(userId, tradeCode, order.getUserId());
  158. BalanceRecord record = userBalanceService.balancePay(order.getUserId(), order.getGasPrice(), orderId, "转赠");
  159. giftOrderService.giftNotify(orderId, PayMethod.BALANCE, record.getId().toString());
  160. }
  161. @Cacheable(value = "payOrder", key = "'gift#'+#orderId")
  162. public Map<String, Object> payGiftOrderAgreement(Long orderId, String bindCardId) {
  163. GiftOrder order = giftOrderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
  164. if (order.getStatus() != OrderStatus.NOT_PAID) {
  165. throw new BusinessException("订单状态错误");
  166. }
  167. if (StringUtils.isEmpty(bindCardId)) {
  168. bindCardId = userBankCardRepo.findByUserId(order.getUserId())
  169. .stream().map(UserBankCard::getBindCardId).findFirst().orElse(null);
  170. }
  171. if (StringUtils.isEmpty(bindCardId)) {
  172. throw new BusinessException("请先绑定银行卡");
  173. }
  174. return payEaseService.pay("转赠" + order.getAssetId(), orderId.toString(), order.getGasPrice(),
  175. order.getUserId().toString(), bindCardId, Constants.OrderNotifyType.GIFT);
  176. }
  177. @Cacheable(value = "payOrder", key = "'mintOrder#'+#orderId")
  178. public String payMintOrder(Long orderId) {
  179. MintOrder order = mintOrderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
  180. if (order.getStatus() != MintOrderStatus.NOT_PAID) {
  181. throw new BusinessException("订单状态错误");
  182. }
  183. switch (PAY_CHANNEL) {
  184. case Constants.PayChannel.SAND:
  185. return sandPayService.pay(orderId + "", "铸造活动:" + order.getMintActivityId(),
  186. order.getGasPrice(), order.getCreatedAt().plusMinutes(3), Constants.OrderNotifyType.MINT);
  187. case Constants.PayChannel.HM:
  188. return hmPayService.requestAlipay(orderId + "", order.getGasPrice(),
  189. "铸造活动:" + order.getMintActivityId(),
  190. HMPayService.getTimeout(order.getCreatedAt(), 180),
  191. Constants.OrderNotifyType.MINT, generalProperties.getHost() + "/9th/home");
  192. }
  193. throw new BusinessException("绿洲宇宙冷却系统已启动,请稍后支付");
  194. }
  195. @Cacheable(value = "payOrder", key = "'mintOrder#'+#orderId")
  196. public String payMintQuick(Long orderId) {
  197. MintOrder order = mintOrderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
  198. if (order.getStatus() != MintOrderStatus.NOT_PAID) {
  199. throw new BusinessException("订单状态错误");
  200. }
  201. return sandPayService.payQuick(orderId + "", "铸造活动:" + order.getMintActivityId(),
  202. order.getGasPrice(), order.getCreatedAt().plusMinutes(3), Constants.OrderNotifyType.MINT,
  203. generalProperties.getHost() + "/9th/home");
  204. }
  205. public void payMintOrderBalance(Long orderId, Long userId, String tradeCode) {
  206. MintOrder order = mintOrderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
  207. if (order.getStatus() != MintOrderStatus.NOT_PAID) {
  208. throw new BusinessException("订单状态错误");
  209. }
  210. checkTradeCode(userId, tradeCode, order.getUserId());
  211. BalanceRecord record = userBalanceService.balancePay(order.getUserId(), order.getGasPrice(), orderId, "铸造活动");
  212. mintOrderService.mintNotify(orderId, PayMethod.BALANCE, record.getId().toString());
  213. }
  214. private void checkTradeCode(Long userId, String tradeCode, Long orderUserId) {
  215. if (!Objects.equals(orderUserId, userId)) {
  216. throw new BusinessException("订单不属于该用户");
  217. }
  218. String encodedPwd = userRepo.findTradeCode(userId);
  219. if (StringUtils.isEmpty(encodedPwd)) {
  220. throw new BusinessException("请先设置交易密码");
  221. }
  222. if (!passwordEncoder.matches(tradeCode, encodedPwd)) {
  223. throw new BusinessException("交易码错误");
  224. }
  225. }
  226. @Cacheable(value = "payOrder", key = "'mint#'+#orderId")
  227. public Map<String, Object> payMintOrderAgreement(Long orderId, String bindCardId) {
  228. MintOrder order = mintOrderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
  229. if (order.getStatus() != MintOrderStatus.NOT_PAID) {
  230. throw new BusinessException("订单状态错误");
  231. }
  232. if (StringUtils.isEmpty(bindCardId)) {
  233. bindCardId = userBankCardRepo.findByUserId(order.getUserId())
  234. .stream().map(UserBankCard::getBindCardId).findFirst().orElse(null);
  235. }
  236. if (StringUtils.isEmpty(bindCardId)) {
  237. throw new BusinessException("请先绑定银行卡");
  238. }
  239. return payEaseService.pay("铸造活动:" + order.getMintActivityId(), orderId.toString(), order.getGasPrice(),
  240. order.getUserId().toString(), bindCardId, Constants.OrderNotifyType.MINT);
  241. }
  242. public String recharge(Long userId, BigDecimal amount) {
  243. BigDecimal minAmount = sysConfigService.getBigDecimal("min_recharge_amount");
  244. if (amount.compareTo(minAmount) < 0) {
  245. throw new BusinessException("充值金额不能小于" + minAmount);
  246. }
  247. if (amount.compareTo(new BigDecimal("50000")) > 0) {
  248. throw new BusinessException("充值金额不能大于50000");
  249. }
  250. RechargeOrder order = RechargeOrder.builder()
  251. .id(snowflakeIdWorker.nextId())
  252. .userId(userId)
  253. .amount(amount)
  254. .status(OrderStatus.NOT_PAID)
  255. .build();
  256. rechargeOrderRepo.save(order);
  257. switch (PAY_CHANNEL) {
  258. case Constants.PayChannel.SAND:
  259. return sandPayService.pay(order.getId() + "", "余额充值", order.getAmount(),
  260. order.getCreatedAt().plusMinutes(3), Constants.OrderNotifyType.RECHARGE);
  261. case Constants.PayChannel.HM:
  262. return hmPayService.requestAlipay(order.getId() + "", order.getAmount(),
  263. "余额充值",
  264. HMPayService.getTimeout(order.getCreatedAt(), 180),
  265. Constants.OrderNotifyType.RECHARGE, generalProperties.getHost() + "/9th/home");
  266. }
  267. throw new BusinessException("绿洲宇宙冷却系统已启动,请稍后支付");
  268. }
  269. public Map<String, Object> rechargeAgreement(Long userId, BigDecimal amount, String bindCardId) {
  270. BigDecimal minAmount = sysConfigService.getBigDecimal("min_recharge_amount");
  271. if (amount.compareTo(minAmount) < 0) {
  272. throw new BusinessException("充值金额不能小于" + minAmount);
  273. }
  274. if (amount.compareTo(new BigDecimal("50000")) > 0) {
  275. throw new BusinessException("充值金额不能大于50000");
  276. }
  277. RechargeOrder order = RechargeOrder.builder()
  278. .id(snowflakeIdWorker.nextId())
  279. .userId(userId)
  280. .amount(amount)
  281. .status(OrderStatus.NOT_PAID)
  282. .build();
  283. rechargeOrderRepo.save(order);
  284. if (StringUtils.isEmpty(bindCardId)) {
  285. bindCardId = userBankCardRepo.findByUserId(order.getUserId())
  286. .stream().map(UserBankCard::getBindCardId).findFirst().orElse(null);
  287. }
  288. if (StringUtils.isEmpty(bindCardId)) {
  289. throw new BusinessException("请先绑定银行卡");
  290. }
  291. return payEaseService.pay("余额充值", order.getId().toString(), order.getAmount(),
  292. order.getUserId().toString(), bindCardId, Constants.OrderNotifyType.RECHARGE);
  293. }
  294. public String rechargeQuick(Long userId, BigDecimal amount) {
  295. BigDecimal minAmount = sysConfigService.getBigDecimal("min_recharge_amount");
  296. if (amount.compareTo(minAmount) < 0) {
  297. throw new BusinessException("充值金额不能小于" + minAmount);
  298. }
  299. if (amount.compareTo(new BigDecimal("50000")) > 0) {
  300. throw new BusinessException("充值金额不能大于50000");
  301. }
  302. RechargeOrder order = RechargeOrder.builder()
  303. .id(snowflakeIdWorker.nextId())
  304. .userId(userId)
  305. .amount(amount)
  306. .status(OrderStatus.NOT_PAID)
  307. .build();
  308. rechargeOrderRepo.save(order);
  309. return sandPayService.payQuick(order.getId() + "", "余额充值",
  310. order.getAmount(), LocalDateTime.now().plusMinutes(3), Constants.OrderNotifyType.RECHARGE,
  311. generalProperties.getHost() + "/9th/home");
  312. }
  313. public JSONObject refund(String orderId, String transactionId, BigDecimal amount, String channel) {
  314. switch (channel) {
  315. case Constants.PayChannel.SAND: {
  316. JSONObject res = sandPayService.refund(orderId, amount);
  317. if (!"000000".equals(res.getJSONObject("head").getString("respCode"))) {
  318. String msg = res.getJSONObject("head").getString("respMsg");
  319. throw new BusinessException("退款失败:" + msg);
  320. }
  321. return res;
  322. }
  323. case Constants.PayChannel.HM: {
  324. JSONObject res = hmPayService.refund(orderId, amount);
  325. if (!"REFUND_SUCCESS".equals(res.getString("sub_code"))) {
  326. String msg = res.getString("msg");
  327. throw new BusinessException("退款失败:" + msg);
  328. }
  329. return res;
  330. }
  331. case Constants.PayChannel.PE: {
  332. JSONObject res = payEaseService.refund(orderId, transactionId, amount);
  333. String status = res.getString("status");
  334. if (!"SUCCESS".equals(status)) {
  335. String error = res.getString("error");
  336. String cause = res.getString("cause");
  337. throw new BusinessException("退款失败:" + error + ";" + cause);
  338. }
  339. return res;
  340. }
  341. }
  342. throw new BusinessException("退款失败");
  343. }
  344. public PayQuery query(String orderId) {
  345. PayQuery query = sandPayService.payQuery(orderId);
  346. if (query == null || !query.isExist()) {
  347. query = hmPayService.payQuery(orderId);
  348. }
  349. if (query == null || !query.isExist()) {
  350. query = payEaseService.payQuery(orderId);
  351. }
  352. return Optional.ofNullable(query).orElse(PayQuery.builder().exist(false).build());
  353. }
  354. }