controller.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. from typing import Annotated, Any, Optional, Dict
  2. from fastapi import APIRouter, Body, Depends, Path, Query
  3. from fastapi.responses import JSONResponse
  4. from app.api.v1.module_system.auth.schema import AuthSchema
  5. from app.common.response import ResponseSchema, SuccessResponse
  6. from app.core.dependencies import AuthPermission
  7. from app.core.logger import log
  8. from app.core.router_class import OperationLogRoute
  9. from app.core.base_params import PaginationQueryParam
  10. from .schema import (
  11. AccountAuthorizeApplySchema,
  12. AccountAuthorizeApplyOutSchema,
  13. AccountCreateSchema,
  14. AccountDepositSchema,
  15. AccountDepositOutSchema,
  16. AccountOperationOutSchema,
  17. AccountQuerySchema,
  18. AccountTransferSchema,
  19. TransferListOutSchema,
  20. TransferOutSchema,
  21. TransferTaskOutSchema,
  22. ConsumeDetailOutSchema,
  23. )
  24. from .service import AccountService
  25. AccountRouter = APIRouter(
  26. route_class=OperationLogRoute,
  27. prefix="/account",
  28. tags=["资金专户"],
  29. )
  30. @AccountRouter.post(
  31. "/authorize/apply",
  32. summary="申请转账授权签约",
  33. description="申请转账授权签约",
  34. response_model=ResponseSchema[AccountAuthorizeApplyOutSchema],
  35. )
  36. async def authorize_apply_controller(
  37. data: AccountAuthorizeApplySchema,
  38. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:authorize"]))],
  39. ) -> JSONResponse:
  40. """申请转账授权签约"""
  41. result = await AccountService.authorize_apply_service(auth=auth, data=data)
  42. log.info(f"申请转账授权签约成功: {data.enterprise_id}")
  43. return SuccessResponse(data=result, msg="申请转账授权签约成功")
  44. @AccountRouter.post(
  45. "",
  46. summary="开通资金专户",
  47. description="开通资金专户",
  48. response_model=ResponseSchema[AccountOperationOutSchema],
  49. )
  50. async def create_account_controller(
  51. data: AccountCreateSchema,
  52. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:create"]))],
  53. ) -> JSONResponse:
  54. """开通资金专户"""
  55. result = await AccountService.create_account_service(auth=auth, data=data)
  56. log.info(f"开通资金专户成功: {data.enterprise_id}")
  57. return SuccessResponse(data=result, msg="开通资金专户成功")
  58. @AccountRouter.get(
  59. "/{enterprise_id}",
  60. summary="查询资金专户",
  61. description="根据企业ID查询资金专户(调用支付宝接口)",
  62. response_model=ResponseSchema[list[Any]],
  63. )
  64. async def query_account_controller(
  65. data: AccountQuerySchema,
  66. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:detail"]))],
  67. ) -> JSONResponse:
  68. """查询资金专户"""
  69. result = await AccountService.query_account_service(auth=auth, data=data)
  70. log.info(f"查询资金专户成功: {data.enterprise_id}")
  71. return SuccessResponse(data=result, msg="查询资金专户成功")
  72. @AccountRouter.post(
  73. "/deposit",
  74. summary="资金专户充值",
  75. description="从支付宝余额向资金专户充值",
  76. response_model=ResponseSchema[AccountDepositOutSchema],
  77. )
  78. async def deposit_controller(
  79. data: AccountDepositSchema,
  80. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:deposit"]))],
  81. ) -> JSONResponse:
  82. """资金专户充值"""
  83. result = await AccountService.deposit_service(auth=auth, data=data)
  84. log.info(f"资金专户充值发起成功: {data.enterprise_id} -> {str(data.amount)}")
  85. return SuccessResponse(data=result, msg="充值页面获取成功,请跳转完成支付")
  86. @AccountRouter.post(
  87. "/transfer",
  88. summary="资金专户转账",
  89. description="从资金专户转账到支付宝账户/银行卡/资金专户",
  90. response_model=ResponseSchema[TransferTaskOutSchema],
  91. )
  92. async def transfer_controller(
  93. data: AccountTransferSchema,
  94. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:transfer"]))],
  95. ) -> JSONResponse:
  96. """资金专户转账"""
  97. result = await AccountService.transfer_service(auth=auth, data=data)
  98. log.info(f"资金专户转账发起成功: 企业: {data.enterprise_id}, 金额: {data.amount}")
  99. return SuccessResponse(data=result, msg="转账申请已提交")
  100. # @AccountRouter.post(
  101. # "/withdraw",
  102. # summary="资金专户提现",
  103. # description="从资金专户向支付宝余额提现",
  104. # response_model=ResponseSchema[AccountOperationOutSchema],
  105. # )
  106. # async def withdraw_controller(
  107. # data: AccountWithdrawSchema,
  108. # auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:withdraw"]))],
  109. # ) -> JSONResponse:
  110. # """资金专户提现"""
  111. # result = await AccountService.withdraw_service(auth=auth, data=data)
  112. # log.info(f"资金专户提现发起成功: {data.out_biz_no} -> {data.amount}")
  113. # return SuccessResponse(data=result, msg="提现申请已提交")
  114. @AccountRouter.get(
  115. "/transfer/{out_biz_no}",
  116. summary="查询转账记录详情",
  117. description="根据订单号查询转账记录",
  118. response_model=ResponseSchema[TransferOutSchema],
  119. )
  120. async def transfer_detail_controller(
  121. out_biz_no: Annotated[str, Path(description="商家侧订单号")],
  122. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:transfer:detail"]))],
  123. ) -> JSONResponse:
  124. """查询转账记录详情"""
  125. result = await AccountService.transfer_detail_service(auth=auth, out_biz_no=out_biz_no)
  126. log.info(f"查询转账记录详情成功: {out_biz_no}")
  127. return SuccessResponse(data=result, msg="查询转账记录详情成功")
  128. @AccountRouter.get(
  129. "/transfer",
  130. summary="查询转账记录列表",
  131. description="分页查询转账记录列表",
  132. response_model=ResponseSchema[TransferListOutSchema],
  133. )
  134. async def transfer_list_controller(
  135. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:transfer:list"]))],
  136. page: Annotated[PaginationQueryParam, Depends()],
  137. search: Annotated[Dict, Depends()],
  138. ) -> JSONResponse:
  139. """查询转账记录列表"""
  140. result = await AccountService.transfer_list_service(
  141. auth=auth, page_no=page.page_no, page_size=page.page_size, order_by=page.order_by, search=search
  142. )
  143. return SuccessResponse(data=result, msg="查询转账记录列表成功")
  144. @AccountRouter.get(
  145. "/consume-detail",
  146. summary="账单详情查询",
  147. description="查询企业码账单详情,支持查询关联退款、订单、票据等信息",
  148. response_model=ResponseSchema[ConsumeDetailOutSchema],
  149. )
  150. async def consume_detail_query_controller(
  151. auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:consume:detail"]))],
  152. pay_no: Annotated[str, Query(description="支付宝账单号")],
  153. enterprise_id: Annotated[str | None, Query(description="企业ID(2.0接口签约企业必填)")] = None,
  154. ant_shop_id: Annotated[str | None, Query(description="蚂蚁门店ID(商户服务商必填)")] = None,
  155. query_options: Annotated[str | None, Query(description="查询选项,多个用逗号分隔")] = None,
  156. ) -> JSONResponse:
  157. """
  158. 账单详情查询
  159. 调用: alipay.commerce.ec.consume.detail.query
  160. 用于查询企业码账单详情,支持查询关联退款、订单、票据等信息。
  161. - pay_no: 支付宝账单号(必填)
  162. - enterprise_id: 企业ID(2.0接口签约企业必填)
  163. - ant_shop_id: 蚂蚁门店ID(商户服务商必填)
  164. - query_options: 查询选项,支持 Refund/Order/Ticket,多个用逗号分隔
  165. """
  166. options_list = None
  167. if query_options:
  168. options_list = [opt.strip() for opt in query_options.split(",") if opt.strip()]
  169. result = await AccountService.consume_detail_query_service(
  170. auth=auth,
  171. pay_no=pay_no,
  172. enterprise_id=enterprise_id,
  173. ant_shop_id=ant_shop_id,
  174. query_options=options_list,
  175. )
  176. log.info(f"账单详情查询成功: {pay_no}")
  177. return SuccessResponse(data=result, msg="账单详情查询成功")
  178. # @AccountRouter.post(
  179. # "/receipt/apply",
  180. # summary="申请资金回单",
  181. # description="申请资金业务回单",
  182. # response_model=ResponseSchema[ReceiptApplyOutSchema],
  183. # )
  184. # async def receipt_apply_controller(
  185. # data: ReceiptApplySchema,
  186. # auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:receipt"]))],
  187. # ) -> JSONResponse:
  188. # """申请资金回单"""
  189. # result = await AccountService.receipt_apply_service(auth=auth, data=data)
  190. # log.info(f"申请资金回单成功: {data.order_no}")
  191. # return SuccessResponse(data=result, msg="申请资金回单成功")
  192. # @AccountRouter.get(
  193. # "/receipt/{file_id}",
  194. # summary="查询资金回单",
  195. # description="查询资金业务回单状态",
  196. # response_model=ResponseSchema[ReceiptQueryOutSchema],
  197. # )
  198. # async def receipt_query_controller(
  199. # file_id: Annotated[str, Path(description="文件申请号")],
  200. # auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:receipt"]))],
  201. # enterprise_id: Annotated[str, Query(description="企业ID")] = None,
  202. # ) -> JSONResponse:
  203. # """查询资金回单"""
  204. # if not enterprise_id:
  205. # enterprise_id = auth.enterprise_id or ""
  206. # result = await AccountService.receipt_query_service(
  207. # auth=auth, enterprise_id=enterprise_id, file_id=file_id
  208. # )
  209. # log.info(f"查询资金回单成功: {file_id}")
  210. # return SuccessResponse(data=result, msg="查询资金回单成功")
  211. # @AccountRouter.post(
  212. # "/transfer/batch",
  213. # summary="批量资金专户转账",
  214. # description="异步批量转账,先放入队列,后台处理",
  215. # response_model=ResponseSchema[AccountTransferBatchOutSchema],
  216. # )
  217. # async def batch_transfer_controller(
  218. # data: AccountTransferBatchSchema,
  219. # auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:transfer"]))],
  220. # ) -> JSONResponse:
  221. # """批量资金专户转账(异步)"""
  222. # result = await AccountService.batch_transfer_service(auth=auth, data=data)
  223. # log.info(f"批量转账任务已提交: {result.batch_id}, 总笔数: {result.total}")
  224. # return SuccessResponse(data=result, msg="批量转账任务已提交,正在处理中")
  225. # @AccountRouter.get(
  226. # "/transfer/batch/{batch_id}",
  227. # summary="查询批量转账结果",
  228. # description="查询批量转账的处理状态和结果",
  229. # response_model=ResponseSchema[dict],
  230. # )
  231. # async def get_batch_result_controller(
  232. # batch_id: Annotated[str, Path(description="批次ID")],
  233. # auth: Annotated[AuthSchema, Depends(AuthPermission(["module_payment:account:transfer"]))],
  234. # ) -> JSONResponse:
  235. # """查询批量转账结果"""
  236. # result = await AccountService.get_batch_result_service(auth=auth, batch_id=batch_id)
  237. # log.info(f"查询批量转账结果成功: {batch_id}")
  238. # return SuccessResponse(data=result, msg="查询批量转账结果成功")