Browse Source

Merge branch 'distribute_transfer_accounts'

# Conflicts:
#	netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
#	netflix-service/src/main/java/com/cyksj/service/gzh/factory/EventMsgService.java
#	netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
#	netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java
#	netflix-web/src/main/java/com/cyksj/web/controller/user/DistributePopularizeController.java
zoujiajian 3 năm trước cách đây
mục cha
commit
17a47542fc
20 tập tin đã thay đổi với 465 bổ sung111 xóa
  1. 2 0
      .gitignore
  2. 1 1
      netflix-common/pom.xml
  3. 2 0
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  4. 33 0
      netflix-common/src/main/java/com/cyksj/common/constant/TransferConstant.java
  5. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/TransferAccountsRecordMapper.java
  6. 11 1
      netflix-dao/src/main/java/com/cyksj/model/entity/ShopConfig.java
  7. 68 0
      netflix-dao/src/main/java/com/cyksj/model/entity/TransferAccountsRecord.java
  8. 50 0
      netflix-dao/src/main/java/com/cyksj/model/request/TransferAccountsReq.java
  9. 0 35
      netflix-service/src/main/java/com/cyksj/common/AliPayCommon.java
  10. 93 0
      netflix-service/src/main/java/com/cyksj/config/zfb/AliPayClientFactory.java
  11. 0 51
      netflix-service/src/main/java/com/cyksj/config/zfb/ZfbConfig.java
  12. 2 0
      netflix-service/src/main/java/com/cyksj/config/zfb/ZfbProductCode.java
  13. 1 1
      netflix-service/src/main/java/com/cyksj/service/mail/MailService.java
  14. 2 2
      netflix-service/src/main/java/com/cyksj/service/mail/impl/MailServiceImpl.java
  15. 13 0
      netflix-service/src/main/java/com/cyksj/service/order/OrderDonService.java
  16. 105 15
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  17. 0 1
      netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsOrderController.java
  18. 29 0
      netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java
  19. 1 1
      netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java
  20. 39 3
      netflix-web/src/main/java/com/cyksj/web/controller/user/DistributePopularizeController.java

+ 2 - 0
.gitignore

@@ -45,3 +45,5 @@ buildNumber.properties
 mvnw
 mvnw.cmd
 
+cert/
+

+ 1 - 1
netflix-common/pom.xml

@@ -79,7 +79,7 @@
         <dependency>
             <groupId>com.alipay.sdk</groupId>
             <artifactId>alipay-sdk-java</artifactId>
-            <version>4.34.22.ALL</version>
+            <version>4.35.65.ALL</version>
         </dependency>
 
         <dependency>

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

@@ -72,4 +72,6 @@ public interface Constant {
 	List<String> payType = List.of("月", "季", "年");
 
 	List<String> registerAccount = List.of("apple", "spotify", "google");
+
+	String SUCCESS = "success";
 }

+ 33 - 0
netflix-common/src/main/java/com/cyksj/common/constant/TransferConstant.java

@@ -0,0 +1,33 @@
+package com.cyksj.common.constant;
+
+/*
+ *项目名: netflix
+ *文件名: TransferConstant
+ *创建者: JavaZou
+ *创建时间:2023/2/28 12:03
+ */
+public interface TransferConstant {
+
+	String ALIPAY = "alipay";
+
+	String WECHAT_PAY = "wechat";
+
+	/**
+	 * biz_scene
+	 * DIRECT_TRANSFER:单笔无密转账到支付宝,B2C现金红包;
+	 * PERSONAL_COLLECTION:C2C现金红包-领红包
+	 */
+	String DIRECT_TRANSFER = "DIRECT_TRANSFER";
+
+	String PERSONAL_COLLECTION = "PERSONAL_COLLECTION";
+
+	String RED_PACKET = "REDPACKET";
+
+	/**
+	 * 传入的扩展参数如下:
+	 * sub_biz_scene 子业务场景,红包业务必传,取值REDPACKET,C2C现金红包、B2C现金红包均需传入
+	 */
+	String SUB_BIZ_SCENE = "SUB_BIZ_SCENE";
+
+	String ALIPAY_LOGON_ID = "ALIPAY_LOGON_ID";
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/TransferAccountsRecordMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.TransferAccountsRecord;
+
+/*
+ *项目名: netflix
+ *文件名: TransferAccountsRecordMapper
+ *创建者: JavaZou
+ *创建时间:2023/2/28 11:42
+ */
+public interface TransferAccountsRecordMapper extends BaseMapper<TransferAccountsRecord> {
+}

+ 11 - 1
netflix-dao/src/main/java/com/cyksj/model/entity/ShopConfig.java

@@ -16,7 +16,12 @@ public class ShopConfig extends BaseEntity{
     /**
      * 品如支付宝商户
      */
-    public static final String ZFB_DEFAULT_APP_ID = "2021003159660212";
+    public static final String ZFB_DEFAULT_APP_ID = "2021003173606268";
+
+    /**
+     * 分销提现支付宝默认商户
+     */
+    public static final String DISTRIBUTE_ZFB_DEFAULT_APP_ID = "2021003159660212";
 
     public static final String WX_DEFAULT_APP_ID = "1634772026";
 
@@ -58,4 +63,9 @@ public class ShopConfig extends BaseEntity{
     @DbIgnore
     @TableField(exist = false)
     private Integer channelCount;
+
+    /***
+     * 是否需要携带证书
+     */
+    private Boolean isCert;
 }

+ 68 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/TransferAccountsRecord.java

@@ -0,0 +1,68 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: TransferAccountsRecord
+ *创建者: JavaZou
+ *创建时间:2023/2/28 11:36
+ */
+@Getter
+@Setter
+public class TransferAccountsRecord extends BaseEntity{
+	private Long userId;
+
+	/**
+	 * 商户转账订单号
+	 */
+	private String transferOutNo;
+
+	/**
+	 * 支付宝转账订单号
+	 */
+	private String transactionId;
+
+	/**
+	 * 转账账户
+	 */
+	private String account;
+
+	/**
+	 * 转账用户真实姓名
+	 */
+	private String name;
+
+	private BigDecimal money;
+
+	/**
+	 * 分销积分
+	 */
+	private BigDecimal points;
+
+	/**
+	 * 转账类型 默认支付宝AliPay
+	 */
+	private String type;
+
+	/**
+	 * 1:默认分销作用
+	 */
+	private Integer scope;
+
+	/**
+	 * 1成功,0失败
+	 */
+	private Integer status;
+
+	private String errorMsg;
+
+	/**
+	 * 转账日期
+	 */
+	private Date transferTime;
+}

+ 50 - 0
netflix-dao/src/main/java/com/cyksj/model/request/TransferAccountsReq.java

@@ -0,0 +1,50 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+
+/*
+ *项目名: netflix
+ *文件名: TransferAccountsReq
+ *创建者: JavaZou
+ *创建时间:2023/2/28 10:09
+ */
+@Getter
+@Setter
+public class TransferAccountsReq {
+	/**
+	 * 转账金额
+	 */
+	@NotNull
+	private BigDecimal money;
+
+	/**
+	 * 转账账户
+	 */
+	@NotNull
+	private String account;
+
+	/**
+	 * 转账账户真实姓名
+	 */
+	@NotEmpty
+	private String name;
+
+	/**
+	 * alipay、wechat
+	 */
+	private String type;
+
+	private BigDecimal points;
+
+	/**
+	 * 默认1分销作用
+	 */
+	private Integer scope;
+
+	private Long userId;
+}

+ 0 - 35
netflix-service/src/main/java/com/cyksj/common/AliPayCommon.java

@@ -1,35 +0,0 @@
-package com.cyksj.common;
-
-import com.alipay.api.AlipayApiException;
-import com.alipay.api.AlipayClient;
-import com.alipay.api.AlipayConfig;
-import com.alipay.api.DefaultAlipayClient;
-import com.cyksj.config.zfb.BaseZfbConfig;
-import com.cyksj.config.zfb.ZfbConfig;
-import com.cyksj.model.entity.ShopConfig;
-
-/*
- *项目名: netflix
- *文件名: AliPayCommon
- *创建者: JavaZou
- *创建时间:2022/11/9 14:07
- */
-public class AliPayCommon {
-
-	/**
-	 * 获取ALI支付客户端
-	 */
-	public static AlipayClient getAlipayClient(ShopConfig config) throws AlipayApiException {
-		AlipayConfig alipayConfig = new AlipayConfig();
-		//网关地址
-		alipayConfig.setServerUrl(BaseZfbConfig.url);
-		alipayConfig.setAppId(config.getAppId());
-		alipayConfig.setPrivateKey(config.getAppPrivateKey());
-		alipayConfig.setFormat(BaseZfbConfig.format);
-		alipayConfig.setCharset(BaseZfbConfig.charset);
-		alipayConfig.setSignType(BaseZfbConfig.signType);
-		alipayConfig.setAlipayPublicKey(config.getPublicKey());
-		AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig);
-		return alipayClient;
-	}
-}

+ 93 - 0
netflix-service/src/main/java/com/cyksj/config/zfb/AliPayClientFactory.java

@@ -0,0 +1,93 @@
+package com.cyksj.config.zfb;
+
+import com.alipay.api.AlipayClient;
+import com.alipay.api.AlipayConfig;
+import com.alipay.api.DefaultAlipayClient;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.mapper.channel.ShopConfigMapper;
+import com.cyksj.model.entity.ShopConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/*
+ *项目名: netflix
+ *文件名: AliPayClientFactory
+ *创建者: JavaZou
+ *创建时间:2022/11/2 11:18
+ */
+@Component
+public class AliPayClientFactory {
+	/**
+	 * 支付宝证书路径
+	 */
+	private static final String ALIPAY_CERT_PATH = "cert/alipay";
+
+	/**
+	 * 应用公钥证书名字
+	 */
+	private static final String ALIPAY_APP_PUBLIC_CERT_NAME = "appCertPublicKey.crt";
+
+	/**
+	 * 支付宝公钥证书名字
+	 */
+	private static final String ALIPAY_PUBLIC_CERT_NAME = "alipayCertPublicKey_RSA2.crt";
+
+	/**
+	 * 支付宝根证书名字
+	 */
+	private static final String ALIPAY_ROOT_CERT_NAME = "alipayRootCert.crt";
+
+	private static Map<String, AlipayClient> alipayClientMap = new ConcurrentHashMap<>();
+
+	@Autowired
+	private ShopConfigMapper shopConfigMapper;
+
+	/**
+	 * 初始化
+	 */
+	@PostConstruct
+	public void initAliPayClient() {
+		List<ShopConfig> zfbShopConfig = shopConfigMapper.selectList(Wrappers.lambdaQuery(ShopConfig.class)
+				.eq(ShopConfig::getType, "zfb"));
+		zfbShopConfig.forEach(config -> {
+			AlipayConfig alipayConfig = new AlipayConfig();
+			//网关地址
+			alipayConfig.setServerUrl(BaseZfbConfig.url);
+			alipayConfig.setAppId(config.getAppId());
+			alipayConfig.setPrivateKey(config.getAppPrivateKey());
+			alipayConfig.setFormat(BaseZfbConfig.format);
+			alipayConfig.setCharset(BaseZfbConfig.charset);
+			alipayConfig.setSignType(BaseZfbConfig.signType);
+			if (config.getIsCert()) {
+				String shopId = config.getAppId();
+				// 设置应用公钥证书路径
+				alipayConfig.setAppCertPath(String.format("%s/%s/%s", ALIPAY_CERT_PATH, shopId, ALIPAY_APP_PUBLIC_CERT_NAME));
+				// 设置支付宝公钥证书路径
+				alipayConfig.setAlipayPublicCertPath(String.format("%s/%s/%s", ALIPAY_CERT_PATH, shopId, ALIPAY_PUBLIC_CERT_NAME));
+				// 设置支付宝根证书路径
+				alipayConfig.setRootCertPath(String.format("%s/%s/%s", ALIPAY_CERT_PATH, shopId, ALIPAY_ROOT_CERT_NAME));
+			}
+			AlipayClient alipayClient = null;
+			try {
+				alipayClient = new DefaultAlipayClient(alipayConfig);
+			} catch (Exception e) {
+				return;
+			}
+			alipayClientMap.putIfAbsent(config.getAppId(), alipayClient);
+		});
+	}
+
+	public static AlipayClient getAlipayClient(String shopId) {
+		AlipayClient alipayClient = alipayClientMap.get(shopId);
+		if (alipayClient == null) {
+			throw BusinessRuntimeException.getInstance("未配置该支付宝商户");
+		}
+		return alipayClient;
+	}
+}

+ 0 - 51
netflix-service/src/main/java/com/cyksj/config/zfb/ZfbConfig.java

@@ -1,51 +0,0 @@
-package com.cyksj.config.zfb;
-
-import lombok.Getter;
-
-/*
- *项目名: netflix
- *文件名: YHLXZfbConfig
- *创建者: JavaZou
- *创建时间:2022/11/2 11:18
- */
-@Getter
-public enum ZfbConfig {
-	YHLX_ZfB("银河录像支付宝",
-			"2021003159660212",
-			"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"),
-	;
-	/**
-	 * 描述
-	 */
-	private String desc;
-
-	/**
-	 * appid 即创建应用后生成。
-	 */
-	private String appId;
-
-	/**
-	 * 支付宝公钥
-	 */
-	private String alipayPublicKey;
-
-	/**
-	 * 应用公钥
-	 */
-	public String aliAppPublicKey;
-
-	/**
-	 * 开发者私钥,由开发者自己生成
-	 */
-	private String privateKey;
-
-	ZfbConfig(String desc, String appId, String alipayPublicKey, String aliAppPublicKey, String privateKey) {
-		this.desc = desc;
-		this.appId = appId;
-		this.alipayPublicKey = alipayPublicKey;
-		this.aliAppPublicKey = aliAppPublicKey;
-		this.privateKey = privateKey;
-	}
-}

+ 2 - 0
netflix-service/src/main/java/com/cyksj/config/zfb/ZfbProductCode.java

@@ -12,6 +12,8 @@ import lombok.Getter;
 public enum ZfbProductCode {
 	MOBILE_WEB("支付宝手机网页支付", "QUICK_WAP_PAY"),
 	PC_WEB("支付宝电脑网站支付", "FAST_INSTANT_TRADE_PAY"),
+	TRANS_ACCOUNT_NO_PWD("单笔无密转账到固定支付宝账户", "TRANS_ACCOUNT_NO_PWD"),
+	STD_RED_PACKET("支付宝红包转账", "STD_RED_PACKET"),
 	;
 	String desc;
 	String productCode;

+ 1 - 1
netflix-web/src/main/java/com/cyksj/web/controller/mail/MailService.java → netflix-service/src/main/java/com/cyksj/service/mail/MailService.java

@@ -1,4 +1,4 @@
-package com.cyksj.web.controller.mail;
+package com.cyksj.service.mail;
 
 /*
  *项目名: netflix

+ 2 - 2
netflix-web/src/main/java/com/cyksj/web/controller/mail/impl/MailServiceImpl.java → netflix-service/src/main/java/com/cyksj/service/mail/impl/MailServiceImpl.java

@@ -1,8 +1,8 @@
-package com.cyksj.web.controller.mail.impl;
+package com.cyksj.service.mail.impl;
 
 import com.cyksj.common.util.StringUtil;
 import com.cyksj.redis.RedisService;
-import com.cyksj.web.controller.mail.MailService;
+import com.cyksj.service.mail.MailService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;

+ 13 - 0
netflix-service/src/main/java/com/cyksj/service/order/OrderDonService.java

@@ -1,5 +1,7 @@
 package com.cyksj.service.order;
 
+import com.alipay.api.AlipayResponse;
+import com.alipay.api.response.AlipayFundTransCommonQueryResponse;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.cyksj.dto.Result;
 import com.cyksj.model.dto.AliPayParams;
@@ -8,6 +10,7 @@ import com.cyksj.model.entity.OrderDon;
 import com.cyksj.model.entity.RealGoodsInterestUser;
 import com.cyksj.model.manage.views.OrderDonView;
 import com.cyksj.model.request.OrderPayRequest;
+import com.cyksj.model.request.TransferAccountsReq;
 import com.cyksj.model.request.WxOrderRefundReq;
 import com.cyksj.model.request.ZfbOrderRefundReq;
 
@@ -81,4 +84,14 @@ public interface OrderDonService extends IService<OrderDon> {
     void updateHasPaymentInterestRealGoodsPayTime();
 
     void saveTransport(Long addressId, Long orderId);
+
+    /**
+     * 支付宝红包转账
+     */
+    AlipayResponse transferAccounts(TransferAccountsReq transferAccountsReq) throws Exception;
+
+    /**
+     * 查询支付宝转账状态
+     */
+    AlipayFundTransCommonQueryResponse getTransFerStatusByTid(String translationId) throws Exception;
 }

+ 105 - 15
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -4,23 +4,22 @@ import cn.hutool.core.date.DateField;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONObject;
 import com.alipay.api.AlipayApiException;
 import com.alipay.api.AlipayClient;
 import com.alipay.api.AlipayRequest;
-import com.alipay.api.domain.AlipayTradePagePayModel;
-import com.alipay.api.domain.AlipayTradeRefundModel;
-import com.alipay.api.domain.AlipayTradeWapPayModel;
+import com.alipay.api.AlipayResponse;
+import com.alipay.api.domain.*;
 import com.alipay.api.internal.util.AlipaySignature;
-import com.alipay.api.request.AlipayTradePagePayRequest;
-import com.alipay.api.request.AlipayTradeRefundRequest;
-import com.alipay.api.request.AlipayTradeWapPayRequest;
+import com.alipay.api.request.*;
+import com.alipay.api.response.AlipayFundTransCommonQueryResponse;
 import com.alipay.api.response.AlipayTradeRefundResponse;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.cyksj.common.AliPayCommon;
 import com.cyksj.common.EnvCommonService;
 import com.cyksj.common.constant.Constant;
 import com.cyksj.common.constant.TaskTypeEnum;
+import com.cyksj.common.constant.TransferConstant;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.snowflake.Sequence;
 import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
@@ -28,6 +27,7 @@ import com.cyksj.common.util.Codec;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.common.util.Xmls;
 import com.cyksj.config.WeChatConfig;
+import com.cyksj.config.zfb.AliPayClientFactory;
 import com.cyksj.config.zfb.BaseZfbConfig;
 import com.cyksj.config.zfb.ZfbProductCode;
 import com.cyksj.dto.RedisKey;
@@ -45,13 +45,11 @@ import com.cyksj.mapper.market.task.TaskTypeMapper;
 import com.cyksj.model.dto.AliPayParams;
 import com.cyksj.model.dto.CouponPopularizeDto;
 import com.cyksj.model.dto.H5JsPayParams;
+import com.cyksj.model.entity.Address;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.views.AccountView;
 import com.cyksj.model.manage.views.OrderDonView;
-import com.cyksj.model.request.OrderAttach;
-import com.cyksj.model.request.OrderPayRequest;
-import com.cyksj.model.request.WxOrderRefundReq;
-import com.cyksj.model.request.ZfbOrderRefundReq;
+import com.cyksj.model.request.*;
 import com.cyksj.model.response.AliPayRefundRep;
 import com.cyksj.model.views.CouponNewUserView;
 import com.cyksj.model.views.CouponUserView;
@@ -184,6 +182,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 	private final GroupRelationFrontService groupRelationFrontService;
 
+	private final TransferAccountsRecordMapper transferAccountsRecordMapper;
+
 	private final List<String> noChekGoodsTemp = List.of("Apple One", "Youtube", "Spotify");
 
 	@Transactional(rollbackFor = Throwable.class)
@@ -891,7 +891,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 				orderDon.setShopId(null);
 			}
 			//支付宝退款
-			AlipayClient alipayClient = AliPayCommon.getAlipayClient(shopConfigMapper.getByAppId(Optional.ofNullable(orderDon.getShopId()).orElse(ShopConfig.ZFB_DEFAULT_APP_ID)));
+			AlipayClient alipayClient = AliPayClientFactory.getAlipayClient(Optional.ofNullable(orderDon.getShopId()).orElse(ShopConfig.ZFB_DEFAULT_APP_ID));
 			AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
 			AlipayTradeRefundModel model = new AlipayTradeRefundModel();
 			//支付宝交易号
@@ -1194,10 +1194,74 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		orderDonTransportMapper.insert(transport);
 	}
 
-	public AliPayParams commonAliPay(Long orderId, String returnUrl, String productCode, String appId, String qrPayMode) throws Exception {
-		ShopConfig shopConfig = shopConfigMapper.getByAppId(Optional.ofNullable(appId).orElse(ShopConfig.ZFB_DEFAULT_APP_ID));
+	@Override
+	public AlipayResponse transferAccounts(TransferAccountsReq transferAccountsReq) throws Exception {
+		Long userId = transferAccountsReq.getUserId();
+		String account = transferAccountsReq.getAccount();
+		String name = transferAccountsReq.getName();
+		BigDecimal money = transferAccountsReq.getMoney();
+		String type = transferAccountsReq.getType();
+		BigDecimal points = transferAccountsReq.getPoints();
+		/* 生成商户转账订单号 */
+		String donNo = SEQUENCE.nextId().toString();
+		if (StrUtil.isEmpty(type)) {
+			type = TransferConstant.ALIPAY;
+		}
+		Integer scope = transferAccountsReq.getScope();
+		AlipayClient alipayClient = AliPayClientFactory.getAlipayClient(ShopConfig.DISTRIBUTE_ZFB_DEFAULT_APP_ID);
+
+		AlipayRequest alipayRequest = aliPayTransferAccountsRequest(donNo, account, name, money);
 
-		AlipayClient alipayClient = AliPayCommon.getAlipayClient(shopConfig);
+		AlipayResponse response = alipayClient.certificateExecute(alipayRequest);
+		if (response.isSuccess()) {
+			log.info("支付宝转账金额:{}至用户:{}成功", money.divide(BigDecimal.valueOf(100)), userId);
+			saveTransferRecord(userId, donNo, account, name, money, points, type, scope, response.getBody(), null);
+			return response;
+		}
+		log.info("支付宝转账金额:{}至用户:{}失败", money.divide(BigDecimal.valueOf(100)), userId);
+		saveTransferRecord(userId, donNo, account, name, money, points, type, scope, response.getBody(), response.getSubMsg());
+		return response;
+	}
+
+	@Override
+	public AlipayFundTransCommonQueryResponse getTransFerStatusByTid(String translationId) throws Exception {
+		AlipayClient alipayClient = AliPayClientFactory.getAlipayClient(ShopConfig.ZFB_DEFAULT_APP_ID);
+		AlipayFundTransCommonQueryRequest request = new AlipayFundTransCommonQueryRequest();
+		AlipayFundTransCommonQueryModel model = new AlipayFundTransCommonQueryModel();
+		model.setOrderId(translationId);
+		model.setBizScene(TransferConstant.DIRECT_TRANSFER);
+		model.setProductCode(ZfbProductCode.STD_RED_PACKET.getProductCode());
+		request.setBizModel(model);
+		AlipayFundTransCommonQueryResponse response = alipayClient.certificateExecute(request);
+		return response;
+	}
+
+	private AlipayRequest aliPayTransferAccountsRequest(String donNo, String account, String name, BigDecimal money) {
+		//支付宝转账
+		AlipayFundTransUniTransferRequest transUniTransferRequest = new AlipayFundTransUniTransferRequest();
+		//转账参数
+		AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
+		model.setOutBizNo(donNo);
+		//单位元
+		model.setTransAmount(money.divide(BigDecimal.valueOf(100)).toString());
+		model.setProductCode(ZfbProductCode.STD_RED_PACKET.getProductCode());
+		model.setBizScene(TransferConstant.DIRECT_TRANSFER);
+		model.setOrderTitle("分销提现");
+		//红包业务必传,取值REDPACKET
+		JSONObject businessParams = new JSONObject();
+		businessParams.putOpt(TransferConstant.SUB_BIZ_SCENE, TransferConstant.RED_PACKET);
+		model.setBusinessParams(businessParams.toString());
+		Participant payeeInfo = new Participant();
+		payeeInfo.setIdentity(account);
+		payeeInfo.setIdentityType(TransferConstant.ALIPAY_LOGON_ID);
+		payeeInfo.setName(name);
+		model.setPayeeInfo(payeeInfo);
+		transUniTransferRequest.setBizModel(model);
+		return transUniTransferRequest;
+	}
+
+	public AliPayParams commonAliPay(Long orderId, String returnUrl, String String productCode, String appId, String qrPayMode) throws Exception {
+		AlipayClient alipayClient = AliPayClientFactory.getAlipayClient(Optional.ofNullable(appId).orElse(ShopConfig.ZFB_DEFAULT_APP_ID));
 		// 创建API对应的request
 		AlipayRequest alipayRequest = getAliAayRequest(orderId, productCode, qrPayMode);
 		if (alipayRequest == null) {
@@ -1650,4 +1714,30 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			});
 		}
 	}
+
+	/**
+	 * 保存转账记录
+	 */
+	public void saveTransferRecord(Long userId, String donNo, String account, String name, BigDecimal money, BigDecimal points, String type, Integer scope, String body, String error) throws Exception {
+		TransferAccountsRecord record = new TransferAccountsRecord();
+		JSONObject re = Jsons.parseObject(body, JSONObject.class);
+		JSONObject response = Jsons.parseObject(re.get("alipay_fund_trans_uni_transfer_response"), JSONObject.class);
+		String transactionId = response.getStr("order_id");
+		String transDate = response.getStr("trans_date");
+		record.setUserId(userId);
+		record.setAccount(account);
+		record.setName(name);
+		record.setMoney(money);
+		record.setType(type);
+		record.setScope(scope);
+		Optional.ofNullable(error).ifPresent(msg -> {
+			record.setErrorMsg(msg);
+			record.setStatus(0);
+		});
+		record.setPoints(points);
+		record.setTransferOutNo(donNo);
+		record.setTransactionId(transactionId);
+		Optional.ofNullable(transDate).ifPresent(transferTime -> record.setTransferTime(DateTime.of(transferTime, "yyyy-MM-dd HH:mm:ss")));
+		transferAccountsRecordMapper.insert(record);
+	}
 }

+ 0 - 1
netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsOrderController.java

@@ -376,5 +376,4 @@ public class CmsOrderController {
 		SearchResult<OrderCommentView> search = beanSearcher.search(OrderCommentView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 	}
-
 }

+ 29 - 0
netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java

@@ -5,6 +5,8 @@ import cn.hutool.extra.qrcode.QrCodeUtil;
 import cn.hutool.extra.qrcode.QrConfig;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.annotation.Log;
+import com.alipay.api.response.AlipayFundTransCommonQueryResponse;
+import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.IoKit;
 import com.cyksj.common.util.Xmls;
@@ -313,6 +315,33 @@ public class OrderController {
 		return "success";
 	}
 
+    /**
+     * 支付宝转账
+     */
+//    @PostMapping("/zfb/transfer/accounts")
+//    @NoSubmit
+//    public Result<String> 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<String> 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());
+    }
+
     /**
      * 获取订单列表
      */

+ 1 - 1
netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java

@@ -38,7 +38,7 @@ import com.cyksj.service.distribute.equipment.EquipmentDistributeService;
 import com.cyksj.service.template.TemplateCommonService;
 import com.cyksj.service.user.UserService;
 import com.cyksj.service.wechat.WeChatService;
-import com.cyksj.web.controller.mail.MailService;
+import com.cyksj.service.mail.MailService;
 import com.cyksj.web.util.StpUserUtil;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;

+ 39 - 3
netflix-web/src/main/java/com/cyksj/web/controller/user/DistributePopularizeController.java

@@ -5,6 +5,7 @@ import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.extra.qrcode.QrCodeUtil;
 import cn.hutool.extra.qrcode.QrConfig;
+import com.alipay.api.AlipayResponse;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.EnvCommonService;
 import com.cyksj.common.annotation.NoSubmit;
@@ -21,6 +22,12 @@ import com.cyksj.mapper.manage.distribute.DistributeWaitingSendPointsMapper;
 import com.cyksj.mapper.manage.distribute.UserDistributeMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.request.ApplyMoneyReq;
+import com.cyksj.model.request.TransferAccountsReq;
+import com.cyksj.model.views.DistributeMoneyApplyView;
+import com.cyksj.model.views.DistributePopularizeOrdersView;
+import com.cyksj.model.views.DistributePopularizeView;
+import com.cyksj.model.views.UserDistributeView;
+import com.cyksj.service.order.OrderDonService;
 import com.cyksj.model.views.*;
 import com.cyksj.web.util.StpUserUtil;
 import com.ejlchina.searcher.BeanSearcher;
@@ -70,6 +77,8 @@ public class DistributePopularizeController {
 
 	private final OrderDonMapper orderDonMapper;
 
+	private final OrderDonService orderService;
+
 	/**
 	 * 推广订单明细
 	 */
@@ -197,7 +206,7 @@ public class DistributePopularizeController {
 	@NoSubmit
 	@PostMapping("/post/applyMoney")
 	@Transactional(rollbackFor = Throwable.class)
-	public Result<Integer> applyMoney(@RequestBody ApplyMoneyReq applyMoneyReq) {
+	public Result<String> applyMoney(@RequestBody ApplyMoneyReq applyMoneyReq) throws Exception {
 		Long userId = StpUserUtil.getLoginIdAsLong();
 		User user = userMapper.selectById(userId);
 		if (user == null) {
@@ -220,16 +229,43 @@ public class DistributePopularizeController {
 		BigDecimal num = user.getPoints().divide(min, RoundingMode.DOWN);
 		BigDecimal points = min.multiply(num);
 		Integer update = userMapper.subPoints(user.getId(), points);
+		//门槛金额是分
+		BigDecimal money = num.multiply(distributePointsExchangeMoney.getMoney());
+		BigDecimal fourHundred = BigDecimal.valueOf(4 * 100 * 100);
+		if (money.compareTo(fourHundred) > 0) {
+			money = fourHundred;
+		}
 		if (update == 1) {
+			TransferAccountsReq req = new TransferAccountsReq();
+			req.setMoney(money);
+			req.setAccount(applyMoneyReq.getAccount());
+			req.setName(applyMoneyReq.getRealName());
+			req.setPoints(points);
+			req.setUserId(userId);
+
 			DistributeMoneyApply distributeMoneyApply = new DistributeMoneyApply();
 			distributeMoneyApply.setUserId(userId);
 			distributeMoneyApply.setPoints(points);
 			distributeMoneyApply.setMoney(num.multiply(distributePointsExchangeMoney.getMoney()));
-			distributeMoneyApply.setVerifyStatus(DistributeMoneyApply.Status.verifying);
 			distributeMoneyApply.setAccount(applyMoneyReq.getAccount());
 			distributeMoneyApply.setRealName(applyMoneyReq.getRealName());
+			AlipayResponse alipayResponse = orderService.transferAccounts(req);
+			if (alipayResponse.isSuccess()) {
+				distributeMoneyApply.setVerifyStatus(DistributeMoneyApply.Status.success);
+			} else {
+				distributeMoneyApply.setVerifyStatus(DistributeMoneyApply.Status.fail);
+				distributeMoneyApply.setReason(alipayResponse.getSubMsg());
+				while (true) {
+					User db = userMapper.selectById(userId);
+					Integer success = userMapper.updatePoints(user.getId(), db.getPoints(), distributeMoneyApply.getPoints());
+					if (success == 1) {
+						break;
+					}
+				}
+				return GatewayResponse.FAIL.newBuilder().setMsg(alipayResponse.getSubMsg()).toResult();
+			}
 			distributeMoneyApplyMapper.insert(distributeMoneyApply);
-			return GatewayResponse.SUCCESS.newBuilder().toResult(distributeMoneyApply.getMoney().intValue());
+			return GatewayResponse.SUCCESS.newBuilder().toResult(distributeMoneyApply.getMoney().toString());
 		}
 		throw BusinessRuntimeException.getInstance("系统异常,请重新提交提现申请");
 	}