Explorar el Código

fix 支付宝转账红包

zoujiajian hace 3 años
padre
commit
fc458b967b

+ 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

@@ -47,4 +47,6 @@ public interface Constant {
 	String LOTTERY_SPECIFIC_ORDER_EFFECTIVE_TIME = "lottery_specific_order_effective_time";
 
 	String CORP_POPULARIZE_CUSTOMER = "corp_popularize_customer";
+
+	String SUCCESS = "success";
 }

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

@@ -23,5 +23,11 @@ public interface TransferConstant {
 
 	String RED_PACKET = "REDPACKET";
 
+	/**
+	 * 传入的扩展参数如下:
+	 * sub_biz_scene 子业务场景,红包业务必传,取值REDPACKET,C2C现金红包、B2C现金红包均需传入
+	 */
+	String SUB_BIZ_SCENE = "SUB_BIZ_SCENE";
+
 	String ALIPAY_LOGON_ID = "ALIPAY_LOGON_ID";
 }

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

@@ -16,7 +16,7 @@ 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 WX_DEFAULT_APP_ID = "1635455207";
 

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

@@ -3,6 +3,7 @@ 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;
 
@@ -30,6 +31,7 @@ public class TransferAccountsReq {
 	/**
 	 * 转账账户真实姓名
 	 */
+	@NotEmpty
 	private String name;
 
 	/**

+ 30 - 3
netflix-service/src/main/java/com/cyksj/common/AliPayCommon.java

@@ -5,7 +5,6 @@ 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;
 
 /*
@@ -15,11 +14,31 @@ import com.cyksj.model.entity.ShopConfig;
  *创建时间:2022/11/9 14:07
  */
 public class AliPayCommon {
+	/**
+	 * 支付宝证书路径
+	 */
+	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";
 
 	/**
 	 * 获取ALI支付客户端
+	 * isCert 是否需要证书
 	 */
-	public static AlipayClient getAlipayClient(ShopConfig config) throws AlipayApiException {
+	public static AlipayClient getAlipayClient(ShopConfig config, Boolean isCert) throws AlipayApiException {
 		AlipayConfig alipayConfig = new AlipayConfig();
 		//网关地址
 		alipayConfig.setServerUrl(BaseZfbConfig.url);
@@ -28,7 +47,15 @@ public class AliPayCommon {
 		alipayConfig.setFormat(BaseZfbConfig.format);
 		alipayConfig.setCharset(BaseZfbConfig.charset);
 		alipayConfig.setSignType(BaseZfbConfig.signType);
-		alipayConfig.setAlipayPublicKey(config.getPublicKey());
+		if (isCert) {
+			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 = new DefaultAlipayClient(alipayConfig);
 		return alipayClient;
 	}

+ 13 - 4
netflix-service/src/main/java/com/cyksj/service/gzh/factory/EventMsgService.java

@@ -5,11 +5,13 @@ import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.constant.Constant;
 import com.cyksj.common.util.Codec;
+import com.cyksj.common.util.Jsons;
 import com.cyksj.config.WeChatConfig;
 import com.cyksj.mapper.UserMapper;
 import com.cyksj.mapper.WxAppMapper;
 import com.cyksj.mapper.WxSyncLogMapper;
 import com.cyksj.mapper.gzh.UserGzhRelationMapper;
+import com.cyksj.model.dto.AuthRedirect;
 import com.cyksj.model.dto.GzhUnionidUserinfo;
 import com.cyksj.model.dto.MsgEvent;
 import com.cyksj.model.entity.User;
@@ -115,10 +117,17 @@ public class EventMsgService implements GzhMsgService {
 			user.setUnionid(info.getUnionid());
 			userMapper.insert(user);
 
-			Object sharedIdObj = redisService.get(RedisService.key.WX_GZH_QRCODE_SHARED_LOGIN.getNameFormat(sceneKey));
-			if (sharedIdObj != null) {
-				Long sharedId = Long.parseLong(sharedIdObj.toString());
-				distributeService.saveDistributionInvitation(sharedId, user.getId());
+			String state = redisService.getStr(RedisService.key.WX_GZH_QRCODE_SHARED_LOGIN.getNameFormat(sceneKey));
+			AuthRedirect re = null;
+			if (StrUtil.isNotEmpty(state)) {
+				// 转跳参数
+				String json = Codec.DoBase64.custom().setData(state).decodeAsText();
+				if (StrUtil.isNotEmpty(json)) {
+					try {
+						re = Jsons.parseObject(json, AuthRedirect.class);
+					} catch (Exception e) {
+					}
+				}
 			}
 
 			saveGzhUserRelation(msgEvent, user.getId(), openId, info.getUnionid(), sceneKey);

+ 4 - 2
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;
@@ -86,10 +88,10 @@ public interface OrderDonService extends IService<OrderDon> {
     /**
      * 支付宝红包转账
      */
-    Boolean transferAccounts(TransferAccountsReq transferAccountsReq) throws Exception;
+    AlipayResponse transferAccounts(TransferAccountsReq transferAccountsReq) throws Exception;
 
     /**
      * 查询支付宝转账状态
      */
-    String getTransFerStatusByTid(String translationId) throws Exception;
+    AlipayFundTransCommonQueryResponse getTransFerStatusByTid(String translationId) throws Exception;
 }

+ 19 - 14
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -857,7 +857,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 = AliPayCommon.getAlipayClient(shopConfigMapper.getByAppId(Optional.ofNullable(orderDon.getShopId()).orElse(ShopConfig.ZFB_DEFAULT_APP_ID)), false);
 			AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
 			AlipayTradeRefundModel model = new AlipayTradeRefundModel();
 			//支付宝交易号
@@ -1150,7 +1150,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 	}
 
 	@Override
-	public Boolean transferAccounts(TransferAccountsReq transferAccountsReq) throws Exception {
+	public AlipayResponse transferAccounts(TransferAccountsReq transferAccountsReq) throws Exception {
 		Long userId = transferAccountsReq.getUserId();
 		String account = transferAccountsReq.getAccount();
 		String name = transferAccountsReq.getName();
@@ -1165,7 +1165,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		Integer scope = transferAccountsReq.getScope();
 		ShopConfig shopConfig = shopConfigMapper.getByAppId(ShopConfig.ZFB_DEFAULT_APP_ID);
 
-		AlipayClient alipayClient = AliPayCommon.getAlipayClient(shopConfig);
+		AlipayClient alipayClient = AliPayCommon.getAlipayClient(shopConfig, true);
 
 		AlipayRequest alipayRequest = aliPayTransferAccountsRequest(donNo, account, name, money);
 
@@ -1173,17 +1173,17 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		if (response.isSuccess()) {
 			log.info("支付宝转账金额:{}至用户:{}成功", money.divide(BigDecimal.valueOf(100)), userId);
 			saveTransferRecord(userId, donNo, account, name, money, points, type, scope, response.getBody(), null);
-			return true;
+			return response;
 		}
 		log.info("支付宝转账金额:{}至用户:{}失败", money.divide(BigDecimal.valueOf(100)), userId);
 		saveTransferRecord(userId, donNo, account, name, money, points, type, scope, response.getBody(), response.getSubMsg());
-		return false;
+		return response;
 	}
 
 	@Override
-	public String getTransFerStatusByTid(String translationId) throws Exception {
+	public AlipayFundTransCommonQueryResponse getTransFerStatusByTid(String translationId) throws Exception {
 		ShopConfig shopConfig = shopConfigMapper.getByAppId(ShopConfig.ZFB_DEFAULT_APP_ID);
-		AlipayClient alipayClient = AliPayCommon.getAlipayClient(shopConfig);
+		AlipayClient alipayClient = AliPayCommon.getAlipayClient(shopConfig, true);
 		AlipayFundTransCommonQueryRequest request = new AlipayFundTransCommonQueryRequest();
 		AlipayFundTransCommonQueryModel model = new AlipayFundTransCommonQueryModel();
 		model.setOrderId(translationId);
@@ -1191,7 +1191,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		model.setProductCode(ZfbProductCode.STD_RED_PACKET.getProductCode());
 		request.setBizModel(model);
 		AlipayFundTransCommonQueryResponse response = alipayClient.certificateExecute(request);
-		return response.getBody();
+		return response;
 	}
 
 	private AlipayRequest aliPayTransferAccountsRequest(String donNo, String account, String name, BigDecimal money) {
@@ -1200,16 +1200,20 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		//转账参数
 		AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
 		model.setOutBizNo(donNo);
-		model.setTransAmount(money.toString());
+		//单位元
+		model.setTransAmount(money.divide(BigDecimal.valueOf(100)).toString());
 		model.setProductCode(ZfbProductCode.STD_RED_PACKET.getProductCode());
 		model.setBizScene(TransferConstant.DIRECT_TRANSFER);
 		model.setOrderTitle("红包转账");
 		//红包业务必传,取值REDPACKET
-		model.setBusinessParams(TransferConstant.RED_PACKET);
+		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;
 	}
@@ -1217,7 +1221,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 	public AliPayParams commonAliPay(Long orderId, String productCode, String appId, String qrPayMode) throws Exception {
 		ShopConfig shopConfig = shopConfigMapper.getByAppId(Optional.ofNullable(appId).orElse(ShopConfig.ZFB_DEFAULT_APP_ID));
 
-		AlipayClient alipayClient = AliPayCommon.getAlipayClient(shopConfig);
+		AlipayClient alipayClient = AliPayCommon.getAlipayClient(shopConfig, false);
 		// 创建API对应的request
 		AlipayRequest alipayRequest = getAliAayRequest(orderId, productCode, qrPayMode);
 		if (alipayRequest == null) {
@@ -1610,8 +1614,9 @@ 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);
-		String transactionId = re.getStr("order_id");
-		String transDate = re.getStr("trans_date");
+		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);
@@ -1625,7 +1630,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		record.setPoints(points);
 		record.setTransferOutNo(donNo);
 		record.setTransactionId(transactionId);
-		record.setTransferTime(DateTime.of(transDate, "yyyy-MM-dd HH:mm:ss"));
+		Optional.ofNullable(transDate).ifPresent(transferTime -> record.setTransferTime(DateTime.of(transferTime, "yyyy-MM-dd HH:mm:ss")));
 		transferAccountsRecordMapper.insert(record);
 	}
 }

+ 23 - 11
netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java

@@ -3,6 +3,9 @@ package com.cyksj.web.controller.payment;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.extra.qrcode.QrCodeUtil;
 import cn.hutool.extra.qrcode.QrConfig;
+import com.alipay.api.response.AlipayFundTransCommonQueryResponse;
+import com.cyksj.common.annotation.NoSubmit;
+import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.IoKit;
 import com.cyksj.common.util.Xmls;
@@ -16,6 +19,7 @@ import com.cyksj.model.dto.H5JsPayParams;
 import com.cyksj.model.entity.OrderDon;
 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;
 import com.cyksj.model.response.AliPayTradeStatus;
@@ -282,23 +286,31 @@ public class OrderController {
 		return "success";
 	}
 
-//    /**
-//     * 支付宝转账
-//     */
-//    @PostMapping("/zfb/transfer/accounts")
-//    @NoSubmit
-//    public Result<String> zfbTransferAccounts(@RequestBody TransferAccountsReq transferAccountsReq) throws Exception {
-//        orderDonService.transferAccounts(transferAccountsReq);
-//        return GatewayResponse.SUCCESS.newBuilder().toResult("转账成功");
-//    }
+    /**
+     * 支付宝转账
+     */
+    @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 {
-        String body = orderDonService.getTransFerStatusByTid(translationId);
-        return GatewayResponse.SUCCESS.newBuilder().toResult(body);
+        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());
     }
 
     /**

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

@@ -196,11 +196,18 @@ public class DistributePopularizeController {
 			distributeMoneyApply.setMoney(num.multiply(distributePointsExchangeMoney.getMoney()));
 			distributeMoneyApply.setAccount(applyMoneyReq.getAccount());
 			distributeMoneyApply.setRealName(applyMoneyReq.getRealName());
-			if (orderService.transferAccounts(req)) {
+			if (orderService.transferAccounts(req).isSuccess()) {
 				distributeMoneyApply.setVerifyStatus(DistributeMoneyApply.Status.success);
-			}else {
+			} else {
 				distributeMoneyApply.setVerifyStatus(DistributeMoneyApply.Status.fail);
-				distributeMoneyApply.setImg("红包转账失败");
+				distributeMoneyApply.setReason("红包转账失败");
+				while (true) {
+					BigDecimal originalPoints = user.getPoints();
+					Integer success = userMapper.updatePoints(user.getId(), originalPoints, distributeMoneyApply.getPoints());
+					if (success == 1) {
+						break;
+					}
+				}
 			}
 			distributeMoneyApplyMapper.insert(distributeMoneyApply);
 			return GatewayResponse.SUCCESS.newBuilder().toResult(distributeMoneyApply.getMoney().intValue());