|
|
@@ -381,8 +381,13 @@ public class AccountService {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 申请回单 — 对应 Python apply_receipt_service (L824-893)
|
|
|
- * 调用 alipay.commerce.ec.trans.receipt.apply
|
|
|
+ * 申请回单 — ISV 模式(对应 Python apply_receipt_service L824-893)
|
|
|
+ * 调用 alipay.data.bill.ereceiptagent.apply(基于协议获取账单回单)
|
|
|
+ *
|
|
|
+ * 2026-08 从 alipay.commerce.ec.trans.receipt.apply(商户直连企业码模式)切换为
|
|
|
+ * ISV 协议代理模式。前端仍传 enterprise_id + order_no,后端内部映射:
|
|
|
+ * key = TransferEntity.fundOrderId(支付宝 pay_fund_order_id)
|
|
|
+ * agreement_no = AccountEntity.agreementNo(ISV 与商户授权协议号)
|
|
|
*/
|
|
|
public Map<String, String> receiptApply(Map<String, Object> body) {
|
|
|
String enterpriseId = (String) body.get("enterprise_id");
|
|
|
@@ -390,6 +395,15 @@ public class AccountService {
|
|
|
if (enterpriseId == null || orderNo == null)
|
|
|
throw new BusinessException(400, "enterprise_id 和 order_no 不能为空");
|
|
|
|
|
|
+ // 从转账记录取支付宝资金单号 pay_fund_order_id 作为申请 key
|
|
|
+ TransferEntity transfer = transferMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<TransferEntity>().eq(TransferEntity::getOrderNo, orderNo));
|
|
|
+ if (transfer == null)
|
|
|
+ throw new BusinessException(400, "未找到对应转账记录: " + orderNo);
|
|
|
+ String fundOrderId = transfer.getFundOrderId();
|
|
|
+ if (fundOrderId == null || fundOrderId.isBlank())
|
|
|
+ throw new BusinessException(400, "该转账记录缺少支付宝资金单号(pay_fund_order_id),无法申请回单");
|
|
|
+
|
|
|
// Redis 缓存 key
|
|
|
String cacheKey = "receipt:" + enterpriseId + ":" + orderNo;
|
|
|
String cachedFileId = (String) redisTemplate.opsForValue().get(cacheKey);
|
|
|
@@ -399,11 +413,12 @@ public class AccountService {
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
- var model = new com.alipay.api.domain.AlipayCommerceEcTransReceiptApplyModel();
|
|
|
- model.setEnterpriseId(enterpriseId);
|
|
|
- model.setOrderNo(orderNo);
|
|
|
+ var model = new com.alipay.api.domain.AlipayDataBillEreceiptagentApplyModel();
|
|
|
+ model.setType("FUND_DETAIL");
|
|
|
+ model.setKey(fundOrderId);
|
|
|
+ model.setAgreementNo(getAgreementNo(enterpriseId));
|
|
|
|
|
|
- var request = new com.alipay.api.request.AlipayCommerceEcTransReceiptApplyRequest();
|
|
|
+ var request = new com.alipay.api.request.AlipayDataBillEreceiptagentApplyRequest();
|
|
|
request.setBizModel(model);
|
|
|
|
|
|
var response = alipayClientFactory.getClient(enterpriseId).certificateExecute(request);
|
|
|
@@ -426,16 +441,17 @@ public class AccountService {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 查询回单状态 — 对应 Python query_receipt_service (L896-944)
|
|
|
- * 调用 alipay.commerce.ec.trans.receipt.query
|
|
|
+ * 查询回单状态 — ISV 模式(对应 Python query_receipt_service L896-944)
|
|
|
+ * 调用 alipay.data.bill.accountbookereceipt.query
|
|
|
+ * 2026-08 从 alipay.commerce.ec.trans.receipt.query 切换,参数由 enterprise_id+file_id 映射为 agreement_no+file_id
|
|
|
*/
|
|
|
public Map<String, Object> queryReceipt(String enterpriseId, String fileId) {
|
|
|
try {
|
|
|
- var model = new com.alipay.api.domain.AlipayCommerceEcTransReceiptQueryModel();
|
|
|
- model.setEnterpriseId(enterpriseId);
|
|
|
+ var model = new com.alipay.api.domain.AlipayDataBillAccountbookereceiptQueryModel();
|
|
|
model.setFileId(fileId);
|
|
|
+ model.setAgreementNo(getAgreementNo(enterpriseId));
|
|
|
|
|
|
- var request = new com.alipay.api.request.AlipayCommerceEcTransReceiptQueryRequest();
|
|
|
+ var request = new com.alipay.api.request.AlipayDataBillAccountbookereceiptQueryRequest();
|
|
|
request.setBizModel(model);
|
|
|
|
|
|
var response = alipayClientFactory.getClient(enterpriseId).certificateExecute(request);
|
|
|
@@ -455,6 +471,15 @@ public class AccountService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /** 获取商户签约协议号(ISV 与商户授权协议号),未签约时抛错 */
|
|
|
+ private String getAgreementNo(String enterpriseId) {
|
|
|
+ AccountEntity account = accountMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<AccountEntity>().eq(AccountEntity::getEnterpriseId, enterpriseId));
|
|
|
+ if (account == null || account.getAgreementNo() == null || account.getAgreementNo().isBlank())
|
|
|
+ throw new BusinessException(400, "该商户未完成签约,缺少协议号 agreement_no");
|
|
|
+ return account.getAgreementNo();
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 获取回单下载链接(封装 apply + query)
|
|
|
* 对应 Python receipt/download 端点 (controller L521-553)
|