OrderController.java 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800
  1. package com.cyksj.web.controller.payment;
  2. import cn.hutool.core.codec.Base64;
  3. import cn.hutool.core.util.StrUtil;
  4. import cn.hutool.extra.qrcode.QrCodeUtil;
  5. import cn.hutool.extra.qrcode.QrConfig;
  6. import cn.hutool.extra.servlet.ServletUtil;
  7. import cn.hutool.json.JSONObject;
  8. import com.alipay.api.response.AlipayFundTransCommonQueryResponse;
  9. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  10. import com.cyksj.common.constant.Constant;
  11. import com.cyksj.common.exception.BusinessRuntimeException;
  12. import com.cyksj.common.util.IoKit;
  13. import com.cyksj.common.util.Jsons;
  14. import com.cyksj.common.util.StringUtil;
  15. import com.cyksj.common.util.Xmls;
  16. import com.cyksj.config.zfb.BaseZfbConfig;
  17. import com.cyksj.config.zfb.ZfbProductCode;
  18. import com.cyksj.dto.Result;
  19. import com.cyksj.enums.GatewayApiCode;
  20. import com.cyksj.enums.GatewayResponse;
  21. import com.cyksj.mapper.OrderDonWaybillMapper;
  22. import com.cyksj.mapper.UserMapper;
  23. import com.cyksj.mapper.channel.UserPayEquipmentAvailableBenefitsMapper;
  24. import com.cyksj.mapper.market.task.UserBindDetailMapper;
  25. import com.cyksj.model.dto.AliPayParams;
  26. import com.cyksj.model.dto.H5JsPayParams;
  27. import com.cyksj.model.entity.*;
  28. import com.cyksj.model.manage.views.*;
  29. import com.cyksj.model.request.AlipayOrderDonReq;
  30. import com.cyksj.model.request.OrderPayRequest;
  31. import com.cyksj.model.response.AliPayTradeStatus;
  32. import com.cyksj.model.views.GoodsDonSkuView;
  33. import com.cyksj.model.views.MidjourneyUserView;
  34. import com.cyksj.model.views.OrderCommentView;
  35. import com.cyksj.service.midjourney.MidjourneyAccountService;
  36. import com.cyksj.service.order.OrderDonService;
  37. import com.cyksj.service.paypal.PayPalService;
  38. import com.cyksj.service.paypal.PaypalPayConfigService;
  39. import com.cyksj.service.stripe.StripePayConfigService;
  40. import com.cyksj.service.stripe.StripeService;
  41. import com.cyksj.service.user.UserBindRelationService;
  42. import com.cyksj.web.util.StpUserUtil;
  43. import com.ejlchina.searcher.BeanSearcher;
  44. import com.ejlchina.searcher.SearchResult;
  45. import com.ejlchina.searcher.param.Operator;
  46. import com.ejlchina.searcher.util.MapBuilder;
  47. import com.ejlchina.searcher.util.MapUtils;
  48. import com.google.gson.JsonSyntaxException;
  49. import com.paypal.api.payments.Links;
  50. import com.paypal.api.payments.Payment;
  51. import com.stripe.exception.SignatureVerificationException;
  52. import com.stripe.model.*;
  53. import com.stripe.model.checkout.Session;
  54. import com.stripe.net.Webhook;
  55. import lombok.extern.slf4j.Slf4j;
  56. import org.apache.commons.lang3.StringUtils;
  57. import org.springframework.beans.BeanUtils;
  58. import org.springframework.beans.factory.annotation.Autowired;
  59. import org.springframework.validation.annotation.Validated;
  60. import org.springframework.web.bind.annotation.*;
  61. import javax.annotation.Resource;
  62. import javax.servlet.http.Cookie;
  63. import javax.servlet.http.HttpServletRequest;
  64. import javax.servlet.http.HttpServletResponse;
  65. import java.io.InputStream;
  66. import java.io.OutputStream;
  67. import java.nio.charset.StandardCharsets;
  68. import java.util.HashMap;
  69. import java.util.List;
  70. import java.util.Map;
  71. import java.util.Set;
  72. import java.util.stream.Collectors;
  73. /**
  74. * @author chan
  75. * @date 2021/10/11 下午3:50
  76. */
  77. @Slf4j
  78. @RequestMapping("/applets/order")
  79. @RestController
  80. public class OrderController {
  81. @Autowired
  82. private OrderDonService orderDonService;
  83. @Resource
  84. private BeanSearcher beanSearcher;
  85. @Resource
  86. private HttpServletRequest request;
  87. @Resource
  88. private HttpServletResponse response;
  89. @Autowired
  90. private UserBindDetailMapper userBindDetailMapper;
  91. @Autowired
  92. private UserMapper userMapper;
  93. @Autowired
  94. private UserPayEquipmentAvailableBenefitsMapper availableBenefitsMapper;
  95. @Autowired
  96. private OrderDonWaybillMapper waybillMapper;
  97. @Autowired
  98. private UserBindRelationService UserBindRelationService;
  99. @Autowired
  100. private PaypalPayConfigService paypalPayConfigService;
  101. @Autowired
  102. private PayPalService payPalService;
  103. @Autowired
  104. private StripePayConfigService stripePayConfigService;
  105. @Autowired
  106. private StripeService stripeService;
  107. @Autowired
  108. private MidjourneyAccountService midjourneyAccountService;
  109. /**
  110. * 支付
  111. * @author chan
  112. * @date 2021-10-11 下午4:56
  113. */
  114. @PostMapping("/post/submit")
  115. public Result<OrderDon> submit(@Validated @RequestBody OrderPayRequest payRequest, HttpServletResponse response) throws Exception {
  116. final String methodName = "吊起微信支付";
  117. Long userId = StpUserUtil.getUserIdAfterLogin();
  118. payRequest.setUserId(userId);
  119. log.info("{}[start] params:{}", methodName, payRequest);
  120. String ip = ServletUtil.getClientIP(request);
  121. String address = StringUtil.getNewInternalAddressByIp(ip);
  122. if (address.contains("柬埔寨") || address.contains("缅甸")) {
  123. throw BusinessRuntimeException.getInstance("用户系统异常");
  124. }
  125. payRequest.setIp(ip);
  126. OrderDon orderDon = orderDonService.submit(payRequest);
  127. //无登录订单 预留手机号免登录
  128. if (userId == null && payRequest.getPopularizeId() != null && StrUtil.isNotBlank(payRequest.getPhone())) {
  129. User user = userMapper.selectById(orderDon.getUserId());
  130. //写回登陆信息
  131. StpUserUtil.login(user.getId());
  132. response.addHeader("satoken-user", StpUserUtil.getTokenValue());
  133. Cookie cookie = new Cookie("satoken-user", StpUserUtil.getTokenValue());
  134. cookie.setMaxAge(31536000);
  135. cookie.setPath("/");
  136. response.addCookie(cookie);
  137. JSONObject jsonObject = new JSONObject();
  138. jsonObject.putOpt("showId", user.getShowId());
  139. jsonObject.putOpt("nickName", user.getNickname());
  140. Cookie userInfo = new Cookie("info", Base64.encode(jsonObject.toString()));
  141. cookie.setMaxAge(31536000);
  142. cookie.setPath("/");
  143. response.addCookie(userInfo);
  144. }
  145. return GatewayResponse.SUCCESS.newBuilder().toResult(orderDon);
  146. }
  147. /**
  148. * 套餐提交支付
  149. */
  150. @PostMapping("/post/upgrade/submit")
  151. public Result<UpgradeOrderDon> submitUpgrade(@Validated @RequestBody OrderPayRequest payRequest) throws Exception {
  152. final String methodName = "套餐吊起支付";
  153. Long userId = StpUserUtil.getUserIdAfterLogin();
  154. payRequest.setUserId(userId);
  155. log.info("{}[start] params:{}", methodName, payRequest);
  156. String ip = ServletUtil.getClientIP(request);
  157. payRequest.setIp(ip);
  158. UpgradeOrderDon orderDon = orderDonService.submitUpgrade(payRequest);
  159. return GatewayResponse.SUCCESS.newBuilder().toResult(orderDon);
  160. }
  161. /**
  162. * 0元订单确认
  163. */
  164. @PostMapping("/post/order/status/{orderId}")
  165. public Result<String> zeroOrderConfirm(@PathVariable Long orderId) {
  166. orderDonService.zeroOrderConfirm(orderId);
  167. return GatewayResponse.SUCCESS.newBuilder().toResult();
  168. }
  169. /**
  170. * 套餐0元订单确认
  171. */
  172. @PostMapping("/post/upgrade/order/status/{orderId}")
  173. public Result<String> zeroUpgradeOrderConfirm(@PathVariable Long orderId) {
  174. orderDonService.zeroUpgradeOrderConfirm(orderId);
  175. return GatewayResponse.SUCCESS.newBuilder().toResult();
  176. }
  177. /**
  178. * 支付
  179. * @author chan
  180. * @date 2021-10-11 下午4:56
  181. */
  182. @PostMapping("/post/pay/{orderId}")
  183. public Result<H5JsPayParams> pay(@PathVariable Long orderId) throws Exception {
  184. final String methodName = "吊起微信支付";
  185. log.info("{}[start] orderId:{}",methodName,orderId);
  186. H5JsPayParams payParams = orderDonService.pay(orderId, "JSAPI");
  187. return GatewayResponse.SUCCESS.newBuilder().toResult(payParams);
  188. }
  189. /**
  190. * 调用生成订单之后
  191. * 微信网页预下单获取交易链接生成二维码
  192. */
  193. @PostMapping("/get/wx/orderQrCode/{orderId}")
  194. public Result<String> createUnifiedOrderQr(@PathVariable Long orderId) throws Exception {
  195. //预下单
  196. H5JsPayParams payParams = orderDonService.wxPcWebPay(orderId, "NATIVE");
  197. //获取二维码链接code_url
  198. String codeUrl = payParams.getCodeUrl();
  199. QrConfig qrConfig = new QrConfig(300, 300);
  200. return GatewayResponse.SUCCESS.newBuilder().toResult(QrCodeUtil.generateAsBase64(codeUrl, qrConfig, "png"));
  201. }
  202. /**
  203. * 微信支付回调
  204. * @author chan
  205. * @date 2021-10-11 下午5:42
  206. */
  207. @PostMapping("/prepay/notify")
  208. public void prepayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
  209. String xml = IoKit.toString(request.getInputStream());
  210. log.info("=== 微信支付成功的回调: \n {}", xml);
  211. // 解析xml
  212. Map<String, String> map = Xmls.toMap(xml);
  213. // 支付失败
  214. if (!StringUtils.equals("SUCCESS", map.get("return_code")) || !StringUtils.equals("SUCCESS", map.get("result_code"))) {
  215. throw BusinessRuntimeException.getInstance("支付失败.");
  216. }
  217. orderDonService.prepayNotify(map);
  218. String toWeChatXmlResponse = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
  219. OutputStream out = null;
  220. try {
  221. out = response.getOutputStream();
  222. IoKit.write(toWeChatXmlResponse, out);
  223. } catch (Exception e) {
  224. throw BusinessRuntimeException.getInstance(e,e.getMessage());
  225. } finally {
  226. IoKit.close(out);
  227. }
  228. }
  229. /**
  230. * pc端微信支付回调
  231. * @author chan
  232. * @date 2021-10-11 下午5:42
  233. */
  234. @PostMapping("/pc/prepay/notify")
  235. public void pcPrepayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
  236. String xml = IoKit.toString(request.getInputStream());
  237. log.info("=== 微信pc端分发支付成功的回调: \n {}", xml);
  238. // 解析xml
  239. Map<String, String> map = Xmls.toMap(xml);
  240. // 支付失败
  241. if (!StringUtils.equals("SUCCESS", map.get("return_code")) || !StringUtils.equals("SUCCESS", map.get("result_code"))) {
  242. throw BusinessRuntimeException.getInstance("支付失败.");
  243. }
  244. orderDonService.prepayNotify(map);
  245. log.info("pc端微信支付回调修改订单状态成功");
  246. String toWeChatXmlResponse = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
  247. OutputStream out = null;
  248. try {
  249. out = response.getOutputStream();
  250. IoKit.write(toWeChatXmlResponse, out);
  251. } catch (Exception e) {
  252. throw BusinessRuntimeException.getInstance(e,e.getMessage());
  253. } finally {
  254. IoKit.close(out);
  255. }
  256. }
  257. /**
  258. * 支付宝表单支付
  259. * 支付宝调起支付宝表单
  260. * 手机支付
  261. */
  262. @PostMapping("/post/pay/zfb")
  263. @Deprecated
  264. public Result<String> aliPay(@RequestBody @Validated AlipayOrderDonReq re) throws Exception {
  265. AliPayParams aliPayParams = orderDonService.aliPay(re, ZfbProductCode.MOBILE_WEB.getProductCode(), null);
  266. // response.setContentType("text/html;charset=" + BaseZfbConfig.charset);
  267. //直接将完整的表单html输出到页面
  268. // response.getWriter().write(aliPayParams.getBody());
  269. // response.getWriter().flush();
  270. // response.getWriter().close();
  271. return GatewayResponse.SUCCESS.newBuilder().toResult(aliPayParams.getBody());
  272. }
  273. /**
  274. * 套餐支付宝支付
  275. */
  276. @PostMapping("/post/pay/upgrade/zfb")
  277. @Deprecated
  278. public Result<String> aliPayUpgrade(@RequestBody @Validated AlipayOrderDonReq re) throws Exception {
  279. AliPayParams aliPayParams = orderDonService.aliPayUpgrade(re, ZfbProductCode.MOBILE_WEB.getProductCode(),null);
  280. return GatewayResponse.SUCCESS.newBuilder().toResult(aliPayParams.getBody());
  281. }
  282. /**
  283. * 支付宝web支付
  284. * pc网页内嵌二维码
  285. */
  286. @PostMapping("/get/zfb/orderQrCode")
  287. public Result<String> zfbWebQrCode(@RequestBody @Validated AlipayOrderDonReq re) throws Exception {
  288. AliPayParams aliPayParams = orderDonService.aliPay(re, ZfbProductCode.PC_WEB.getProductCode(), BaseZfbConfig.qrPayMode_orderCode);
  289. // response.setContentType("text/html;charset=" + BaseZfbConfig.charset);
  290. //直接将完整的表单html输出到页面
  291. // response.getWriter().write(aliPayParams.getBody());
  292. // response.getWriter().flush();
  293. // response.getWriter().close();
  294. return GatewayResponse.SUCCESS.newBuilder().toResult(aliPayParams.getBody());
  295. }
  296. /**
  297. * 支付宝web支付
  298. * pc网页内嵌二维码
  299. */
  300. @PostMapping("/get/zfb/upgrade/orderQrCode")
  301. public Result<String> zfbWebQrCodeUpgrade(@RequestBody @Validated AlipayOrderDonReq re) throws Exception {
  302. AliPayParams aliPayParams = orderDonService.aliPayUpgrade(re, ZfbProductCode.PC_WEB.getProductCode(), BaseZfbConfig.qrPayMode_orderCode);
  303. // response.setContentType("text/html;charset=" + BaseZfbConfig.charset);
  304. //直接将完整的表单html输出到页面
  305. // response.getWriter().write(aliPayParams.getBody());
  306. // response.getWriter().flush();
  307. // response.getWriter().close();
  308. return GatewayResponse.SUCCESS.newBuilder().toResult(aliPayParams.getBody());
  309. }
  310. /**
  311. * 支付宝web支付
  312. * pc网页跳转二维码
  313. */
  314. @PostMapping("/get/zfb/orderRedirect")
  315. public Result<String> zfbWebRedirectQrCode(@RequestBody @Validated AlipayOrderDonReq re) throws Exception {
  316. AliPayParams aliPayParams = orderDonService.aliPay(re, ZfbProductCode.PC_WEB.getProductCode(), BaseZfbConfig.qrPayMode_redirect);
  317. return GatewayResponse.SUCCESS.newBuilder().toResult(aliPayParams.getBody());
  318. }
  319. /**
  320. * 支付宝回调
  321. */
  322. @PostMapping("/prepay/zfb/notify")
  323. public String aliPayNotify(HttpServletRequest request) throws Exception {
  324. ////将异步通知中收到的所有参数都存放到map中
  325. Map<String, String> params = convertRequestParamsToMap(request);
  326. String tradeStatus = params.get("trade_status");
  327. String orderNo = params.get("out_trade_no");
  328. if (AliPayTradeStatus.TRADE_SUCCESS.getStatus().equals(tradeStatus) || AliPayTradeStatus.TRADE_FINISHED.getStatus().equals(tradeStatus)) {
  329. log.info("支付宝商家订单号orderNo:{},status:{}开始回调", orderNo, tradeStatus);
  330. orderDonService.aliPayNotify(params);
  331. } else {
  332. log.error("支付宝回调 error 状态不符合 成功或完成 status:{} ,orderNo:{}", tradeStatus, orderNo);
  333. return "fail";
  334. }
  335. return "success";
  336. }
  337. /**
  338. * 支付宝套餐包回调
  339. */
  340. @PostMapping("/prepay/zfb/upgrade/notify")
  341. public String aliPayUpgradeNotify(HttpServletRequest request) throws Exception {
  342. ////将异步通知中收到的所有参数都存放到map中
  343. Map<String, String> params = convertRequestParamsToMap(request);
  344. String tradeStatus = params.get("trade_status");
  345. String orderNo = params.get("out_trade_no");
  346. if (AliPayTradeStatus.TRADE_SUCCESS.getStatus().equals(tradeStatus) || AliPayTradeStatus.TRADE_FINISHED.getStatus().equals(tradeStatus)) {
  347. log.info("支付宝商家订单号orderNo:{},status:{}开始回调", orderNo, tradeStatus);
  348. orderDonService.aliPayUpgradeNotify(params);
  349. } else {
  350. log.error("支付宝回调 error 状态不符合 成功或完成 status:{} ,orderNo:{}", tradeStatus, orderNo);
  351. return "fail";
  352. }
  353. return "success";
  354. }
  355. /**
  356. * 支付宝转账
  357. */
  358. // @PostMapping("/zfb/transfer/accounts")
  359. // @NoSubmit
  360. // public Result<String> zfbTransferAccounts(@RequestBody @Validated TransferAccountsReq transferAccountsReq) throws Exception {
  361. // long userId = StpUserUtil.getLoginIdAsLong();
  362. // transferAccountsReq.setUserId(userId);
  363. // orderDonService.transferAccounts(transferAccountsReq);
  364. // return GatewayResponse.SUCCESS.newBuilder().toResult("转账成功");
  365. // }
  366. /**
  367. * 查询支付宝转账状态
  368. */
  369. @GetMapping("/zfb/transfer/status")
  370. public Result<String> getTransFerStatusByTid(String translationId) throws Exception {
  371. AlipayFundTransCommonQueryResponse response = orderDonService.getTransFerStatusByTid(translationId);
  372. if (response.isSuccess()) {
  373. if (!Constant.SUCCESS.equals(response.getStatus())) {
  374. return GatewayResponse.SUCCESS.newBuilder().toResult(response.getFailReason());
  375. }
  376. return GatewayResponse.SUCCESS.newBuilder().toResult("该红包已转账成功");
  377. }
  378. return GatewayResponse.SUCCESS.newBuilder().toResult(response.getSubMsg());
  379. }
  380. /**
  381. * 获取订单列表
  382. */
  383. @GetMapping("/get")
  384. public Result<SearchResult<OrderDonView>> list(String customId){
  385. long userId = StpUserUtil.getLoginIdAsLong();
  386. MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
  387. //Long yhsId = yhShopFrontService.getYhsIdByCustomId(customId);
  388. List<Long> userIds = UserBindRelationService.getRelationUserIdList(userId, null);
  389. SearchResult<OrderDonView> search = beanSearcher.search(OrderDonView.class, builder
  390. //.field(OrderDonView::getYhsId, yhsId)
  391. .field(OrderDonView::getUserId, userIds).op(Operator.InList)
  392. .orderBy(OrderDonView::getId).desc()
  393. .build());
  394. search.getDataList().forEach(data->{
  395. Integer count = availableBenefitsMapper.selectCount(Wrappers.lambdaQuery(UserPayEquipmentAvailableBenefits.class)
  396. .eq(UserPayEquipmentAvailableBenefits::getRealOrderId, data.getId())
  397. .eq(UserPayEquipmentAvailableBenefits::getDeleted, true));
  398. data.setIsHasBenefits(count > 0 ? true : false);
  399. if (data.getIsBenefits() != null && data.getIsBenefits()) {
  400. String benefitsList = data.getBenefitsList();
  401. if (StrUtil.isNotBlank(benefitsList)) {
  402. try {
  403. List<Long> skuIds = Jsons.parseList(benefitsList, GoodsDonSku.class).stream().map(GoodsDonSku::getId).collect(Collectors.toList());
  404. data.setBenefitsViews(beanSearcher.searchAll(GoodsDonSkuView.class, MapUtils.builder().field(GoodsDonSkuView::getSkuId, skuIds).op(Operator.InList).build()));
  405. } catch (Exception e) {
  406. }
  407. }
  408. }
  409. data.setWaybill(waybillMapper.selectOne(Wrappers.lambdaQuery(OrderDonWaybill.class).eq(OrderDonWaybill::getOrderId, data.getId()).last("limit 1")));
  410. });
  411. return GatewayResponse.SUCCESS.newBuilder().toResult(search);
  412. }
  413. /**
  414. * 获取订单详情
  415. */
  416. @GetMapping("/get/{orderId}")
  417. public Result<OrderDetailView> detail(@PathVariable Long orderId, Boolean isNoLogin) {
  418. Long userId = StpUserUtil.getUserIdAfterLogin();
  419. OrderDetailView detail = orderDonService.getDetail(orderId, userId);
  420. return GatewayResponse.SUCCESS.newBuilder().toResult(detail);
  421. }
  422. /**
  423. * 取消订单
  424. */
  425. @GetMapping("/get/close/{orderId}")
  426. public Result<String> closeOrder(@PathVariable Long orderId) {
  427. long userId = StpUserUtil.getLoginIdAsLong();
  428. orderDonService.closeOrder(orderId, userId);
  429. return GatewayResponse.SUCCESS.newBuilder().toResult();
  430. }
  431. @GetMapping("/get/order/status/{orderId}")
  432. public Result<OrderDonSearchView> getOrderStatusById(@PathVariable Long orderId) {
  433. if (orderId < 1) {
  434. throw BusinessRuntimeException.getInstance("订单不存在");
  435. }
  436. OrderDonSearchView orderDonView = beanSearcher.searchFirst(OrderDonSearchView.class, MapUtils.builder()
  437. .put("orderId", String.format("where id = %s", orderId))
  438. .build());
  439. if (orderDonView == null) {
  440. throw BusinessRuntimeException.getInstance("订单不存在");
  441. }
  442. return GatewayResponse.SUCCESS.newBuilder().toResult(orderDonView);
  443. }
  444. /**
  445. * 查询套餐订单支付状态
  446. */
  447. @GetMapping("/get/upgrade/order/status/{orderId}")
  448. public Result<UpgradeOrderDonSearchView> getUpgradeOrderStatusById(@PathVariable Long orderId) {
  449. if (orderId < 1) {
  450. throw BusinessRuntimeException.getInstance("订单不存在");
  451. }
  452. UpgradeOrderDonSearchView orderDonView = beanSearcher.searchFirst(UpgradeOrderDonSearchView.class, MapUtils.builder()
  453. .put("orderId", String.format("where id = %s", orderId))
  454. .build());
  455. if (orderDonView == null) {
  456. throw BusinessRuntimeException.getInstance("订单不存在");
  457. }
  458. return GatewayResponse.SUCCESS.newBuilder().toResult(orderDonView);
  459. }
  460. @PostMapping("/get/noLogin/order")
  461. public Result<List<OrderDonView>> getSearchResult(@RequestBody List<Long> orderIds) {
  462. List<OrderDonView> orderDonViews = beanSearcher.searchAll(OrderDonView.class, MapUtils.builder()
  463. .field(OrderDonView::getId, orderIds).op(Operator.InList)
  464. .orderBy(OrderDonView::getId).desc().build());
  465. return GatewayResponse.SUCCESS.newBuilder().toResult(orderDonViews);
  466. }
  467. /**
  468. * 平台评论列表
  469. */
  470. @GetMapping("/get/orderComment")
  471. public Result<SearchResult<OrderCommentView>> getOrderCommentView() {
  472. SearchResult<OrderCommentView> search = beanSearcher.search(OrderCommentView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
  473. return GatewayResponse.SUCCESS.newBuilder().toResult(search);
  474. }
  475. /**
  476. * 电脑端手机号注册 购买车票是否绑定了微信用户
  477. */
  478. @GetMapping("/isBindWx")
  479. public Result<Boolean> isBindWx() {
  480. Long userId = StpUserUtil.getLoginIdAsLong();
  481. User user = userMapper.selectById(userId);
  482. if (user == null) {
  483. throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID);
  484. }
  485. if (StrUtil.isEmpty(user.getLoginPhone())) {
  486. return GatewayResponse.SUCCESS.newBuilder().toResult(true);
  487. }
  488. UserBindDetail userBindDetail = userBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class)
  489. .eq(UserBindDetail::getPhone, user.getLoginPhone()));
  490. if (userBindDetail == null || userBindDetail.getUserId() == null) {
  491. return GatewayResponse.SUCCESS.newBuilder().toResult(false);
  492. }
  493. return GatewayResponse.SUCCESS.newBuilder().toResult(true);
  494. }
  495. /**
  496. * 是否绑定了邮箱或手机号
  497. */
  498. @GetMapping("/isBind")
  499. public Result<Boolean> isBindPhoneOrEmail() {
  500. Long userId = StpUserUtil.getLoginIdAsLong();
  501. User user = userMapper.selectById(userId);
  502. if (user == null) {
  503. throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID);
  504. }
  505. //手机号注册 无需绑定
  506. if (StrUtil.isNotEmpty(user.getLoginPhone())) {
  507. return GatewayResponse.SUCCESS.newBuilder().toResult(true);
  508. }
  509. //是否绑定了手机号
  510. UserBindDetail userBindDetail = userBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class)
  511. .eq(StrUtil.isNotEmpty(user.getOpenId()), UserBindDetail::getUserId, userId)
  512. .eq(StrUtil.isNotEmpty(user.getEmail()), UserBindDetail::getEmailUserId, userId).last("limit 1"));
  513. //台湾ip
  514. String address = StringUtil.getNewInternalAddressByIp(ServletUtil.getClientIP(request));
  515. if (address.contains("台湾") || !address.contains("中国")) {
  516. return GatewayResponse.SUCCESS.newBuilder().toResult(true);
  517. }
  518. if (userBindDetail == null || StrUtil.isEmpty(userBindDetail.getPhone())) {
  519. return GatewayResponse.SUCCESS.newBuilder().toResult(false);
  520. }
  521. return GatewayResponse.SUCCESS.newBuilder().toResult(true);
  522. }
  523. /**
  524. * 获取支付宝回调参数
  525. */
  526. private static Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
  527. Map<String, String> retMap = new HashMap<>();
  528. Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();
  529. for (Map.Entry<String, String[]> entry : entrySet) {
  530. String name = entry.getKey();
  531. String[] values = entry.getValue();
  532. int valLen = values.length;
  533. if (valLen == 1) {
  534. retMap.put(name, values[0]);
  535. } else if (valLen > 1) {
  536. StringBuilder sb = new StringBuilder();
  537. for (String val : values) {
  538. sb.append(",").append(val);
  539. }
  540. retMap.put(name, sb.substring(1));
  541. } else {
  542. retMap.put(name, "");
  543. }
  544. }
  545. return retMap;
  546. }
  547. /**
  548. * paypal支付
  549. */
  550. @PostMapping("/paypal/pay/{orderId}")
  551. public Result<String> paypalPay(@PathVariable Long orderId,String successUrl) throws Exception {
  552. final String methodName = "paypal支付";
  553. log.info("{}[start] orderId:{}",methodName,orderId);
  554. Payment payment = payPalService.createPayment(orderId,successUrl);
  555. String payUrl = "/";
  556. log.info("paypal links:{}",payment.getLinks());
  557. for(Links links : payment.getLinks()){
  558. if("approval_url".equals(links.getRel())){
  559. // 客户付款登陆地址
  560. String payPalUrl = links.getHref();
  561. log.info("PayPal调起支付成功[end]:{}", orderId);
  562. payUrl = payPalUrl;
  563. }
  564. }
  565. log.info("paypal支付成功[end]");
  566. return GatewayResponse.SUCCESS.newBuilder().toResult(payUrl);
  567. }
  568. /**
  569. * stripe支付
  570. */
  571. @PostMapping("/stripe/pay/{orderId}")
  572. public Result<String> stripePay(@PathVariable Long orderId,String successUrl) throws Exception {
  573. final String methodName = "stripe支付";
  574. log.info("{}[start] orderId:{}",methodName,orderId);
  575. String payUrl = stripeService.checkOutStripe(orderId,successUrl);
  576. log.info("Stripe支付成功 result:{}[end]",payUrl);
  577. return GatewayResponse.SUCCESS.newBuilder().toResult(payUrl);
  578. }
  579. /**
  580. * paypal支付回调
  581. */
  582. @RequestMapping(value = "/paypal/notify")
  583. public void successPay(@RequestParam(value = "paymentId") String paymentId, @RequestParam(value = "PayerID") String PayerID) throws Exception {
  584. PaypalPayConfig paypalPayConfig = paypalPayConfigService.getById(1);
  585. response.sendRedirect(payPalService.successPayment(paymentId,PayerID,paypalPayConfig));
  586. }
  587. /**
  588. * stripe支付回调
  589. */
  590. @PostMapping("/stripe/notify")
  591. @ResponseBody
  592. public String webhooks() throws Exception {
  593. InputStream inputStream = request.getInputStream();
  594. byte[] bytes = IoKit.toBytes(inputStream);
  595. String payload = new String(bytes, StandardCharsets.UTF_8);
  596. String sigHeader = request.getHeader("Stripe-Signature");
  597. StripePayConfig stripePayConfig = stripePayConfigService.getById(1);
  598. Event event = null;
  599. try {
  600. event = Webhook.constructEvent(
  601. payload, sigHeader, stripePayConfig.getWebhookSecret()
  602. );
  603. } catch (JsonSyntaxException | SignatureVerificationException e) {
  604. response.setStatus(400);
  605. return "";
  606. }
  607. // Deserialize the nested object inside the event
  608. EventDataObjectDeserializer dataObjectDeserializer = event.getDataObjectDeserializer();
  609. StripeObject stripeObject = null;
  610. if (dataObjectDeserializer.getObject().isPresent()) {
  611. stripeObject = dataObjectDeserializer.getObject().orElse(null);
  612. } else {
  613. // Deserialization failed, probably due to an API version mismatch.
  614. // Refer to the Javadoc documentation on `EventDataObjectDeserializer` for
  615. // instructions on how to handle this case, or return an error here.
  616. }
  617. // Handle the event
  618. switch (event.getType()) {
  619. case "payment_intent.succeeded":
  620. PaymentIntent paymentIntent = (PaymentIntent) stripeObject;
  621. response.setStatus(200);
  622. break;
  623. case "charge.succeeded":
  624. //使用token支付成功回调
  625. Charge charge = (Charge) stripeObject;
  626. //TODO 此时根据charge ID 查询出关联的订单并处理支付成功业务代码
  627. response.setStatus(200);
  628. break;
  629. case "checkout.session.completed":
  630. //使用checkout支付成功回调
  631. Session session = (Session) stripeObject;
  632. stripeService.fulfillOrder(session);
  633. response.setStatus(200);
  634. break;
  635. default:
  636. response.setStatus(400);
  637. return "";
  638. }
  639. response.setStatus(200);
  640. return "";
  641. }
  642. /**
  643. * 余额明细
  644. */
  645. @GetMapping("/get/balance/detail")
  646. public Result<SearchResult<UserBalanceSourceRecord>> getUserBalanceSourceRecord() {
  647. long userId = StpUserUtil.getLoginIdAsLong();
  648. SearchResult<UserBalanceSourceRecord> search = beanSearcher.search(UserBalanceSourceRecord.class, MapUtils.flatBuilder(request.getParameterMap())
  649. .field(UserBalanceSourceRecord::getUserId, userId)
  650. .field(UserBalanceSourceRecord::getDetail).op(Operator.NotNull)
  651. .orderBy(UserBalanceSourceRecord::getId).desc()
  652. .onlySelect(UserBalanceSourceRecord::getBalance, UserBalanceSourceRecord::getDetail, UserBalanceSourceRecord::getCreatedTime)
  653. .build());
  654. return GatewayResponse.SUCCESS.newBuilder().toResult(search);
  655. }
  656. /**
  657. * 获取套餐订单列表
  658. */
  659. @GetMapping("/upgrade/get")
  660. public Result<SearchResult<UpgradeOrderDonView>> listUpgradeOrder(){
  661. long userId = StpUserUtil.getLoginIdAsLong();
  662. MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
  663. List<Long> userIds = UserBindRelationService.getRelationUserIdList(userId, null);
  664. SearchResult<UpgradeOrderDonView> search = beanSearcher.search(UpgradeOrderDonView.class, builder
  665. .field(UpgradeOrderDonView::getUserId, userIds).op(Operator.InList)
  666. .orderBy(UpgradeOrderDonView::getId).desc()
  667. .build());
  668. return GatewayResponse.SUCCESS.newBuilder().toResult(search);
  669. }
  670. /**
  671. * 获取套餐订单详情
  672. */
  673. @GetMapping("/get/upgrade/{orderId}")
  674. public Result<UpgradeOrderDetailView> upgradeOrderDetail(@PathVariable Long orderId) {
  675. Long userId = StpUserUtil.getUserIdAfterLogin();
  676. UpgradeOrderDetailView detail = orderDonService.getUpgradeOrderDetail(orderId, userId);
  677. return GatewayResponse.SUCCESS.newBuilder().toResult(detail);
  678. }
  679. /**
  680. * 取消套餐订单
  681. */
  682. @GetMapping("/get/close/upgrade/{orderId}")
  683. public Result<String> closeUpgradeOrder(@PathVariable Long orderId) {
  684. long userId = StpUserUtil.getLoginIdAsLong();
  685. orderDonService.closeUpgradeOrder(orderId, userId);
  686. return GatewayResponse.SUCCESS.newBuilder().toResult();
  687. }
  688. /**
  689. * midjourney查询订单用户账号剩余次数
  690. */
  691. @GetMapping("/get/midjourney/user")
  692. public Result<MidjourneyUserView> getMidjourneyUser(Long relationId) {
  693. long userId = StpUserUtil.getLoginIdAsLong();
  694. MidjourneyUserView search = beanSearcher.searchFirst(MidjourneyUserView.class, MapUtils.flatBuilder(request.getParameterMap())
  695. .field(MidjourneyUserView::getUserId, userId).field(MidjourneyUserView::getRelationId, relationId).build());
  696. if (search == null) {
  697. MidjourneyUser midjourneyUser = midjourneyAccountService.getMidjourneyUserToken(userId, relationId);
  698. search = new MidjourneyUserView();
  699. BeanUtils.copyProperties(midjourneyUser, search);
  700. }
  701. return GatewayResponse.SUCCESS.newBuilder().toResult(search);
  702. }
  703. }