|
@@ -163,24 +163,87 @@ class OpenTransferService:
|
|
|
if existing:
|
|
if existing:
|
|
|
raise CustomException("三方订单号已存在")
|
|
raise CustomException("三方订单号已存在")
|
|
|
|
|
|
|
|
- # 执行转账记录创建
|
|
|
|
|
- result = await AccountService.transfer_service(auth=auth, data=data)
|
|
|
|
|
- log.info(f"租户资金专户转账发起成功: 企业: {data.enterprise_id}, 金额: {data.amount}")
|
|
|
|
|
|
|
+ # 执行转账
|
|
|
|
|
+ try:
|
|
|
|
|
+ result = await AccountService.transfer_service(auth=auth, data=data)
|
|
|
|
|
+ log.info(f"租户资金专户转账发起成功: 企业: {data.enterprise_id}, 金额: {data.amount}")
|
|
|
|
|
+
|
|
|
|
|
+ # 保存三方订单号关联记录
|
|
|
|
|
+ create_data = {
|
|
|
|
|
+ "third_biz_no": third_biz_no,
|
|
|
|
|
+ "out_biz_no": result.out_biz_no,
|
|
|
|
|
+ "api_key": data.api_key,
|
|
|
|
|
+ }
|
|
|
|
|
+ await crud.create(create_data)
|
|
|
|
|
+
|
|
|
|
|
+ return OpenTransferOutSchema(
|
|
|
|
|
+ status=result.status,
|
|
|
|
|
+ order_no=result.order_no,
|
|
|
|
|
+ third_biz_no=third_biz_no,
|
|
|
|
|
+ )
|
|
|
|
|
+ except CustomException as e:
|
|
|
|
|
+ # 转账失败(支付宝返回错误),通知调用方
|
|
|
|
|
+ error_msg = e.args[0] if e.args else "转账失败"
|
|
|
|
|
+ log.warning(f"租户资金专户转账失败: third_biz_no={third_biz_no}, error={error_msg}")
|
|
|
|
|
+
|
|
|
|
|
+ # 异步通知调用方
|
|
|
|
|
+ try:
|
|
|
|
|
+ await cls._open_return_fail(auth, third_biz_no, error_msg, data)
|
|
|
|
|
+ except Exception as notify_err:
|
|
|
|
|
+ log.warning(f"发送失败通知异常: {notify_err}")
|
|
|
|
|
+
|
|
|
|
|
+ return OpenTransferOutSchema(
|
|
|
|
|
+ status="FAIL",
|
|
|
|
|
+ order_no="",
|
|
|
|
|
+ third_biz_no=third_biz_no,
|
|
|
|
|
+ )
|
|
|
|
|
|
|
|
- # 保存三方订单号关联记录
|
|
|
|
|
- create_data = {
|
|
|
|
|
- "third_biz_no": third_biz_no,
|
|
|
|
|
- "out_biz_no": result.out_biz_no,
|
|
|
|
|
- "api_key": data.api_key,
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ @classmethod
|
|
|
|
|
+ async def _open_return_fail(
|
|
|
|
|
+ cls,
|
|
|
|
|
+ auth: AuthSchema,
|
|
|
|
|
+ third_biz_no: str,
|
|
|
|
|
+ error_msg: str,
|
|
|
|
|
+ data: OpenTransferSchema,
|
|
|
|
|
+ ) -> None:
|
|
|
|
|
+ """转账失败时通知调用方"""
|
|
|
|
|
+ import time
|
|
|
|
|
+ import json
|
|
|
|
|
+ import aiohttp
|
|
|
|
|
+
|
|
|
|
|
+ # 获取回调地址
|
|
|
|
|
+ return_url = None
|
|
|
|
|
+ if data.api_key:
|
|
|
|
|
+ from ..apikey.service import TenantApiKeyService
|
|
|
|
|
+ try:
|
|
|
|
|
+ apikey_data = await TenantApiKeyService.get_apikey_service(auth=auth, api_key=data.api_key)
|
|
|
|
|
+ return_url = apikey_data.return_url
|
|
|
|
|
+ except Exception:
|
|
|
|
|
+ pass
|
|
|
|
|
|
|
|
- await crud.create(create_data)
|
|
|
|
|
|
|
+ if not return_url:
|
|
|
|
|
+ conf = await OpenConfService.get_conf_service(auth)
|
|
|
|
|
+ if conf:
|
|
|
|
|
+ return_url = conf.return_url
|
|
|
|
|
|
|
|
- return OpenTransferOutSchema(
|
|
|
|
|
- status=result.status,
|
|
|
|
|
- order_no=result.order_no,
|
|
|
|
|
- third_biz_no=third_biz_no,
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ if not return_url:
|
|
|
|
|
+ log.warning("转账失败通知: 未配置回调地址")
|
|
|
|
|
+ return
|
|
|
|
|
+
|
|
|
|
|
+ from app.utils.snowflake import get_snowflake_id
|
|
|
|
|
+ notify_id = f"n{get_snowflake_id()}"
|
|
|
|
|
+ timestamp = int(time.time() * 1000)
|
|
|
|
|
+ content = json.dumps({
|
|
|
|
|
+ "status": "FAIL",
|
|
|
|
|
+ "third_biz_no": third_biz_no,
|
|
|
|
|
+ "amount": str(data.amount),
|
|
|
|
|
+ "error_msg": error_msg,
|
|
|
|
|
+ }, ensure_ascii=False)
|
|
|
|
|
+
|
|
|
|
|
+ timeout = aiohttp.ClientTimeout(total=30)
|
|
|
|
|
+ async with aiohttp.ClientSession(timeout=timeout) as session:
|
|
|
|
|
+ log.info(f"转账失败回调: third_biz_no={third_biz_no}, url={return_url}")
|
|
|
|
|
+ await fetch_manual_retry(session, return_url, notify_id, timestamp, content)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|