ソースを参照

feat: 更新体现接口

gatsby 3 週間 前
コミット
36e68c90b1

+ 29 - 14
backend/app/plugin/module_payment/account/controller.py

@@ -20,6 +20,7 @@ from .schema import (
     AccountOperationOutSchema,
     AccountQuerySchema,
     AccountTransferSchema,
+    AccountWithdrawSchema,
     TransferListOutSchema,
     TransferOutSchema,
     TransferTaskOutSchema,
@@ -115,20 +116,34 @@ async def transfer_controller(
     return SuccessResponse(data=result, msg="转账申请已提交")
 
 
-# @AccountRouter.post(
-#     "/withdraw",
-#     summary="资金专户提现",
-#     description="从资金专户向支付宝余额提现",
-#     response_model=ResponseSchema[AccountOperationOutSchema],
-# )
-# async def withdraw_controller(
-#     data: AccountWithdrawSchema,
-#     auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:withdraw"]))],
-# ) -> JSONResponse:
-#     """资金专户提现"""
-#     result = await AccountService.withdraw_service(auth=auth, data=data)
-#     log.info(f"资金专户提现发起成功: {data.out_biz_no} -> {data.amount}")
-#     return SuccessResponse(data=result, msg="提现申请已提交")
+@AccountRouter.post(
+    "/withdraw",
+    summary="资金专户提现",
+    description="从资金专户向支付宝余额提现。调用支付宝接口: alipay.commerce.ec.trans.account.withdraw",
+    response_model=ResponseSchema[AccountOperationOutSchema],
+)
+async def withdraw_controller(
+    data: AccountWithdrawSchema,
+    auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:withdraw"]))],
+) -> JSONResponse:
+    """
+    资金专户提现
+    
+    接口文档: https://opendocs.alipay.com/pre-open/d651859b_alipay.commerce.ec.trans.account.withdraw
+    
+    参数说明:
+    - enterprise_id: 企业ID
+    - account_book_id: 资金专户号
+    - amount: 提现金额(大于0)
+    - out_biz_no: 商家侧订单号(唯一)
+    
+    返回:
+    - enterprise_id: 企业ID
+    - account_book_id: 资金专户号
+    """
+    result = await AccountService.withdraw_service(auth=auth, data=data)
+    log.info(f"资金专户提现发起成功: 企业: {data.enterprise_id}, 金额: {data.amount}")
+    return SuccessResponse(data=result, msg="提现申请已提交")
 
 
 @AccountRouter.get(

+ 0 - 1
backend/app/plugin/module_payment/account/schema.py

@@ -150,7 +150,6 @@ class AccountWithdrawSchema(BaseModel):
     enterprise_id: str = Field(description="企业ID")
     account_book_id: str = Field(description="资金专户号")
     amount: Decimal = Field(max_digits=10, decimal_places=2, gt=0, description="提现金额")
-    out_biz_no: str = Field(description="商家侧订单号")
 
 
 class ReceiptApplySchema(BaseModel):

+ 78 - 66
backend/app/plugin/module_payment/account/service.py

@@ -14,6 +14,7 @@ from app.plugin.module_payment.enterprise.crud import EnterpriseCRUD
 from .crud import AccountCRUD, TransferCRUD, DepositCRUD, WithdrawCRUD
 from .enums import (
     DepositStatusEnum,
+    WithdrawStatusEnum,
 )
 from .schema import (
     AccountAuthorizeApplySchema,
@@ -25,6 +26,7 @@ from .schema import (
     AccountQuerySchema,
     AccountTransferSchema,
     AccountTransferOutSchema,
+    AccountWithdrawSchema,
     TransferListOutSchema,
     TransferOutSchema,
     TenantTransferCreate,
@@ -400,72 +402,82 @@ class AccountService:
             fund_order_id=result.fund_order_id,
         )
 
-    # @classmethod
-    # async def withdraw_service(
-    #     cls,
-    #     auth: AuthSchema,
-    #     data: AccountWithdrawSchema
-    # ) -> AccountOperationOutSchema:
-    #     """
-    #     资金专户提现
-
-    #     调用: alipay.commerce.ec.trans.account.withdraw
-    #     """
-    #     from alipay.aop.api.request.AlipayCommerceEcTransAccountWithdrawRequest import (
-    #         AlipayCommerceEcTransAccountWithdrawRequest,
-    #     )
-    #     from alipay.aop.api.domain.AlipayCommerceEcTransAccountWithdrawModel import (
-    #         AlipayCommerceEcTransAccountWithdrawModel,
-    #     )
-    #     from alipay.aop.api.response.AlipayCommerceEcTransAccountWithdrawResponse import (
-    #         AlipayCommerceEcTransAccountWithdrawResponse,
-    #     )
-
-    #     crud = AccountCRUD(auth)
-    #     enterprise = await crud.get_by_enterprise_id(data.enterprise_id)
-
-    #     if not enterprise:
-    #         raise CustomException(msg="企业不存在")
-
-    #     model = AlipayCommerceEcTransAccountWithdrawModel()
-    #     model.enterprise_id = enterprise.alipay_enterprise_id
-    #     model.account_book_id = data.account_book_id
-    #     model.amount = str(data.amount)
-    #     model.out_biz_no = data.out_biz_no
-
-    #     request = AlipayCommerceEcTransAccountWithdrawRequest()
-    #     request.biz_model = model
-
-    #     client = AlipayClient.get_client()
-    #     response = client.execute(request)
-
-    #     if not response:
-    #         raise CustomException(msg="提现失败: 无响应")
-
-    #     result = AlipayCommerceEcTransAccountWithdrawResponse()
-    #     result.parse_response_content(response)
-
-    #     if not result.is_success():
-    #         log.error(f"支付宝接口调用失败: {result.code} - {result.msg}")
-    #         raise CustomException(msg=f"提现失败: {result.msg}")
-
-    #     withdraw_crud = WithdrawCRUD(auth)
-    #     withdraw_data = {
-    #         "enterprise_id": data.enterprise_id,
-    #         "out_biz_no": data.out_biz_no,
-    #         "account_book_id": data.account_book_id,
-    #         "amount": data.amount,
-    #         "status": WithdrawStatusEnum.DEALING.value,
-    #         "order_no": result.order_no,
-    #     }
-    #     await withdraw_crud.create(withdraw_data)
-
-    #     return AccountOperationOutSchema(
-    #         enterprise_id=data.enterprise_id,
-    #         account_book_id=data.account_book_id,
-    #         out_biz_no=data.out_biz_no,
-    #         status=WithdrawStatusEnum.DEALING.value,
-    #     )
+    @classmethod
+    async def withdraw_service(
+        cls,
+        auth: AuthSchema,
+        data: AccountWithdrawSchema
+    ) -> AccountOperationOutSchema:
+        """
+        资金专户提现
+
+        调用: alipay.commerce.ec.trans.account.withdraw
+
+        接口文档: https://opendocs.alipay.com/pre-open/d651859b_alipay.commerce.ec.trans.account.withdraw
+
+        参数说明:
+        - enterprise_id: 企业ID
+        - account_book_id: 资金专户号
+        - amount: 提现金额
+        - out_biz_no: 商家侧订单号(唯一)
+        """
+        from alipay.aop.api.request.AlipayCommerceEcTransAccountWithdrawRequest import (
+            AlipayCommerceEcTransAccountWithdrawRequest,
+        )
+        from alipay.aop.api.domain.AlipayCommerceEcTransAccountWithdrawModel import (
+            AlipayCommerceEcTransAccountWithdrawModel,
+        )
+        from alipay.aop.api.response.AlipayCommerceEcTransAccountWithdrawResponse import (
+            AlipayCommerceEcTransAccountWithdrawResponse,
+        )
+
+        crud = AccountCRUD(auth)
+        enterprise = await crud.get_by_enterprise_id(data.enterprise_id)
+
+        if not enterprise:
+            raise CustomException(msg="企业不存在")
+
+        model = AlipayCommerceEcTransAccountWithdrawModel()
+        model.enterprise_id = enterprise.enterprise_id
+        model.account_book_id = data.account_book_id
+        model.amount = str(data.amount)
+        model.out_biz_no = get_snowflake_id_str(auth.tenant_id)
+
+        request = AlipayCommerceEcTransAccountWithdrawRequest()
+        request.biz_model = model
+
+        client = AlipayClient.get_client()
+        response = client.execute(request)
+
+        if not response:
+            raise CustomException(msg="提现失败: 无响应")
+
+        result = AlipayCommerceEcTransAccountWithdrawResponse()
+        result.parse_response_content(response)
+
+        if not result.is_success():
+            log.error(f"支付宝接口调用失败: {result.code} - {result.msg}")
+            raise CustomException(msg=f"提现失败: {result.msg}")
+
+        withdraw_crud = WithdrawCRUD(auth)
+        withdraw_data = {
+            "enterprise_id": data.enterprise_id,
+            "out_biz_no": model.out_biz_no,
+            "account_book_id": data.account_book_id,
+            "amount": data.amount,
+            # 专户提现到余额户是同步操作,要么执行成功,要么执行异常,
+            # 出参status设计多余,遵循规范使用业务码区分成功与失败
+            "status": WithdrawStatusEnum.SUCCESS.value,
+            "order_no": result.order_no,
+        }
+        await withdraw_crud.create(withdraw_data)
+
+        log.info(f"资金专户提现发起成功: 企业: {data.enterprise_id}, 金额: {data.amount}")
+
+        return AccountOperationOutSchema(
+            enterprise_id=data.enterprise_id,
+            account_book_id=data.account_book_id,
+        )
 
     @classmethod
     async def query_account_service(