|
|
@@ -50,6 +50,9 @@ import java.time.OffsetDateTime;
|
|
|
import java.time.ZoneId;
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
import java.time.format.DateTimeParseException;
|
|
|
+import com.payment.platform.module.payment.enterprise.entity.EnterpriseEntity;
|
|
|
+import com.payment.platform.module.payment.enterprise.mapper.EnterpriseMapper;
|
|
|
+
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.HashSet;
|
|
|
import java.util.LinkedHashMap;
|
|
|
@@ -82,17 +85,19 @@ public class AlipayBatchPayService {
|
|
|
private final BatchAuthorizeMapper batchAuthorizeMapper;
|
|
|
private final BatchOrderMapper batchOrderMapper;
|
|
|
private final BatchDetailMapper batchDetailMapper;
|
|
|
+ private final EnterpriseMapper enterpriseMapper;
|
|
|
|
|
|
/**
|
|
|
* alipay.fund.authorize.uni.apply — 生成制单授权短链接(PC 渠道)
|
|
|
* <p>
|
|
|
- * Ruling 19/21: 付款方即企业自己的支付宝 UID(pay_enterprise.enterprise_id),
|
|
|
- * 不接收客户端传入的 participant_id(防篡改指向他人账号),恒以 enterprise_id 为付款方。
|
|
|
+ * Ruling 19/22: 付款方即企业自己,不接收客户端传入的 participant_id(防篡改指向他人账号)。
|
|
|
+ * 付款方身份遵循系统惯例(同 AlipayTransferService.createOnboard): 企业入驻身份
|
|
|
+ * pay_enterprise.identity 优先(配套 identityType),为空回退 enterprise_id。
|
|
|
*/
|
|
|
@Transactional
|
|
|
public Map<String, String> authorizeApply(String enterpriseId) {
|
|
|
- requireEnterpriseId(enterpriseId);
|
|
|
- return doAuthorizeApply(enterpriseId, enterpriseId);
|
|
|
+ EnterpriseEntity ent = requireEnterprise(enterpriseId);
|
|
|
+ return doAuthorizeApply(enterpriseId, payerIdentity(ent), payerIdentityType(ent));
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -102,7 +107,7 @@ public class AlipayBatchPayService {
|
|
|
*/
|
|
|
@Transactional
|
|
|
public Map<String, String> authorizeRebind(String enterpriseId) {
|
|
|
- requireEnterpriseId(enterpriseId);
|
|
|
+ EnterpriseEntity ent = requireEnterprise(enterpriseId);
|
|
|
BatchAuthorizeEntity existing = batchAuthorizeMapper.selectOne(
|
|
|
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<BatchAuthorizeEntity>()
|
|
|
.eq(BatchAuthorizeEntity::getEnterpriseId, enterpriseId)
|
|
|
@@ -117,11 +122,11 @@ public class AlipayBatchPayService {
|
|
|
log.info("制单授权重新生成,作废旧申请: old_out_biz_no={}, enterprise_id={}",
|
|
|
existing.getOutBizNo(), enterpriseId);
|
|
|
}
|
|
|
- return doAuthorizeApply(enterpriseId, enterpriseId);
|
|
|
+ return doAuthorizeApply(enterpriseId, payerIdentity(ent), payerIdentityType(ent));
|
|
|
}
|
|
|
|
|
|
/** 授权申请公共逻辑(三态预检 + 调支付宝 + 落库),apply 与 rebind 共用 */
|
|
|
- private Map<String, String> doAuthorizeApply(String enterpriseId, String participantId) {
|
|
|
+ private Map<String, String> doAuthorizeApply(String enterpriseId, String participantId, String participantIdType) {
|
|
|
if (participantId == null || participantId.isBlank())
|
|
|
throw new BusinessException(400, "付款方支付宝账号不能为空");
|
|
|
// 重复新增防护三态(设计文档 2.4/7):
|
|
|
@@ -154,7 +159,7 @@ public class AlipayBatchPayService {
|
|
|
model.setChannel("pc");
|
|
|
AuthParticipantInfo principal = new AuthParticipantInfo();
|
|
|
principal.setParticipantId(participantId);
|
|
|
- principal.setParticipantIdType("ALIPAY_USER_ID");
|
|
|
+ principal.setParticipantIdType(participantIdType);
|
|
|
model.setPrincipalInfo(principal);
|
|
|
|
|
|
AlipayFundAuthorizeUniApplyRequest request = new AlipayFundAuthorizeUniApplyRequest();
|
|
|
@@ -298,11 +303,12 @@ public class AlipayBatchPayService {
|
|
|
model.setOrderTitle(dto.getOrderTitle());
|
|
|
if (dto.getTimeExpire() != null) model.setTimeExpire(dto.getTimeExpire());
|
|
|
if (dto.getRemark() != null) model.setRemark(dto.getRemark());
|
|
|
- // 付款方 + 制单授权协议(Ruling 19/21: 付款方即企业自己的 UID,不接受客户端传入,恒用 enterprise_id)
|
|
|
- String payerUid = dto.getEnterpriseId();
|
|
|
+ // 付款方 + 制单授权协议(Ruling 19/22: 不接受客户端指定,付款方身份遵循系统惯例 identity 优先回退 enterprise_id)
|
|
|
+ EnterpriseEntity ent = requireEnterprise(dto.getEnterpriseId());
|
|
|
+ String payerUid = payerIdentity(ent);
|
|
|
Participant payer = new Participant();
|
|
|
payer.setIdentity(payerUid);
|
|
|
- payer.setIdentityType("ALIPAY_USER_ID");
|
|
|
+ payer.setIdentityType(payerIdentityType(ent));
|
|
|
if (dto.getAgreementNo() != null && !dto.getAgreementNo().isBlank()) {
|
|
|
Map<String, String> ext = new LinkedHashMap<>();
|
|
|
ext.put("agreement_no", dto.getAgreementNo());
|
|
|
@@ -567,6 +573,23 @@ public class AlipayBatchPayService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /** 企业校验 + 身份解析: 付款方/参与方支付宝身份 = 企业入驻身份 identity(配套 identityType),为空回退 enterprise_id(同 AlipayTransferService.createOnboard 惯例) */
|
|
|
+ private EnterpriseEntity requireEnterprise(String enterpriseId) {
|
|
|
+ requireEnterpriseId(enterpriseId);
|
|
|
+ EnterpriseEntity ent = enterpriseMapper.selectByEnterpriseIdIgnoreTenant(enterpriseId);
|
|
|
+ if (ent == null)
|
|
|
+ throw new BusinessException(400, "企业不存在");
|
|
|
+ return ent;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String payerIdentity(EnterpriseEntity ent) {
|
|
|
+ return ent.getIdentity() != null ? ent.getIdentity() : ent.getEnterpriseId();
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String payerIdentityType(EnterpriseEntity ent) {
|
|
|
+ return ent.getIdentityType() != null ? ent.getIdentityType() : "ALIPAY_USER_ID";
|
|
|
+ }
|
|
|
+
|
|
|
/** 租户隔离: 企业 ID 是业务必需参数,为空直接拒绝(防御 Controller body 路径的零校验) */
|
|
|
private static void requireEnterpriseId(String enterpriseId) {
|
|
|
if (enterpriseId == null || enterpriseId.isBlank())
|