zoujiajian 1 anno fa
parent
commit
c8720903fe

+ 5 - 0
netflix-common/src/main/java/com/cyksj/common/constant/Constant.java

@@ -589,4 +589,9 @@ public interface Constant {
 	 * VIP用户费用
 	 */
 	String VIP_FEE_KEY = "vip_fee_key";
+
+	/**
+	 * VIP title
+	 */
+	String VIP_TITLE = "银河超级AI会员";
 }

+ 4 - 0
netflix-service/src/main/java/com/cyksj/config/zfb/BaseZfbConfig.java

@@ -42,12 +42,16 @@ public class BaseZfbConfig {
 
 	public static String zfb_register_login_return_url = "yinhe/web/registerTicket";
 
+	public static String zfb_vip_login_return_url = "AIMirror";
+
 	public static String notifyUrl = "applets/order/prepay/zfb/notify";
 
 	public static String upgradeNotifyUrl = "applets/order/prepay/zfb/upgrade/notify";
 
 	public static String zfb_register_notify_url = "applets/register/prepay/zfb/notify";
 
+	public static String zfb_vip_notify_url = "/applet/vip/orders/zfb/notify";
+
 	public static String wholesaleNotifyUrl = "applet/wholesale/zfb/notify";
 
 	public static String wholesaleDepositNotifyUrl = "applet/wholesale/deposit/zfb/notify";

+ 8 - 0
netflix-service/src/main/java/com/cyksj/service/order/VipOrderDonService.java

@@ -1,9 +1,13 @@
 package com.cyksj.service.order;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.dto.AliPayParams;
 import com.cyksj.model.entity.VipOrderDon;
+import com.cyksj.model.request.AlipayOrderDonReq;
 import com.cyksj.model.request.VipOrderDonPayReq;
 
+import java.util.Map;
+
 /**
  * 项目名: yhlxj2
  * 文件名: VipOrderDonService
@@ -12,4 +16,8 @@ import com.cyksj.model.request.VipOrderDonPayReq;
  */
 public interface VipOrderDonService extends IService<VipOrderDon> {
 	VipOrderDon submit(VipOrderDonPayReq payRequest);
+
+	AliPayParams aliPay(AlipayOrderDonReq re) throws Exception;
+
+	void aliPayNotify(Map<String, String> params) throws Exception;
 }

+ 76 - 1
netflix-service/src/main/java/com/cyksj/service/order/impl/VipOrderDonServiceImpl.java

@@ -1,31 +1,47 @@
 package com.cyksj.service.order.impl;
 
 import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.StrUtil;
+import com.alipay.api.internal.util.AlipaySignature;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.snowflake.Sequence;
+import com.cyksj.common.util.Codec;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.config.zfb.BaseZfbConfig;
+import com.cyksj.config.zfb.ZfbProductCode;
 import com.cyksj.enums.GatewayApiCode;
 import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.channel.ShopConfigMapper;
 import com.cyksj.mapper.sys.SysConfigMapper;
 import com.cyksj.mapper.vip.VipGoodsSkuMapper;
 import com.cyksj.mapper.vip.VipOrderDonMapper;
+import com.cyksj.model.dto.AliPayParams;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.views.GroupsRelationView;
+import com.cyksj.model.request.AlipayOrderDonReq;
+import com.cyksj.model.request.OrderAttach;
 import com.cyksj.model.request.VipOrderDonPayReq;
 import com.cyksj.service.order.VipOrderDonService;
+import com.cyksj.service.pay.AliPayCommonService;
 import com.cyksj.service.user.UserBenefitsService;
 import com.cyksj.service.user.UserBindRelationService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.param.Operator;
 import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
+import java.util.Date;
 import java.util.List;
+import java.util.Map;
+import java.util.Optional;
 
 /**
  * 项目名: yhlxj2
@@ -35,6 +51,7 @@ import java.util.List;
  */
 @Service
 @RequiredArgsConstructor
+@Slf4j
 public class VipOrderDonServiceImpl extends ServiceImpl<VipOrderDonMapper, VipOrderDon> implements VipOrderDonService {
 	private static final Sequence SEQUENCE = new Sequence(0);
 
@@ -50,6 +67,10 @@ public class VipOrderDonServiceImpl extends ServiceImpl<VipOrderDonMapper, VipOr
 
 	private final SysConfigMapper sysConfigMapper;
 
+	private final AliPayCommonService aliPayCommonService;
+
+	private final ShopConfigMapper shopConfigMapper;
+
 	@Override
 	public VipOrderDon submit(VipOrderDonPayReq payRequest) {
 		Long userId = payRequest.getUserId();
@@ -75,7 +96,7 @@ public class VipOrderDonServiceImpl extends ServiceImpl<VipOrderDonMapper, VipOr
 		//扣除使用优惠券、余额的订单金额
 		deductOrderMoney(orderDon, user, payRequest);
 		//设置订单支付商品信息
-		orderDon.setPayTitle("银河超级AI会员");
+		orderDon.setPayTitle(Constant.VIP_TITLE);
 		this.saveOrUpdate(orderDon);
 
 		Long orderId = orderDon.getId();
@@ -87,6 +108,60 @@ public class VipOrderDonServiceImpl extends ServiceImpl<VipOrderDonMapper, VipOr
 		return orderDon;
 	}
 
+	@Override
+	public AliPayParams aliPay(AlipayOrderDonReq re) throws Exception {
+		String productCode = StrUtil.EMPTY;
+		if (re.getType() == 1) {
+			productCode = ZfbProductCode.MOBILE_WEB.getProductCode();
+		}
+		if (re.getType() == 2) {
+			productCode = ZfbProductCode.PC_WEB.getProductCode();
+		}
+		return aliPayCommonService.unifiedPayVip(re.getOrderId(), productCode, re.getPayMode(), re.getReturnUrl());
+	}
+
+	@Override
+	public void aliPayNotify(Map<String, String> params) throws Exception {
+		//调用SDK验证签名
+		String body = Codec.DoBase64.custom().setData(params.get("body")).decodeAsText();
+		OrderAttach orderAttach = Jsons.parseObject(body, OrderAttach.class);
+		Long oderId = orderAttach.getO();
+		VipOrderDon orderDon = this.getById(oderId);
+		if (null == orderDon) {
+			throw BusinessRuntimeException.getInstance("订单不存在.");
+		}
+		if (orderDon.getPopularizeId() == null) {
+			orderDon.setShopId(null);
+		}
+		String appId = params.get("app_id");
+		boolean signVerified = AlipaySignature.rsaCheckV1(params, shopConfigMapper.getByAppId(appId).getPublicKey(), BaseZfbConfig.charset, BaseZfbConfig.signType);
+		if (!signVerified) {
+			log.error("支付宝回调校验签名错误,自定义入参:{}", params.get("body"));
+			throw BusinessRuntimeException.getInstance("支付宝回调校验签名错误");
+		}
+		String transactionId = params.get("trade_no");
+		String payTimeStr = params.get("gmt_payment");
+		//买家支付宝账号
+		String buyerId = Optional.ofNullable(params.get("buyer_id")).orElse(params.get("buyer_open_id"));
+		log.info("支付宝回调信息:{}", Jsons.toJson(params));
+		if (!orderDon.getStatus().equals(OrderDon.Status.noPayment) && !orderDon.getStatus().equals(OrderDon.Status.close)) {
+			log.info("支付宝已回调,重复修改状态 id:{}", orderDon.getId());
+			return;
+		}
+		Date payTime = DateTime.now();
+		if (StringUtils.isNotBlank(payTimeStr)) {
+			payTime = DateUtil.parse(payTimeStr, "yyyy-MM-dd HH:mm:ss");
+		}
+		// 更改订单状态
+		orderDon.setTransactionId(transactionId);
+		orderDon.setPayTime(payTime);
+		orderDon.setShopId(appId);
+		orderDon.setType(VipOrderDon.Type.ALI_PAY);
+		orderDon.setBuyerId(buyerId);
+		//回调
+		unifiedHandlerOrderNotify(orderDon);
+	}
+
 	private void unifiedHandlerOrderNotify(VipOrderDon orderDon) {
 		orderDon.setStatus(VipOrderDon.Status.complete);
 		this.updateById(orderDon);

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/pay/AliPayCommonService.java

@@ -30,4 +30,6 @@ public interface AliPayCommonService {
 	AliPayParams openShopAliPay(AlipayOrderDonReq re, String productCode, String qrPayMode) throws Exception;
 
 	AliPayParams aliPaySpotifyUpgrade(AlipayOrderDonReq re, String productCode, String qrPayMode) throws Exception;
+
+	AliPayParams unifiedPayVip(Long orderId, String productCode, String payMode, String returnUrl) throws Exception;
 }

+ 36 - 0
netflix-service/src/main/java/com/cyksj/service/pay/impl/AliPayCommonServiceImpl.java

@@ -28,6 +28,7 @@ import com.cyksj.mapper.*;
 import com.cyksj.mapper.channel.ShopConfigMapper;
 import com.cyksj.mapper.mirrorshop.UserMirrorShopFeeOrderDonMapper;
 import com.cyksj.mapper.order.OrderDonPostMapper;
+import com.cyksj.mapper.vip.VipOrderDonMapper;
 import com.cyksj.model.dto.AliPayParams;
 import com.cyksj.model.dto.OrderPayBuilderDto;
 import com.cyksj.model.entity.*;
@@ -88,6 +89,8 @@ public class AliPayCommonServiceImpl implements AliPayCommonService {
 
 	private final SpotifyUserUpgradeOrderMapper spotifyUserUpgradeOrderMapper;
 
+	private final VipOrderDonMapper vipOrderDonMapper;
+
 	private static final Sequence SEQUENCE = new Sequence(0);
 
 	@Override
@@ -547,6 +550,39 @@ public class AliPayCommonServiceImpl implements AliPayCommonService {
 				returnUrl);
 	}
 
+	@Override
+	public AliPayParams unifiedPayVip(Long orderId, String productCode, String payMode, String returnUrl) throws Exception {
+		VipOrderDon orderDon = vipOrderDonMapper.selectById(orderId);
+		Assert.notNull(orderDon, "订单不存在");
+		if (StrUtil.isEmpty(productCode)) throw BusinessRuntimeException.getInstance("支付异常");
+		//获取支付宝默认商户
+		String shopId = sysConfigService.getDefaultShopConfigByType("zfb");
+		orderDon.setShopId(shopId);
+		orderDon.setType(VipOrderDon.Type.ALI_PAY);
+		if (orderDon.getType() != VipOrderDon.Type.ALI_PAY) {
+			orderDon.setType(VipOrderDon.Type.ALI_PAY);
+		}
+		vipOrderDonMapper.updateById(orderDon);
+		//回调地址
+		String host = envCommonService.getNotifyHost();
+		String notifyUrl = String.format("%s%s", host, BaseZfbConfig.zfb_vip_notify_url);
+		if (ZfbProductCode.MOBILE_WEB.getProductCode().equals(productCode) && BaseZfbConfig.qrPayMode_redirect.equals(payMode)) {
+			returnUrl = String.format("%s%s", envCommonService.getDomain(), BaseZfbConfig.zfb_vip_login_return_url);
+		}
+		String subject = orderDon.getPayTitle();
+		AliPayParams aliPayParams = builderPayParams(orderDon.getId(),
+				orderDon.getOrderNo(),
+				orderDon.getShopId(),
+				orderDon.getMoney(),
+				orderDon.getCreatedTime(),
+				subject,
+				productCode,
+				payMode,
+				notifyUrl,
+				returnUrl);
+		return aliPayParams;
+	}
+
 	public String getZfbDayLimitShopId(OrderDon orderDon) {
 		String appId = orderDon.getShopId();
 		if (orderDon.getPopularizeId() != null) {

+ 56 - 6
netflix-web/src/main/java/com/cyksj/web/controller/vip/VipUserOrderController.java

@@ -5,8 +5,11 @@ import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.StringUtil;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.dto.AliPayParams;
 import com.cyksj.model.entity.VipOrderDon;
+import com.cyksj.model.request.AlipayOrderDonReq;
 import com.cyksj.model.request.VipOrderDonPayReq;
+import com.cyksj.model.response.AliPayTradeStatus;
 import com.cyksj.service.order.VipOrderDonService;
 import com.cyksj.web.util.StpUserUtil;
 import lombok.RequiredArgsConstructor;
@@ -18,6 +21,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * 项目名: yhlxj2
@@ -37,11 +43,6 @@ public class VipUserOrderController {
 	/**
 	 * 会员预下单
 	 */
-	/**
-	 * 支付
-	 * @author chan
-	 * @date 2021-10-11 下午4:56
-	 */
 	@PostMapping("/post/submit")
 	public Result<VipOrderDon> submit(@Validated @RequestBody VipOrderDonPayReq payRequest) throws Exception {
 		final String methodName = "吊起会员预支付";
@@ -61,6 +62,55 @@ public class VipUserOrderController {
 
 
 	/**
-	 * 会员支付宝支付
+	 * 支付宝支付
 	 */
+	@PostMapping("/post/pay/zfb")
+	public Result<String> aliPay(@RequestBody @Validated AlipayOrderDonReq re) throws Exception {
+		AliPayParams aliPayParams = vipOrderDonService.aliPay(re);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(aliPayParams.getBody());
+	}
+
+	/**
+	 * 支付宝回调
+	 */
+	@PostMapping("/zfb/notify")
+	public String aliPayNotify(@RequestBody @Validated AlipayOrderDonReq re) throws Exception {
+		////将异步通知中收到的所有参数都存放到map中
+		Map<String, String> 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);
+			vipOrderDonService.aliPayNotify(params);
+		} else {
+			log.error("支付宝回调 error 状态不符合 成功或完成 status:{} ,orderNo:{}", tradeStatus, orderNo);
+			return "fail";
+		}
+		return "success";
+	}
+
+	/**
+	 * 获取支付宝回调参数
+	 */
+	private static Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
+		Map<String, String> retMap = new HashMap<>();
+		Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();
+		for (Map.Entry<String, String[]> 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;
+	}
 }