package com.cyksj.web.controller.payment; import cn.hutool.core.codec.Base64; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.qrcode.QrCodeUtil; import cn.hutool.extra.qrcode.QrConfig; import cn.hutool.extra.servlet.ServletUtil; import cn.hutool.json.JSONObject; import com.alipay.api.response.AlipayFundTransCommonQueryResponse; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.cyksj.common.constant.Constant; import com.cyksj.common.exception.BusinessRuntimeException; import com.cyksj.common.util.IoKit; import com.cyksj.common.util.Jsons; import com.cyksj.common.util.StringUtil; import com.cyksj.common.util.Xmls; import com.cyksj.config.zfb.BaseZfbConfig; import com.cyksj.config.zfb.ZfbProductCode; import com.cyksj.dto.Result; import com.cyksj.enums.GatewayApiCode; import com.cyksj.enums.GatewayResponse; import com.cyksj.mapper.*; import com.cyksj.mapper.channel.UserPayEquipmentAvailableBenefitsMapper; import com.cyksj.mapper.market.task.UserBindDetailMapper; import com.cyksj.model.dto.AliPayParams; import com.cyksj.model.dto.H5JsPayParams; import com.cyksj.model.entity.*; import com.cyksj.model.manage.views.*; import com.cyksj.model.request.AlipayOrderDonReq; import com.cyksj.model.request.OrderPayRequest; import com.cyksj.model.response.AliPayTradeStatus; import com.cyksj.model.views.GoodsDonSkuView; import com.cyksj.model.views.LumaUserView; import com.cyksj.model.views.MidjourneyUserView; import com.cyksj.model.views.OrderCommentView; import com.cyksj.service.luma.LumaService; import com.cyksj.service.midjourney.MidjourneyAccountService; import com.cyksj.service.order.OrderDonService; import com.cyksj.service.paypal.PayPalService; import com.cyksj.service.paypal.PaypalPayConfigService; import com.cyksj.service.paypal.PaypalV2Service; import com.cyksj.service.stripe.StripePayConfigService; import com.cyksj.service.stripe.StripeService; import com.cyksj.service.translations.BackInfoTranslationsFrontService; import com.cyksj.service.user.UserBindRelationService; import com.cyksj.web.util.StpUserUtil; import com.ejlchina.searcher.BeanSearcher; import com.ejlchina.searcher.SearchResult; import com.ejlchina.searcher.param.Operator; import com.ejlchina.searcher.util.MapBuilder; import com.ejlchina.searcher.util.MapUtils; import com.google.gson.JsonSyntaxException; import com.paypal.api.payments.Links; import com.paypal.api.payments.Payment; import com.stripe.exception.SignatureVerificationException; import com.stripe.model.*; import com.stripe.model.checkout.Session; import com.stripe.net.Webhook; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.InputStream; import java.io.OutputStream; import java.math.BigDecimal; import java.math.RoundingMode; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.stream.Collectors; /** * @author chan * @date 2021/10/11 下午3:50 */ @Slf4j @RequestMapping("/applets/order") @RestController public class OrderController { @Autowired private OrderDonService orderDonService; @Resource private BeanSearcher beanSearcher; @Resource private HttpServletRequest request; @Resource private HttpServletResponse response; @Autowired private UserBindDetailMapper userBindDetailMapper; @Autowired private UserMapper userMapper; @Autowired private UserPayEquipmentAvailableBenefitsMapper availableBenefitsMapper; @Autowired private OrderDonWaybillMapper waybillMapper; @Autowired private UserBindRelationService UserBindRelationService; @Autowired private PaypalPayConfigService paypalPayConfigService; @Autowired private PayPalService payPalService; @Autowired private PaypalV2Service paypalV2Service; @Autowired private StripePayConfigService stripePayConfigService; @Autowired private StripeService stripeService; @Autowired private MidjourneyAccountService midjourneyAccountService; @Autowired private GoodsDonSkuMapper skuMapper; @Autowired private OrderDonRenewRecordMapper orderDonRenewRecordMapper; @Autowired private LumaService lumaService; @Autowired private UserBindRelationService userBindRelationService; @Autowired private GroupsRelationMapper relationMapper; @Autowired private BackInfoTranslationsFrontService backInfoTranslationsFrontService; @Autowired private UpgradePackageMapper upgradePackageMapper; @Autowired private OrderDonMapper orderDonMapper; /** * 支付 * @author chan * @date 2021-10-11 下午4:56 */ @PostMapping("/post/submit") public Result submit(@Validated @RequestBody OrderPayRequest payRequest, HttpServletResponse response) throws Exception { final String methodName = "吊起微信支付"; Long userId = StpUserUtil.getUserIdAfterLogin(); payRequest.setUserId(userId); log.info("{}[start] params:{}", methodName, payRequest); String ip = ServletUtil.getClientIP(request); String address = StringUtil.getNewInternalAddressByIp(ip); //address.contains("柬埔寨") || if (address != null && address.contains("缅甸")) { throw BusinessRuntimeException.getInstance("用户异常"); } payRequest.setIp(ip); //非推广 免登录 if (payRequest.getPopularizeId() == null && payRequest.getIsNoLogin()) { throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID); } OrderDon orderDon = orderDonService.submit(payRequest); //无登录订单 预留手机号免登录 if (userId == null && payRequest.getPopularizeId() != null && StrUtil.isNotBlank(payRequest.getPhone())) { User user = userMapper.selectById(orderDon.getUserId()); //写回登陆信息 StpUserUtil.login(user.getId()); response.addHeader("satoken-user", StpUserUtil.getTokenValue()); Cookie cookie = new Cookie("satoken-user", StpUserUtil.getTokenValue()); cookie.setMaxAge(31536000); cookie.setPath("/"); response.addCookie(cookie); JSONObject jsonObject = new JSONObject(); jsonObject.putOpt("showId", user.getShowId()); jsonObject.putOpt("nickName", user.getNickname()); Cookie userInfo = new Cookie("info", Base64.encode(jsonObject.toString())); cookie.setMaxAge(31536000); cookie.setPath("/"); response.addCookie(userInfo); } return GatewayResponse.SUCCESS.newBuilder().toResult(orderDon); } /** * 套餐提交支付 */ @PostMapping("/post/upgrade/submit") public Result submitUpgrade(@Validated @RequestBody OrderPayRequest payRequest) throws Exception { final String methodName = "套餐吊起支付"; //无需免登录 Long userId = StpUserUtil.getLoginIdAsLong(); payRequest.setUserId(userId); log.info("{}[start] params:{}", methodName, payRequest); String ip = ServletUtil.getClientIP(request); payRequest.setIp(ip); UpgradeOrderDon orderDon = orderDonService.submitUpgrade(payRequest); return GatewayResponse.SUCCESS.newBuilder().toResult(orderDon); } /** * 0元订单确认 */ @PostMapping("/post/order/status/{orderId}") @Deprecated public Result zeroOrderConfirm(@PathVariable Long orderId) { orderDonService.zeroOrderConfirm(orderId); return GatewayResponse.SUCCESS.newBuilder().toResult(); } /** * 套餐0元订单确认 */ @PostMapping("/post/upgrade/order/status/{orderId}") @Deprecated public Result zeroUpgradeOrderConfirm(@PathVariable Long orderId) { orderDonService.zeroUpgradeOrderConfirm(orderId); return GatewayResponse.SUCCESS.newBuilder().toResult(); } /** * 支付 * @author chan * @date 2021-10-11 下午4:56 */ @PostMapping("/post/pay/{orderId}") public Result pay(@PathVariable Long orderId) throws Exception { final String methodName = "吊起微信支付"; log.info("{}[start] orderId:{}",methodName,orderId); H5JsPayParams payParams = orderDonService.pay(orderId, "JSAPI"); return GatewayResponse.SUCCESS.newBuilder().toResult(payParams); } /** * 调用生成订单之后 * 微信网页预下单获取交易链接生成二维码 */ @PostMapping("/get/wx/orderQrCode/{orderId}") public Result createUnifiedOrderQr(@PathVariable Long orderId) throws Exception { //预下单 H5JsPayParams payParams = orderDonService.wxPcWebPay(orderId, "NATIVE"); //获取二维码链接code_url String codeUrl = payParams.getCodeUrl(); QrConfig qrConfig = new QrConfig(300, 300); return GatewayResponse.SUCCESS.newBuilder().toResult(QrCodeUtil.generateAsBase64(codeUrl, qrConfig, "png")); } /** * 微信支付回调 * @author chan * @date 2021-10-11 下午5:42 */ @PostMapping("/prepay/notify") public void prepayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception { String xml = IoKit.toString(request.getInputStream()); log.info("=== 微信支付成功的回调: \n {}", xml); // 解析xml Map map = Xmls.toMap(xml); // 支付失败 if (!StringUtils.equals("SUCCESS", map.get("return_code")) || !StringUtils.equals("SUCCESS", map.get("result_code"))) { throw BusinessRuntimeException.getInstance("支付失败."); } orderDonService.prepayNotify(map); String toWeChatXmlResponse = ""; OutputStream out = null; try { out = response.getOutputStream(); IoKit.write(toWeChatXmlResponse, out); } catch (Exception e) { throw BusinessRuntimeException.getInstance(e,e.getMessage()); } finally { IoKit.close(out); } } /** * pc端微信支付回调 * @author chan * @date 2021-10-11 下午5:42 */ @PostMapping("/pc/prepay/notify") public void pcPrepayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception { String xml = IoKit.toString(request.getInputStream()); log.info("=== 微信pc端分发支付成功的回调: \n {}", xml); // 解析xml Map map = Xmls.toMap(xml); // 支付失败 if (!StringUtils.equals("SUCCESS", map.get("return_code")) || !StringUtils.equals("SUCCESS", map.get("result_code"))) { throw BusinessRuntimeException.getInstance("支付失败."); } orderDonService.prepayNotify(map); log.info("pc端微信支付回调修改订单状态成功"); String toWeChatXmlResponse = ""; OutputStream out = null; try { out = response.getOutputStream(); IoKit.write(toWeChatXmlResponse, out); } catch (Exception e) { throw BusinessRuntimeException.getInstance(e,e.getMessage()); } finally { IoKit.close(out); } } /** * 支付宝表单支付 * 支付宝调起支付宝表单 * 手机支付 */ @PostMapping("/post/pay/zfb") public Result aliPay(@RequestBody @Validated AlipayOrderDonReq re) throws Exception { AliPayParams aliPayParams = orderDonService.aliPay(re, ZfbProductCode.MOBILE_WEB.getProductCode(), null); // response.setContentType("text/html;charset=" + BaseZfbConfig.charset); //直接将完整的表单html输出到页面 // response.getWriter().write(aliPayParams.getBody()); // response.getWriter().flush(); // response.getWriter().close(); return GatewayResponse.SUCCESS.newBuilder().toResult(aliPayParams.getBody()); } /** * 套餐支付宝支付 */ @PostMapping("/post/pay/upgrade/zfb") public Result aliPayUpgrade(@RequestBody @Validated AlipayOrderDonReq re) throws Exception { AliPayParams aliPayParams = orderDonService.aliPayUpgrade(re, ZfbProductCode.MOBILE_WEB.getProductCode(),null); return GatewayResponse.SUCCESS.newBuilder().toResult(aliPayParams.getBody()); } /** * 支付宝web支付 * pc网页内嵌二维码 */ @PostMapping("/get/zfb/orderQrCode") public Result zfbWebQrCode(@RequestBody @Validated AlipayOrderDonReq re) throws Exception { AliPayParams aliPayParams = orderDonService.aliPay(re, ZfbProductCode.PC_WEB.getProductCode(), BaseZfbConfig.qrPayMode_orderCode); // response.setContentType("text/html;charset=" + BaseZfbConfig.charset); //直接将完整的表单html输出到页面 // response.getWriter().write(aliPayParams.getBody()); // response.getWriter().flush(); // response.getWriter().close(); return GatewayResponse.SUCCESS.newBuilder().toResult(aliPayParams.getBody()); } /** * 支付宝web支付 * pc网页内嵌二维码 */ @PostMapping("/get/zfb/upgrade/orderQrCode") public Result zfbWebQrCodeUpgrade(@RequestBody @Validated AlipayOrderDonReq re) throws Exception { AliPayParams aliPayParams = orderDonService.aliPayUpgrade(re, ZfbProductCode.PC_WEB.getProductCode(), BaseZfbConfig.qrPayMode_orderCode); // response.setContentType("text/html;charset=" + BaseZfbConfig.charset); //直接将完整的表单html输出到页面 // response.getWriter().write(aliPayParams.getBody()); // response.getWriter().flush(); // response.getWriter().close(); return GatewayResponse.SUCCESS.newBuilder().toResult(aliPayParams.getBody()); } /** * 支付宝web支付 * pc网页跳转二维码 */ @PostMapping("/get/zfb/orderRedirect") public Result zfbWebRedirectQrCode(@RequestBody @Validated AlipayOrderDonReq re) throws Exception { AliPayParams aliPayParams = orderDonService.aliPay(re, ZfbProductCode.PC_WEB.getProductCode(), BaseZfbConfig.qrPayMode_redirect); return GatewayResponse.SUCCESS.newBuilder().toResult(aliPayParams.getBody()); } /** * 支付宝回调 */ @PostMapping("/prepay/zfb/notify") public String aliPayNotify(HttpServletRequest request) throws Exception { ////将异步通知中收到的所有参数都存放到map中 Map params = convertRequestParamsToMap(request); String tradeStatus = params.get("trade_status"); String orderNo = params.get("out_trade_no"); if (AliPayTradeStatus.TRADE_SUCCESS.getStatus().equals(tradeStatus) || AliPayTradeStatus.TRADE_FINISHED.getStatus().equals(tradeStatus)) { log.info("支付宝商家订单号orderNo:{},status:{}开始回调", orderNo, tradeStatus); orderDonService.aliPayNotify(params); } else { log.error("支付宝回调 error 状态不符合 成功或完成 status:{} ,orderNo:{}", tradeStatus, orderNo); return "fail"; } return "success"; } /** * 支付宝套餐包回调 */ @PostMapping("/prepay/zfb/upgrade/notify") public String aliPayUpgradeNotify(HttpServletRequest request) throws Exception { ////将异步通知中收到的所有参数都存放到map中 Map params = convertRequestParamsToMap(request); String tradeStatus = params.get("trade_status"); String orderNo = params.get("out_trade_no"); if (AliPayTradeStatus.TRADE_SUCCESS.getStatus().equals(tradeStatus) || AliPayTradeStatus.TRADE_FINISHED.getStatus().equals(tradeStatus)) { log.info("支付宝商家订单号orderNo:{},status:{}开始回调", orderNo, tradeStatus); orderDonService.aliPayUpgradeNotify(params); } else { log.error("支付宝回调 error 状态不符合 成功或完成 status:{} ,orderNo:{}", tradeStatus, orderNo); return "fail"; } return "success"; } /** * 支付宝转账 */ // @PostMapping("/zfb/transfer/accounts") // @NoSubmit // public Result zfbTransferAccounts(@RequestBody @Validated TransferAccountsReq transferAccountsReq) throws Exception { // long userId = StpUserUtil.getLoginIdAsLong(); // transferAccountsReq.setUserId(userId); // orderDonService.transferAccounts(transferAccountsReq); // return GatewayResponse.SUCCESS.newBuilder().toResult("转账成功"); // } /** * 查询支付宝转账状态 */ @GetMapping("/zfb/transfer/status") public Result getTransFerStatusByTid(String translationId) throws Exception { AlipayFundTransCommonQueryResponse response = orderDonService.getTransFerStatusByTid(translationId); if (response.isSuccess()) { if (!Constant.SUCCESS.equals(response.getStatus())) { return GatewayResponse.SUCCESS.newBuilder().toResult(response.getFailReason()); } return GatewayResponse.SUCCESS.newBuilder().toResult("该红包已转账成功"); } return GatewayResponse.SUCCESS.newBuilder().toResult(response.getSubMsg()); } /** * 获取订单列表 */ @GetMapping("/get") public Result> list(String customId){ long userId = StpUserUtil.getLoginIdAsLong(); MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap()); //Long yhsId = yhShopFrontService.getYhsIdByCustomId(customId); List userIds = UserBindRelationService.getRelationUserIdList(userId, null); SearchResult search = beanSearcher.search(OrderDonView.class, builder //.field(OrderDonView::getYhsId, yhsId) .field(OrderDonView::getUserId, userIds).op(Operator.InList) .orderBy(OrderDonView::getId).desc() .build()); String lang = request.getHeader("lang"); search.getDataList().forEach(data->{ Integer count = availableBenefitsMapper.selectCount(Wrappers.lambdaQuery(UserPayEquipmentAvailableBenefits.class) .eq(UserPayEquipmentAvailableBenefits::getRealOrderId, data.getId()) .eq(UserPayEquipmentAvailableBenefits::getDeleted, true)); data.setIsHasBenefits(count > 0 ? true : false); if (data.getIsBenefits() != null && data.getIsBenefits()) { String benefitsList = data.getBenefitsList(); if (StrUtil.isNotBlank(benefitsList)) { try { List skuIds = Jsons.parseList(benefitsList, GoodsDonSku.class).stream().map(GoodsDonSku::getId).collect(Collectors.toList()); if (CollUtil.isNotEmpty(skuIds)) { data.setBenefitsViews(beanSearcher.searchAll(GoodsDonSkuView.class, MapUtils.builder().field(GoodsDonSkuView::getSkuId, skuIds).op(Operator.InList).build())); } } catch (Exception e) { } } } if (data.getRelationId() == 0) { if (data.getGoodsDonType() == null || data.getGoodsDonType() != 5) { data.setWaybill(waybillMapper.selectOne(Wrappers.lambdaQuery(OrderDonWaybill.class).eq(OrderDonWaybill::getOrderId, data.getId()).last("limit 1"))); } } if (data.getOrderType() == 2) { OrderDonRenewRecord orderDonRenewRecord = orderDonRenewRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonRenewRecord.class) .eq(OrderDonRenewRecord::getOrderId, data.getId()) .last("limit 1")); data.setIsRenewPackage(orderDonRenewRecord != null ? true : false); } if (lang != null && !StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) { String languagePayTitle = backInfoTranslationsFrontService.getLanguagePayTitle(data.getGoodsId(), data.getSkuId(), lang); if (StrUtil.isNotBlank(languagePayTitle)) { data.setPayTitle(languagePayTitle); } String languageSpecVal = backInfoTranslationsFrontService.getLanguageSpecVal(data.getSkuId(), lang); if (StrUtil.isNotBlank(languageSpecVal)) { data.setSpecVal(languageSpecVal); } } }); return GatewayResponse.SUCCESS.newBuilder().toResult(search); } /** * 获取订单详情 */ @GetMapping("/get/{orderId}") public Result detail(@PathVariable Long orderId, Boolean isNoLogin) { Long userId = StpUserUtil.getUserIdAfterLogin(); OrderDetailView detail = orderDonService.getDetail(orderId, userId); return GatewayResponse.SUCCESS.newBuilder().toResult(detail); } /** * 取消订单 */ @GetMapping("/get/close/{orderId}") public Result closeOrder(@PathVariable Long orderId) { long userId = StpUserUtil.getLoginIdAsLong(); orderDonService.closeOrder(orderId, userId); return GatewayResponse.SUCCESS.newBuilder().toResult(); } @GetMapping("/get/order/status/{orderId}") public Result getOrderStatusById(@PathVariable Long orderId) { if (orderId < 1) { throw BusinessRuntimeException.getInstance("订单不存在"); } OrderDonSearchView orderDonView = beanSearcher.searchFirst(OrderDonSearchView.class, MapUtils.builder() .put("orderId", String.format("where id = %s", orderId)) .build()); if (orderDonView == null) { throw BusinessRuntimeException.getInstance("订单不存在"); } if (orderDonView.getOrderType() == 2 && orderDonView.getIsMirror()) { Optional.ofNullable(orderDonRenewRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonRenewRecord.class) .eq(OrderDonRenewRecord::getOrderId, orderId) .last("limit 1"))) .ifPresent(renew -> { GoodsDonSku sku = skuMapper.selectById(renew.getOriSkuId()); orderDonView.setOriSpecVal(sku.getSpecVal()); }); } String lang = request.getHeader("lang"); if (lang != null && !StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) { String languagePayTitle = backInfoTranslationsFrontService.getLanguagePayTitle(orderDonView.getGoodsId(), orderDonView.getSkuId(), lang); if (StrUtil.isNotBlank(languagePayTitle)) { orderDonView.setPayTitle(languagePayTitle); } String languageSpecVal = backInfoTranslationsFrontService.getLanguageSpecVal(orderDonView.getSkuId(), lang); if (StrUtil.isNotBlank(languageSpecVal)) { orderDonView.setSpecVal(languageSpecVal); } String languagePayDesc = backInfoTranslationsFrontService.getLanguagePayDesc(orderDonView.getGoodsId(), lang); if (StrUtil.isNotBlank(languagePayDesc)) { orderDonView.setPayDesc(languagePayDesc); } } return GatewayResponse.SUCCESS.newBuilder().toResult(orderDonView); } /** * 查询套餐订单支付状态 */ @GetMapping("/get/upgrade/order/status/{orderId}") public Result getUpgradeOrderStatusById(@PathVariable Long orderId) { if (orderId < 1) { throw BusinessRuntimeException.getInstance("订单不存在"); } UpgradeOrderDonSearchView orderDonView = beanSearcher.searchFirst(UpgradeOrderDonSearchView.class, MapUtils.builder() .put("orderId", String.format("where id = %s", orderId)) .build()); if (orderDonView == null) { throw BusinessRuntimeException.getInstance("订单不存在"); } return GatewayResponse.SUCCESS.newBuilder().toResult(orderDonView); } @PostMapping("/get/noLogin/order") public Result> getSearchResult(@RequestBody List orderIds) { List orderDonViews = beanSearcher.searchAll(OrderDonView.class, MapUtils.builder() .field(OrderDonView::getId, orderIds).op(Operator.InList) .orderBy(OrderDonView::getId).desc().build()); return GatewayResponse.SUCCESS.newBuilder().toResult(orderDonViews); } /** * 平台评论列表 */ @GetMapping("/get/orderComment") public Result> getOrderCommentView() { SearchResult search = beanSearcher.search(OrderCommentView.class, MapUtils.flatBuilder(request.getParameterMap()).build()); return GatewayResponse.SUCCESS.newBuilder().toResult(search); } /** * 电脑端手机号注册 购买车票是否绑定了微信用户 */ @GetMapping("/isBindWx") public Result isBindWx() { Long userId = StpUserUtil.getLoginIdAsLong(); User user = userMapper.selectById(userId); if (user == null) { throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID); } if (StrUtil.isEmpty(user.getLoginPhone())) { return GatewayResponse.SUCCESS.newBuilder().toResult(true); } UserBindDetail userBindDetail = userBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class) .eq(UserBindDetail::getPhone, user.getLoginPhone())); if (userBindDetail == null || userBindDetail.getUserId() == null) { return GatewayResponse.SUCCESS.newBuilder().toResult(false); } return GatewayResponse.SUCCESS.newBuilder().toResult(true); } /** * 是否绑定了邮箱或手机号 */ @GetMapping("/isBind") public Result isBindPhoneOrEmail(@RequestParam(defaultValue = "1") Boolean fip) { Long userId = StpUserUtil.getLoginIdAsLong(); User user = userMapper.selectById(userId); if (user == null) { throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID); } //手机号注册 无需绑定 if (StrUtil.isNotEmpty(user.getLoginPhone())) { return GatewayResponse.SUCCESS.newBuilder().toResult(true); } //是否绑定了手机号 UserBindDetail userBindDetail = userBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class) .eq(StrUtil.isNotEmpty(user.getUnionid()), UserBindDetail::getUserId, userId) .eq(StrUtil.isNotEmpty(user.getEmail()), UserBindDetail::getEmailUserId, userId).last("limit 1")); if (fip) { //台湾ip String address = StringUtil.getNewInternalAddressByIp(ServletUtil.getClientIP(request)); if (address.contains("台湾") || !address.contains("中国")) { return GatewayResponse.SUCCESS.newBuilder().toResult(true); } } if (userBindDetail == null || StrUtil.isEmpty(userBindDetail.getPhone())) { return GatewayResponse.SUCCESS.newBuilder().toResult(false); } return GatewayResponse.SUCCESS.newBuilder().toResult(true); } /** * 获取支付宝回调参数 */ private static Map convertRequestParamsToMap(HttpServletRequest request) { Map retMap = new HashMap<>(); Set> entrySet = request.getParameterMap().entrySet(); for (Map.Entry entry : entrySet) { String name = entry.getKey(); String[] values = entry.getValue(); int valLen = values.length; if (valLen == 1) { retMap.put(name, values[0]); } else if (valLen > 1) { StringBuilder sb = new StringBuilder(); for (String val : values) { sb.append(",").append(val); } retMap.put(name, sb.substring(1)); } else { retMap.put(name, ""); } } return retMap; } /** * paypal支付 */ @PostMapping("/paypal/pay/{orderId}") public Result paypalPay(@PathVariable Long orderId,String successUrl) throws Exception { final String methodName = "paypal支付"; log.info("{}[start] orderId:{}",methodName,orderId); Payment payment = payPalService.createPayment(orderId,successUrl); String payUrl = "/"; log.info("paypal links:{}",payment.getLinks()); for(Links links : payment.getLinks()){ if("approval_url".equals(links.getRel())){ // 客户付款登陆地址 String payPalUrl = links.getHref(); log.info("PayPal调起支付成功[end]:{}", orderId); payUrl = payPalUrl; } } log.info("paypal支付成功[end]"); return GatewayResponse.SUCCESS.newBuilder().toResult(payUrl); } /** * stripe支付 */ @PostMapping("/stripe/pay/{orderId}") public Result stripePay(@PathVariable Long orderId,String successUrl) throws Exception { final String methodName = "stripe支付"; log.info("{}[start] orderId:{}",methodName,orderId); String payUrl = stripeService.checkOutStripe(orderId,successUrl); log.info("Stripe支付成功 result:{}[end]",payUrl); return GatewayResponse.SUCCESS.newBuilder().toResult(payUrl); } /** * paypal支付回调 */ @RequestMapping(value = "/paypal/notify") public void successPay(@RequestParam(value = "paymentId") String paymentId, @RequestParam(value = "PayerID") String PayerID) throws Exception { PaypalPayConfig paypalPayConfig = paypalPayConfigService.getById(1); response.sendRedirect(payPalService.successPayment(paymentId,PayerID,paypalPayConfig)); } /** * stripe支付回调 */ @PostMapping("/stripe/notify") @ResponseBody public String webhooks() throws Exception { InputStream inputStream = request.getInputStream(); byte[] bytes = IoKit.toBytes(inputStream); String payload = new String(bytes, StandardCharsets.UTF_8); String sigHeader = request.getHeader("Stripe-Signature"); StripePayConfig stripePayConfig = stripePayConfigService.getById(1); Event event = null; try { event = Webhook.constructEvent( payload, sigHeader, stripePayConfig.getWebhookSecret() ); } catch (JsonSyntaxException | SignatureVerificationException e) { response.setStatus(400); return ""; } // Deserialize the nested object inside the event EventDataObjectDeserializer dataObjectDeserializer = event.getDataObjectDeserializer(); StripeObject stripeObject = null; if (dataObjectDeserializer.getObject().isPresent()) { stripeObject = dataObjectDeserializer.getObject().orElse(null); } else { // Deserialization failed, probably due to an API version mismatch. // Refer to the Javadoc documentation on `EventDataObjectDeserializer` for // instructions on how to handle this case, or return an error here. } // Handle the event switch (event.getType()) { case "payment_intent.succeeded": PaymentIntent paymentIntent = (PaymentIntent) stripeObject; response.setStatus(200); break; case "charge.succeeded": //使用token支付成功回调 Charge charge = (Charge) stripeObject; //TODO 此时根据charge ID 查询出关联的订单并处理支付成功业务代码 response.setStatus(200); break; case "checkout.session.completed": //使用checkout支付成功回调 Session session = (Session) stripeObject; String clientReferenceId = session.getClientReferenceId(); if (clientReferenceId.contains("vip_")){ stripeService.fulfillOrderVip(session); }else { stripeService.fulfillOrder(session); } response.setStatus(200); break; default: response.setStatus(400); return ""; } response.setStatus(200); return ""; } /** * 余额明细 */ @GetMapping("/get/balance/detail") public Result> getUserBalanceSourceRecord() { long userId = StpUserUtil.getLoginIdAsLong(); SearchResult search = beanSearcher.search(UserBalanceSourceRecord.class, MapUtils.flatBuilder(request.getParameterMap()) .field(UserBalanceSourceRecord::getUserId, userId) .field(UserBalanceSourceRecord::getDetail).op(Operator.NotNull) .orderBy(UserBalanceSourceRecord::getId).desc() .onlySelect(UserBalanceSourceRecord::getBalance, UserBalanceSourceRecord::getDetail, UserBalanceSourceRecord::getCreatedTime) .build()); return GatewayResponse.SUCCESS.newBuilder().toResult(search); } /** * 获取套餐订单列表 */ @GetMapping("/upgrade/get") public Result> listUpgradeOrder(){ long userId = StpUserUtil.getLoginIdAsLong(); MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap()); List userIds = UserBindRelationService.getRelationUserIdList(userId, null); SearchResult search = beanSearcher.search(UpgradeOrderDonView.class, builder .field(UpgradeOrderDonView::getUserId, userIds).op(Operator.InList) .orderBy(UpgradeOrderDonView::getId).desc() .build()); return GatewayResponse.SUCCESS.newBuilder().toResult(search); } /** * 获取套餐订单详情 */ @GetMapping("/get/upgrade/{orderId}") public Result upgradeOrderDetail(@PathVariable Long orderId) { Long userId = StpUserUtil.getUserIdAfterLogin(); UpgradeOrderDetailView detail = orderDonService.getUpgradeOrderDetail(orderId, userId); return GatewayResponse.SUCCESS.newBuilder().toResult(detail); } /** * 取消套餐订单 */ @GetMapping("/get/close/upgrade/{orderId}") public Result closeUpgradeOrder(@PathVariable Long orderId) { long userId = StpUserUtil.getLoginIdAsLong(); orderDonService.closeUpgradeOrder(orderId, userId); return GatewayResponse.SUCCESS.newBuilder().toResult(); } /** * midjourney查询订单用户账号剩余次数 */ @GetMapping("/get/midjourney/user") public Result getMidjourneyUser(Long relationId) { long userId = StpUserUtil.getLoginIdAsLong(); MidjourneyUserView search = beanSearcher.searchFirst(MidjourneyUserView.class, MapUtils.flatBuilder(request.getParameterMap()) .field(MidjourneyUserView::getRelationId, relationId).build()); if (search == null) { MidjourneyUser midjourneyUser = midjourneyAccountService.getMidjourneyUserToken(userId, relationId); search = new MidjourneyUserView(); BeanUtils.copyProperties(midjourneyUser, search); } else { List upgradePackages = upgradePackageMapper.selectList(Wrappers.lambdaQuery(UpgradePackage.class).apply("JSON_CONTAINS(sku_ids,'\"" + search.getSkuId() + "\"')").eq(UpgradePackage::getStatus, Boolean.TRUE).eq(UpgradePackage::getDeleted, Boolean.TRUE)); if (CollectionUtil.isNotEmpty(upgradePackages)) { upgradePackages.stream().map(e -> e.getPrice().divide(BigDecimal.valueOf(e.getNum()), 2, RoundingMode.HALF_UP)).min(BigDecimal::compareTo).ifPresent(search::setMjPackagePrice); } } return GatewayResponse.SUCCESS.newBuilder().toResult(search); } /** * 续费升级提交支付 */ @PostMapping("/post/renew/upgrade/submit") public Result submitRenewUpgrade(@Validated @RequestBody OrderPayRequest payRequest) throws Exception { final String methodName = "续费升级吊起支付"; //无需免登录 Long userId = StpUserUtil.getLoginIdAsLong(); payRequest.setUserId(userId); log.info("{}[start] params:{}", methodName, payRequest); String ip = ServletUtil.getClientIP(request); payRequest.setIp(ip); OrderDon orderDon = orderDonService.submitRenewUpgrade(payRequest); return GatewayResponse.SUCCESS.newBuilder().toResult(orderDon); } /** * cc抵扣升级 预支付 */ @PostMapping("/cc/deduct/submit") public Result deductSubmitOrder(@RequestBody OrderPayRequest payRequest) { long userId = StpUserUtil.getLoginIdAsLong(); payRequest.setUserId(userId); OrderDon orderDon = orderDonService.ccDeductSubmitOrder(payRequest); return GatewayResponse.SUCCESS.newBuilder().toResult(orderDon); } /** * 获取续费套餐订单列表 */ @GetMapping("/renew/get") public Result> listRenewOrders(){ long userId = StpUserUtil.getLoginIdAsLong(); MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap()); List userIds = UserBindRelationService.getRelationUserIdList(userId, null); SearchResult search = beanSearcher.search(RenewUpgradeOrderDonView.class, builder .field(UpgradeOrderDonView::getUserId, userIds).op(Operator.InList) .orderBy(UpgradeOrderDonView::getId).desc() .build()); return GatewayResponse.SUCCESS.newBuilder().toResult(search); } /** * luma查询订单用户账号剩余次数 */ @GetMapping("/get/luma/user") public Result getLumaUser(Long relationId) { long userId = StpUserUtil.getLoginIdAsLong(); LumaUserView search = beanSearcher.searchFirst(LumaUserView.class, MapUtils.flatBuilder(request.getParameterMap()) .field(LumaUserView::getUserId, userId).field(LumaUserView::getRelationId, relationId).build()); if (search == null) { LumaUser lumaUser = lumaService.getLumaUser(userId, relationId); search = new LumaUserView(); BeanUtils.copyProperties(lumaUser, search); } return GatewayResponse.SUCCESS.newBuilder().toResult(search); } /** * 用户续费订单列表 */ @GetMapping("/get/renew/order") public Result> getRenewOrder(Long relationId) { long userId = StpUserUtil.getLoginIdAsLong(); MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap()); if (relationId != null) { builder.field(OrderDonView::getRelationId, relationId); } GroupsRelation relation = relationMapper.selectById(relationId); if (relation == null) { return GatewayResponse.SUCCESS.newBuilder().toResult(); } List userIds = UserBindRelationService.getRelationUserIdList(userId, null); List list = beanSearcher.searchAll(OrderDonView.class, builder .field(OrderDonView::getUserId, userIds).op(Operator.InList) .field(OrderDonView::getOrderType, 2) .field(OrderDonView::getCreatedTime, relation.getStartTime()).op(Operator.GreaterThan) .orderBy(OrderDonView::getId).desc() .build()); return GatewayResponse.SUCCESS.newBuilder().toResult(list); } /** * 用户权益预支付 */ @PostMapping("/user/benefits/submit") public Result userBenefitsSubmit(@RequestBody OrderPayRequest orderPayRequest) throws Exception { long userId = StpUserUtil.getLoginIdAsLong(); orderPayRequest.setUserId(userId); String ip = ServletUtil.getClientIP(request); orderPayRequest.setIp(ip); OrderDon orderDon = orderDonService.userBenefitsSubmit(orderPayRequest); return GatewayResponse.SUCCESS.newBuilder().toResult(orderDon); } /** * 是否是实物可选多张车票权益记录 */ @GetMapping("/get/combo/optional/ticket/record/{orderId}") public Result getComboOptionalTicketRecord(@PathVariable Long orderId) { long userId = StpUserUtil.getLoginIdAsLong(); UserPayEquipmentAvailableBenefits userPayEquipmentAvailableBenefits = orderDonService.getComboOptionalTicketRecord(userId, orderId); return GatewayResponse.SUCCESS.newBuilder().toResult(userPayEquipmentAvailableBenefits); } /** * 是否购买过实物设备 */ @GetMapping("/has/paid/equipment") public Result hasPaidEquipment() { long userId = StpUserUtil.getLoginIdAsLong(); List userIdList = userBindRelationService.getRelationUserIdList(userId, null); //是否买过设备 Integer selectCount = orderDonService.count(Wrappers.lambdaQuery(OrderDon.class) .eq(OrderDon::getGoodsId, 15) .in(OrderDon::getUserId, userIdList) .notIn(OrderDon::getStatus, Constant.noOrderAllStatus)); return GatewayResponse.SUCCESS.newBuilder().toResult(selectCount > 0); } /** * paypalV2支付 */ @PostMapping("/paypalV2/pay/{orderId}") public Result paypalV2Pay(@PathVariable Long orderId,String successUrl) throws Exception { final String methodName = "paypal支付"; log.info("{}[start] orderId:{}",methodName,orderId); String payUrl = paypalV2Service.createPayment(orderId,successUrl); log.info("paypal links:{}",payUrl); log.info("paypal支付成功[end]"); return GatewayResponse.SUCCESS.newBuilder().toResult(payUrl); } /** * paypal支付回调 */ @RequestMapping(value = "/paypalV2/notify") public void successV2Pay(@RequestParam(value = "token") String token, @RequestParam(value = "PayerID") String PayerID) throws Exception { PaypalPayConfig paypalPayConfig = paypalPayConfigService.getById(1); response.sendRedirect(paypalV2Service.successPayment(token,PayerID,paypalPayConfig)); } /** * 领取GPT镜像天卡 */ @PostMapping("/receive/gptMirror/dayCard/{orderId}") public Result receiveGptMirrorDayCard(@PathVariable Long orderId) throws Exception { orderDonService.receiveGptMirrorDayCard(orderId); return GatewayResponse.SUCCESS.newBuilder().toResult(); } /** * 是否购买过AI订单 */ @GetMapping("/get/payAiOrders/condition") public Result getPayAiOrdersConditions() { long userId = StpUserUtil.getLoginIdAsLong(); Integer selectCount = orderDonMapper.hasPaymentAiGoods(userId); return GatewayResponse.SUCCESS.newBuilder().toResult(selectCount > 0); } }