AliPayCommonServiceImpl.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. package com.cyksj.service.pay.impl;
  2. import cn.hutool.core.date.DateUtil;
  3. import cn.hutool.core.util.StrUtil;
  4. import com.alipay.api.AlipayApiException;
  5. import com.alipay.api.AlipayClient;
  6. import com.alipay.api.AlipayRequest;
  7. import com.alipay.api.domain.AlipayTradePagePayModel;
  8. import com.alipay.api.domain.AlipayTradeWapPayModel;
  9. import com.alipay.api.request.AlipayTradePagePayRequest;
  10. import com.alipay.api.request.AlipayTradeWapPayRequest;
  11. import com.baomidou.mybatisplus.core.toolkit.Assert;
  12. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  13. import com.cyksj.common.EnvCommonService;
  14. import com.cyksj.common.exception.BusinessRuntimeException;
  15. import com.cyksj.common.snowflake.Sequence;
  16. import com.cyksj.common.util.Codec;
  17. import com.cyksj.common.util.Jsons;
  18. import com.cyksj.common.util.StringUtil;
  19. import com.cyksj.config.zfb.AliPayClientFactory;
  20. import com.cyksj.config.zfb.BaseZfbConfig;
  21. import com.cyksj.config.zfb.ZfbProductCode;
  22. import com.cyksj.mapper.*;
  23. import com.cyksj.mapper.channel.ShopConfigMapper;
  24. import com.cyksj.mapper.order.OrderDonPostMapper;
  25. import com.cyksj.model.dto.AliPayParams;
  26. import com.cyksj.model.dto.OrderPayBuilderDto;
  27. import com.cyksj.model.entity.*;
  28. import com.cyksj.model.request.AlipayOrderDonReq;
  29. import com.cyksj.model.request.OrderAttach;
  30. import com.cyksj.service.pay.AliPayCommonService;
  31. import com.cyksj.service.sys.SysConfigService;
  32. import lombok.RequiredArgsConstructor;
  33. import lombok.extern.slf4j.Slf4j;
  34. import org.springframework.stereotype.Service;
  35. import java.math.BigDecimal;
  36. import java.math.RoundingMode;
  37. import java.util.Date;
  38. import java.util.Optional;
  39. /*
  40. *项目名: netflix
  41. *文件名: AliPayCommonServiceImpl
  42. *创建者: JavaZou
  43. *创建时间:2023/6/14 15:19
  44. */
  45. @Service
  46. @RequiredArgsConstructor
  47. @Slf4j
  48. public class AliPayCommonServiceImpl implements AliPayCommonService {
  49. private final RegisterOrderDonMapper registerOrderDonMapper;
  50. private final OrderDonMapper orderDonMapper;
  51. private final GoodsDonMapper goodsDonMapper;
  52. private final ShopConfigMapper shopConfigMapper;
  53. private final EnvCommonService envCommonService;
  54. private final SysConfigService sysConfigService;
  55. private final OrderDonPostMapper orderDonPostMapper;
  56. private final UpgradeOrderDonMapper upgradeOrderDonMapper;
  57. private final UpgradePackageMapper upgradePackageMapper;
  58. private final GoodsWholesaleOrderDonMapper goodsWholesaleOrderDonMapper;
  59. private final GoodsWholesaleUserDepositMapper depositMapper;
  60. private final UserBenefitsOrderRecordMapper userBenefitsOrderRecordMapper;
  61. private static final Sequence SEQUENCE = new Sequence(0);
  62. @Override
  63. public AliPayParams unifiedPayRegister(Long orderId, String productCode, String payMode, String returnUrl) throws Exception {
  64. RegisterOrderDon orderDon = registerOrderDonMapper.selectById(orderId);
  65. Assert.notNull(orderDon, "订单不存在");
  66. if (StrUtil.isEmpty(productCode)) throw BusinessRuntimeException.getInstance("支付异常");
  67. //获取支付宝默认商户
  68. String shopId = sysConfigService.getDefaultShopConfigByType("zfb");
  69. orderDon.setShopId(shopId);
  70. orderDon.setType(RegisterOrderDon.Type.ALI_PAY);
  71. if (orderDon.getType() != RegisterOrderDon.Type.ALI_PAY) {
  72. orderDon.setType(RegisterOrderDon.Type.ALI_PAY);
  73. }
  74. registerOrderDonMapper.updateById(orderDon);
  75. //回调地址
  76. String host = envCommonService.getNotifyHost();
  77. String notifyUrl = String.format("%s%s", host, BaseZfbConfig.zfb_register_notify_url);
  78. if (ZfbProductCode.MOBILE_WEB.getProductCode().equals(productCode) && BaseZfbConfig.qrPayMode_redirect.equals(payMode)) {
  79. returnUrl = String.format("%s%s", envCommonService.getDomain(), BaseZfbConfig.zfb_register_login_return_url);
  80. }
  81. String subject = "注册服务";
  82. AliPayParams aliPayParams = builderPayParams(orderDon.getId(),
  83. orderDon.getOrderNo(),
  84. orderDon.getShopId(),
  85. orderDon.getMoney(),
  86. orderDon.getCreatedTime(),
  87. subject,
  88. productCode,
  89. payMode,
  90. notifyUrl,
  91. returnUrl);
  92. return aliPayParams;
  93. }
  94. @Override
  95. public AliPayParams unifiedPay(AlipayOrderDonReq re, String productCode, String payMode) throws Exception {
  96. Long orderId = re.getOrderId();
  97. String returnUrl = re.getReturnUrl();
  98. OrderDon orderDon = orderDonMapper.selectById(orderId);
  99. //获取支付宝默认商户
  100. String appId = sysConfigService.getDefaultShopConfigByType("zfb");
  101. if (orderDon.getPopularizeId() != null) {
  102. ShopConfig shopConfig = shopConfigMapper.getByChannelPopularizeId(orderDon.getPopularizeId(), "zfb");
  103. if (shopConfig != null) {
  104. appId = shopConfig.getAppId();
  105. }
  106. }
  107. if (OrderDon.Type.ALI_PAY != orderDon.getType()) {
  108. orderDon.setType(OrderDon.Type.ALI_PAY);
  109. }
  110. orderDon.setShopId(appId);
  111. if (ZfbProductCode.PC_WEB.getProductCode().equals(productCode)) {
  112. orderDon.setIsWebPay(true);
  113. }
  114. if (ZfbProductCode.MOBILE_WEB.getProductCode().equals(productCode)) {
  115. orderDon.setIsWebPay(false);
  116. }
  117. orderDonMapper.updateById(orderDon);
  118. String notifyPath = BaseZfbConfig.notifyUrl;
  119. Boolean isUserBenefits = re.getIsUserBenefits();
  120. String subject;
  121. if (isUserBenefits) {
  122. subject = orderDon.getGoodsId() == 15 ? "套餐权益" : "续费减免";
  123. } else {
  124. GoodsDon goodsDon = goodsDonMapper.selectById(orderDon.getGoodsId());
  125. subject = goodsDon.getTitle().contains("ChatGPT") ? "AI订阅" : goodsDon.getTitle();
  126. }
  127. //回调地址
  128. String host = envCommonService.getNotifyHost();
  129. String notifyUrl = String.format("%s%s", host, notifyPath);
  130. //手机h5 跳转
  131. OrderDonPost orderDonPost = orderDonPostMapper.selectOne(Wrappers.lambdaQuery(OrderDonPost.class)
  132. .eq(OrderDonPost::getOrderId, orderId).last("limit 1"));
  133. //百度回传 跳转
  134. Boolean is_bdPost = false;
  135. if (orderDonPost != null && OrderDonPost.Type.BaiDu == orderDonPost.getType()) {
  136. is_bdPost = true;
  137. }
  138. if (StrUtil.isNotEmpty(returnUrl)) {
  139. log.info("支付宝支付成功返回地址:{}", returnUrl);
  140. }
  141. //是否在微信内支付 微信内支付宝支付后 支付宝回调页面不跳转
  142. Boolean isWx = Optional.ofNullable(re.getIsWx()).orElse(false);
  143. if (ZfbProductCode.MOBILE_WEB.getProductCode().equals(productCode) && !isWx) {
  144. if (is_bdPost) {
  145. //页面 拼接订单号,前端从url获取订单id.
  146. returnUrl = String.format("%s%s", envCommonService.getDomain(), BaseZfbConfig.SUCCESS_URL) + orderDon.getId();
  147. } else {
  148. if (StrUtil.isEmpty(returnUrl)) {
  149. //默认跳转页
  150. returnUrl = String.format("%s%s", envCommonService.getDomain(), BaseZfbConfig.DEFAULT_URL);
  151. }
  152. }
  153. }
  154. if (StrUtil.isNotEmpty(returnUrl)) {
  155. log.info("支付宝支付成功最终返回地址:{}", returnUrl);
  156. }
  157. AliPayParams aliPayParams = builderPayParams(orderDon.getId(),
  158. orderDon.getOrderNo(),
  159. orderDon.getShopId(),
  160. orderDon.getMoney(),
  161. orderDon.getCreatedTime(),
  162. subject,
  163. productCode,
  164. payMode,
  165. notifyUrl,
  166. returnUrl);
  167. return aliPayParams;
  168. }
  169. public AliPayParams builderPayParams(Long orderId, String orderNo, String shopId, BigDecimal money, Date orderCreatedTime, String subject, String productCode, String payMode, String notifyUrl, String returnUrl) throws Exception {
  170. OrderPayBuilderDto orderPayBuilderDto = new OrderPayBuilderDto();
  171. orderPayBuilderDto.setOrderId(orderId);
  172. orderPayBuilderDto.setMoney(money);
  173. orderPayBuilderDto.setOrderNo(orderNo);
  174. orderPayBuilderDto.setSubject(subject);
  175. orderPayBuilderDto.setOrderCreatedTime(orderCreatedTime);
  176. orderPayBuilderDto.setProductCode(productCode);
  177. orderPayBuilderDto.setPayMode(payMode);
  178. orderPayBuilderDto.setReturnUrl(returnUrl);
  179. orderPayBuilderDto.setNotifyUrl(notifyUrl);
  180. orderPayBuilderDto.setShopId(shopId);
  181. AliPayParams aliPayParams = commonAliPay(orderPayBuilderDto);
  182. return aliPayParams;
  183. }
  184. public AliPayParams commonAliPay(OrderPayBuilderDto orderPayBuilderDto) throws Exception {
  185. AlipayClient alipayClient = AliPayClientFactory.getAlipayClient(Optional.ofNullable(orderPayBuilderDto.getShopId()).orElse(ShopConfig.ZFB_DEFAULT_APP_ID));
  186. String returnUrl = orderPayBuilderDto.getReturnUrl();
  187. String notifyUrl = orderPayBuilderDto.getNotifyUrl();
  188. // 创建API对应的request
  189. AlipayRequest alipayRequest = getAliAayRequest(orderPayBuilderDto);
  190. if (alipayRequest == null) {
  191. throw BusinessRuntimeException.getInstance("支付宝不支持该支付方式:{0}", orderPayBuilderDto.getProductCode());
  192. }
  193. if (StrUtil.isNotBlank(returnUrl)) {
  194. alipayRequest.setReturnUrl(returnUrl);
  195. }
  196. alipayRequest.setNotifyUrl(notifyUrl);
  197. String form = null;
  198. try {
  199. //调用SDK生成表单
  200. //pagePay 统一下单接口
  201. form = alipayClient.pageExecute(alipayRequest).getBody();
  202. } catch (AlipayApiException e) {
  203. log.error("支付宝生成表单错误:{}", StringUtil.getErrorText(e));
  204. }
  205. log.info("支付宝返回参数:{}", form);
  206. return new AliPayParams(form);
  207. }
  208. /**
  209. * 支付宝获取不同的request
  210. */
  211. private AlipayRequest getAliAayRequest(OrderPayBuilderDto payBuilderDto) throws Exception {
  212. Long orderId = payBuilderDto.getOrderId();
  213. BigDecimal money = payBuilderDto.getMoney();
  214. String orderNo = payBuilderDto.getOrderNo();
  215. //productCode 销售产品码,与支付宝签约的产品码名称
  216. String productCode = payBuilderDto.getProductCode();
  217. String subject = payBuilderDto.getSubject();
  218. Date orderCreatedTime = payBuilderDto.getOrderCreatedTime();
  219. //网页支付跳转模式
  220. String qrPayMode = payBuilderDto.getPayMode();
  221. OrderAttach attach = new OrderAttach();
  222. attach.setO(orderId);
  223. String body = Codec.DoBase64.custom()
  224. .setData(Jsons.toJson(attach)).encodeAsText();
  225. String moneyStr = money.divide(new BigDecimal(100), 2, RoundingMode.HALF_EVEN).toString();
  226. if (ZfbProductCode.MOBILE_WEB.getProductCode().equals(productCode)) {
  227. //手机网站支付
  228. AlipayTradeWapPayRequest alipayTradeWapPayRequest = new AlipayTradeWapPayRequest();
  229. //手机网站支付支付参数
  230. AlipayTradeWapPayModel alipayTradeWapPayModel = new AlipayTradeWapPayModel();
  231. alipayTradeWapPayModel.setBody(body);
  232. alipayTradeWapPayModel.setOutTradeNo(orderNo);
  233. alipayTradeWapPayModel.setTotalAmount(moneyStr);
  234. alipayTradeWapPayModel.setSubject(subject);
  235. alipayTradeWapPayModel.setProductCode(productCode);
  236. //5分钟订单失效时间
  237. alipayTradeWapPayModel.setTimeExpire(DateUtil.offsetMinute(orderCreatedTime, 5).toString());
  238. alipayTradeWapPayRequest.setBizModel(alipayTradeWapPayModel);
  239. return alipayTradeWapPayRequest;
  240. } else if (ZfbProductCode.PC_WEB.getProductCode().equals(productCode)) {
  241. //电脑网站支付
  242. AlipayTradePagePayRequest alipayTradePagePayRequest = new AlipayTradePagePayRequest();
  243. //电脑网站支付参数
  244. AlipayTradePagePayModel alipayTradePagePayModel = new AlipayTradePagePayModel();
  245. alipayTradePagePayModel.setBody(body);
  246. alipayTradePagePayModel.setOutTradeNo(orderNo);
  247. alipayTradePagePayModel.setTotalAmount(moneyStr);
  248. alipayTradePagePayModel.setSubject(subject);
  249. alipayTradePagePayModel.setProductCode(productCode);
  250. //5分钟订单失效时间
  251. alipayTradePagePayModel.setTimeExpire(DateUtil.offsetMinute(orderCreatedTime, 5).toString());
  252. if (StrUtil.isEmpty(qrPayMode)) {
  253. qrPayMode = BaseZfbConfig.qrPayMode_orderCode;
  254. }
  255. alipayTradePagePayModel.setQrPayMode(qrPayMode);
  256. alipayTradePagePayRequest.setBizModel(alipayTradePagePayModel);
  257. return alipayTradePagePayRequest;
  258. }
  259. return null;
  260. }
  261. @Override
  262. public AliPayParams unifiedPayUpgrade(AlipayOrderDonReq re, String productCode, String payMode) throws Exception {
  263. Long orderId = re.getOrderId();
  264. String returnUrl = re.getReturnUrl();
  265. UpgradeOrderDon orderDon = upgradeOrderDonMapper.selectById(orderId);
  266. //获取支付宝默认商户
  267. String appId = sysConfigService.getDefaultShopConfigByType("zfb");
  268. if (UpgradeOrderDon.Type.ALI_PAY != orderDon.getType()) {
  269. orderDon.setType(UpgradeOrderDon.Type.ALI_PAY);
  270. }
  271. orderDon.setShopId(appId);
  272. if (ZfbProductCode.PC_WEB.getProductCode().equals(productCode)) {
  273. orderDon.setIsWebPay(true);
  274. }
  275. if (ZfbProductCode.MOBILE_WEB.getProductCode().equals(productCode)) {
  276. orderDon.setIsWebPay(false);
  277. }
  278. upgradeOrderDonMapper.updateById(orderDon);
  279. UpgradePackage upgradePackage = upgradePackageMapper.selectById(orderDon.getPackageId());
  280. String subject = upgradePackage.getName();
  281. //回调地址
  282. String host = envCommonService.getNotifyHost();
  283. String notifyUrl = String.format("%s%s", host, BaseZfbConfig.upgradeNotifyUrl);
  284. //是否在微信内支付 微信内支付宝支付后 支付宝回调页面不跳转
  285. Boolean isWx = Optional.ofNullable(re.getIsWx()).orElse(false);
  286. if (ZfbProductCode.MOBILE_WEB.getProductCode().equals(productCode) && !isWx) {
  287. //默认跳转页
  288. returnUrl = String.format("%s%s", envCommonService.getDomain(), BaseZfbConfig.DEFAULT_URL);
  289. }
  290. return builderPayParams(orderDon.getId(),
  291. orderDon.getOrderNo(),
  292. orderDon.getShopId(),
  293. orderDon.getMoney(),
  294. orderDon.getCreatedTime(),
  295. subject,
  296. productCode,
  297. payMode,
  298. notifyUrl,
  299. returnUrl);
  300. }
  301. @Override
  302. public AliPayParams aliPayUnifiedWholesale(AlipayOrderDonReq re, String productCode, String payMode) throws Exception {
  303. Long orderId = re.getOrderId();
  304. String returnUrl = re.getReturnUrl();
  305. GoodsWholesaleOrderDon orderDon = goodsWholesaleOrderDonMapper.selectById(orderId);
  306. //获取支付宝默认商户
  307. String appId = sysConfigService.getDefaultShopConfigByType("zfb");
  308. if (GoodsWholesaleOrderDon.Type.ALI_PAY != orderDon.getType()) {
  309. orderDon.setType(GoodsWholesaleOrderDon.Type.ALI_PAY);
  310. }
  311. orderDon.setShopId(appId);
  312. if (ZfbProductCode.PC_WEB.getProductCode().equals(productCode)) {
  313. orderDon.setIsWebPay(true);
  314. }
  315. if (ZfbProductCode.MOBILE_WEB.getProductCode().equals(productCode)) {
  316. orderDon.setIsWebPay(false);
  317. }
  318. goodsWholesaleOrderDonMapper.updateById(orderDon);
  319. GoodsDon goodsDon = goodsDonMapper.selectById(orderDon.getGoodsId());
  320. String subject = goodsDon.getTitle();
  321. //回调地址
  322. String host = envCommonService.getNotifyHost();
  323. String notifyUrl = String.format("%s%s", host, BaseZfbConfig.wholesaleNotifyUrl);
  324. //是否在微信内支付 微信内支付宝支付后 支付宝回调页面不跳转
  325. Boolean isWx = Optional.ofNullable(re.getIsWx()).orElse(false);
  326. if (StrUtil.isEmpty(returnUrl) && ZfbProductCode.MOBILE_WEB.getProductCode().equals(productCode) && !isWx) {
  327. //默认跳转页
  328. returnUrl = String.format("%s%s", envCommonService.getDomain(), BaseZfbConfig.DEFAULT_URL);
  329. }
  330. return builderPayParams(orderDon.getId(),
  331. orderDon.getOrderNo(),
  332. orderDon.getShopId(),
  333. orderDon.getMoney(),
  334. orderDon.getUpdateTime(),
  335. subject,
  336. productCode,
  337. payMode,
  338. notifyUrl,
  339. returnUrl);
  340. }
  341. @Override
  342. public AliPayParams aliPayUnifiedWholesaleDeposit(AlipayOrderDonReq re, String productCode, String payMode) throws Exception {
  343. Long orderId = re.getOrderId();
  344. String returnUrl = re.getReturnUrl();
  345. GoodsWholesaleUserDeposit orderDon = depositMapper.selectById(orderId);
  346. //获取支付宝默认商户
  347. String appId = sysConfigService.getDefaultShopConfigByType("zfb");
  348. if (GoodsWholesaleUserDeposit.Type.ALI_PAY != orderDon.getType()) {
  349. orderDon.setType(GoodsWholesaleUserDeposit.Type.ALI_PAY);
  350. }
  351. orderDon.setShopId(appId);
  352. if (ZfbProductCode.PC_WEB.getProductCode().equals(productCode)) {
  353. orderDon.setIsWebPay(true);
  354. }
  355. if (ZfbProductCode.MOBILE_WEB.getProductCode().equals(productCode)) {
  356. orderDon.setIsWebPay(false);
  357. }
  358. depositMapper.updateById(orderDon);
  359. String subject = "押金";
  360. //回调地址
  361. String host = envCommonService.getNotifyHost();
  362. String notifyUrl = String.format("%s%s", host, BaseZfbConfig.wholesaleDepositNotifyUrl);
  363. //是否在微信内支付 微信内支付宝支付后 支付宝回调页面不跳转
  364. Boolean isWx = Optional.ofNullable(re.getIsWx()).orElse(false);
  365. if (StrUtil.isEmpty(returnUrl) && ZfbProductCode.MOBILE_WEB.getProductCode().equals(productCode) && !isWx) {
  366. //默认跳转页
  367. returnUrl = String.format("%s%s", envCommonService.getDomain(), BaseZfbConfig.DEFAULT_URL);
  368. }
  369. //退款后重新支付
  370. if (orderDon.getStatus() == GoodsWholesaleUserDeposit.Status.refund) {
  371. orderDon.setOrderNo(SEQUENCE.nextId().toString());
  372. }
  373. return builderPayParams(orderDon.getId(),
  374. orderDon.getOrderNo(),
  375. orderDon.getShopId(),
  376. orderDon.getMoney(),
  377. orderDon.getUpdateTime(),
  378. subject,
  379. productCode,
  380. payMode,
  381. notifyUrl,
  382. returnUrl);
  383. }
  384. }