Browse Source

feat(account): 全量同步转账状态接口,调用支付宝核实 DEALING 记录

alphah 2 weeks ago
parent
commit
42a440c174

+ 15 - 0
backend/app/plugin/module_payment/account/controller.py

@@ -272,6 +272,21 @@ async def transfer_sync_status_controller(
     return SuccessResponse(data=result, msg="同步转账状态成功")
 
 
+@AccountRouter.post(
+    "/transfer/sync-all",
+    summary="全量同步转账状态",
+    description="自动查询所有企业卡在 DEALING 的转账,调用支付宝核实状态并更新",
+    response_model=ResponseSchema[dict],
+)
+async def transfer_sync_all_controller(
+    auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:transfer:update"]))],
+) -> JSONResponse:
+    """全量同步转账状态"""
+    result = await AccountService.transfer_sync_all_service(auth=auth)
+    log.info(f"全量同步转账状态完成: {result}")
+    return SuccessResponse(data=result, msg="全量同步完成")
+
+
 @AccountRouter.get(
     "/consume-detail",
     summary="账单详情查询",

+ 116 - 0
backend/app/plugin/module_payment/account/service.py

@@ -844,6 +844,122 @@ class AccountService:
         }
 
 
+    @classmethod
+    async def transfer_sync_all_service(
+        cls,
+        auth: AuthSchema,
+    ) -> dict:
+        """
+        全量同步转账状态
+        自动查询所有卡在 DEALING 的转账,调用支付宝核实状态
+        """
+        from app.plugin.module_payment.account.crud import TransferCRUD
+        from app.plugin.module_payment.enterprise.service import EnterpriseService
+        from sqlalchemy import update as sa_update
+        from app.plugin.module_payment.account.model import TransferModel
+        from app.plugin.module_payment.account.enums import TransferStatusEnum
+
+        # 获取所有企业
+        enterprises = await EnterpriseService.all_service(auth=auth)
+        if not enterprises:
+            return {"total": 0, "synced": 0, "failed": 0, "details": []}
+
+        try:
+            from alipay.aop.api.request.AlipayCommerceEcTransOrderQueryRequest import (
+                AlipayCommerceEcTransOrderQueryRequest,
+            )
+            from alipay.aop.api.domain.AlipayCommerceEcTransOrderQueryModel import (
+                AlipayCommerceEcTransOrderQueryModel,
+            )
+            from alipay.aop.api.response.AlipayCommerceEcTransOrderQueryResponse import (
+                AlipayCommerceEcTransOrderQueryResponse,
+            )
+            from app.core.alipay_client import AlipayClient
+        except ImportError:
+            raise CustomException(msg="支付宝SDK未正确安装")
+
+        crud = TransferCRUD(auth)
+        client = AlipayClient.get_client()
+
+        synced = 0
+        failed = 0
+        total = 0
+        details = []
+
+        for enterprise in enterprises:
+            eid = enterprise.enterprise_id
+            dealing_transfers = await crud.list(search={
+                "status": TransferStatusEnum.DEALING.value,
+                "enterprise_id": eid,
+            })
+            if not dealing_transfers:
+                continue
+
+            for transfer in dealing_transfers:
+                total += 1
+                out_biz_no = transfer.out_biz_no
+                if not out_biz_no:
+                    continue
+
+                try:
+                    query_model = AlipayCommerceEcTransOrderQueryModel()
+                    query_model.out_biz_no = out_biz_no
+                    query_model.enterprise_id = eid
+
+                    request = AlipayCommerceEcTransOrderQueryRequest()
+                    request.biz_model = query_model
+
+                    response = client.execute(request)
+                    if not response:
+                        failed += 1
+                        details.append({"out_biz_no": out_biz_no, "status": "DEALING", "error": "无响应"})
+                        continue
+
+                    query_result = AlipayCommerceEcTransOrderQueryResponse()
+                    query_result.parse_response_content(response)
+
+                    if not query_result.is_success():
+                        failed += 1
+                        err_msg = query_result.sub_msg or query_result.msg
+                        details.append({"out_biz_no": out_biz_no, "status": "DEALING", "error": err_msg})
+                        log.warning(f"全量同步 - 查询失败: out_biz_no={out_biz_no}, error={err_msg}")
+                        continue
+
+                    alipay_status = getattr(query_result, 'status', None)
+                    if alipay_status and alipay_status != TransferStatusEnum.DEALING.value:
+                        update_data = {"status": alipay_status}
+                        order_no = getattr(query_result, 'order_no', None)
+                        fund_order_id = getattr(query_result, 'pay_fund_order_id', None)
+                        if order_no:
+                            update_data["order_no"] = order_no
+                        if fund_order_id:
+                            update_data["fund_order_id"] = fund_order_id
+
+                        upd = sa_update(TransferModel).where(
+                            TransferModel.out_biz_no == out_biz_no
+                        ).values(**update_data)
+                        await auth.db.execute(upd)
+                        synced += 1
+                        details.append({"out_biz_no": out_biz_no, "status": alipay_status, "synced": True})
+                        log.info(f"全量同步 - 已更新: out_biz_no={out_biz_no}, old=DEALING, new={alipay_status}")
+                    else:
+                        details.append({"out_biz_no": out_biz_no, "status": "DEALING", "error": "支付宝侧仍为处理中"})
+                except Exception as e:
+                    failed += 1
+                    details.append({"out_biz_no": out_biz_no, "status": "DEALING", "error": str(e)})
+                    log.warning(f"全量同步 - 异常: out_biz_no={out_biz_no}, error={e}")
+
+            if synced > 0 or failed > 0:
+                await auth.db.flush()
+
+        return {
+            "total": total,
+            "synced": synced,
+            "failed": failed,
+            "details": details,
+        }
+
+
     @classmethod
     async def update_transfer_status_service(
         cls,