增加银行卡相关接口。

This commit is contained in:
aaron 2025-01-24 22:23:21 +08:00
parent f2891a17c0
commit 25c2936039
4 changed files with 191 additions and 1 deletions

View File

@ -0,0 +1,109 @@
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from app.models.user_bank_card import UserBankCardDB, BankCardCreate, BankCardInfo
from app.models.user_auth import UserAuthDB
from app.models.database import get_db
from app.api.deps import get_current_user
from app.models.user import UserDB
from app.core.response import success_response, error_response, ResponseModel
from app.core.qcloud import qcloud_manager
from typing import List
router = APIRouter()
@router.post("", response_model=ResponseModel)
async def add_bank_card(
card: BankCardCreate,
db: Session = Depends(get_db),
current_user: UserDB = Depends(get_current_user)
):
"""添加银行卡"""
# 检查是否已实名认证
if not current_user.is_auth:
return error_response(code=400, message="请先完成实名认证")
# 获取认证信息
auth_info = db.query(UserAuthDB).filter(
UserAuthDB.user_id == current_user.userid
).first()
if not auth_info:
return error_response(code=400, message="未找到实名认证信息")
# 验证姓名是否一致
if card.name != auth_info.name:
return error_response(code=400, message="银行卡持卡人姓名与实名认证信息不一致")
try:
# 调用银行卡三要素核验
verify_result = await qcloud_manager.verify_bank_card(
name=auth_info.name,
id_card=auth_info.id_number,
card_number=card.card_number
)
# 验证不通过
if verify_result["Result"] != "0":
return error_response(
code=400,
message=f"银行卡验证失败: {verify_result['Description']}"
)
# 创建银行卡记录
bank_card = UserBankCardDB(
user_id=current_user.userid,
name=card.name,
card_number=card.card_number,
bank_name=card.bank_name
)
db.add(bank_card)
db.commit()
db.refresh(bank_card)
return success_response(data=BankCardInfo.model_validate(bank_card))
except Exception as e:
db.rollback()
return error_response(code=500, message=f"添加银行卡失败: {str(e)}")
@router.get("", response_model=ResponseModel)
async def get_bank_cards(
db: Session = Depends(get_db),
current_user: UserDB = Depends(get_current_user)
):
"""获取用户的银行卡列表"""
cards = db.query(UserBankCardDB).filter(
UserBankCardDB.user_id == current_user.userid
).all()
# 对银行卡号进行脱敏处理
card_list = []
for card in cards:
card_info = BankCardInfo.model_validate(card)
# 只显示后四位,其他用*代替
card_info.card_number = f"{'*' * (len(card.card_number)-4)}{card.card_number[-4:]}"
card_list.append(card_info)
return success_response(data=card_list)
@router.delete("/{card_id}", response_model=ResponseModel)
async def delete_bank_card(
card_id: int,
db: Session = Depends(get_db),
current_user: UserDB = Depends(get_current_user)
):
"""删除银行卡"""
card = db.query(UserBankCardDB).filter(
UserBankCardDB.id == card_id,
UserBankCardDB.user_id == current_user.userid
).first()
if not card:
return error_response(code=404, message="银行卡不存在")
try:
db.delete(card)
db.commit()
return success_response(message="删除成功")
except Exception as e:
db.rollback()
return error_response(code=500, message=f"删除失败: {str(e)}")

View File

@ -4,6 +4,7 @@ from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.faceid.v20180301 import faceid_client, models from tencentcloud.faceid.v20180301 import faceid_client, models
from tencentcloud.sms.v20210111 import sms_client, models as sms_models from tencentcloud.sms.v20210111 import sms_client, models as sms_models
from tencentcloud.faceid.v20180301 import models as faceid_models
from qcloud_cos import CosConfig, CosS3Client from qcloud_cos import CosConfig, CosS3Client
from app.core.config import settings from app.core.config import settings
import json import json
@ -210,5 +211,51 @@ class QCloudManager:
except Exception as e: except Exception as e:
raise Exception(f"获取上传URL失败: {str(e)}") raise Exception(f"获取上传URL失败: {str(e)}")
async def verify_bank_card(self, name: str, id_card: str, card_number: str) -> dict:
"""
银行卡三要素核验
Args:
name: 姓名
id_card: 身份证号
card_number: 银行卡号
Returns:
dict: {
"Result": str, # "0":认证通过 "1":认证未通过 "2":认证不确定
"Description": str, # 结果描述
"RequestId": str # 请求ID
}
Raises:
Exception: 验证失败时抛出异常
"""
try:
self._init_faceid_client()
# 构建请求
req = faceid_models.BankCardVerificationRequest()
params = {
"Name": name,
"IdCard": id_card,
"BankCard": card_number
}
req.from_json_string(json.dumps(params))
# 发送请求
response = self.faceid_client.BankCardVerification(req)
# 解析结果
result = json.loads(response.to_json_string())
return {
"Result": result.get("Result", "2"),
"Description": result.get("Description", "验证失败"),
"RequestId": result.get("RequestId", "")
}
except TencentCloudSDKException as e:
raise Exception(f"银行卡三要素核验失败: {str(e)}")
# 创建全局实例 # 创建全局实例
qcloud_manager = QCloudManager() qcloud_manager = QCloudManager()

View File

@ -1,6 +1,6 @@
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from app.api.endpoints import wechat,user, address, community, station, order, coupon, community_building, upload, merchant, merchant_product, merchant_order, point, config, merchant_category, log, account,merchant_pay_order, message from app.api.endpoints import wechat,user, address, community, station, order, coupon, community_building, upload, merchant, merchant_product, merchant_order, point, config, merchant_category, log, account,merchant_pay_order, message, bank_card
from app.models.database import Base, engine from app.models.database import Base, engine
from fastapi.exceptions import RequestValidationError from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
@ -32,6 +32,7 @@ app.add_middleware(RequestLoggerMiddleware)
# 添加用户路由 # 添加用户路由
app.include_router(wechat.router,prefix="/api/wechat",tags=["微信"]) app.include_router(wechat.router,prefix="/api/wechat",tags=["微信"])
app.include_router(user.router, prefix="/api/user", tags=["用户"]) app.include_router(user.router, prefix="/api/user", tags=["用户"])
app.include_router(bank_card.router, prefix="/api/bank-cards", tags=["用户银行卡"])
app.include_router(point.router, prefix="/api/point", tags=["用户积分"]) app.include_router(point.router, prefix="/api/point", tags=["用户积分"])
app.include_router(account.router, prefix="/api/account", tags=["账户"]) app.include_router(account.router, prefix="/api/account", tags=["账户"])
app.include_router(address.router, prefix="/api/address", tags=["配送地址"]) app.include_router(address.router, prefix="/api/address", tags=["配送地址"])
@ -50,6 +51,7 @@ app.include_router(upload.router, prefix="/api/upload", tags=["文件上传"])
app.include_router(config.router, prefix="/api/config", tags=["系统配置"]) app.include_router(config.router, prefix="/api/config", tags=["系统配置"])
app.include_router(log.router, prefix="/api/logs", tags=["系统日志"]) app.include_router(log.router, prefix="/api/logs", tags=["系统日志"])
@app.get("/") @app.get("/")
async def root(): async def root():
return {"message": "欢迎使用 Beefast 蜂快到家 API"} return {"message": "欢迎使用 Beefast 蜂快到家 API"}

View File

@ -0,0 +1,32 @@
from sqlalchemy import Column, String, Integer, DateTime, ForeignKey
from sqlalchemy.sql import func
from pydantic import BaseModel, Field
from typing import Optional
from datetime import datetime
from .database import Base
class UserBankCardDB(Base):
__tablename__ = "user_bank_cards"
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("users.userid"), nullable=False)
name = Column(String(50), nullable=False)
card_number = Column(String(30), nullable=False)
bank_name = Column(String(100), nullable=False)
create_time = Column(DateTime(timezone=True), server_default=func.now())
update_time = Column(DateTime(timezone=True), onupdate=func.now())
class BankCardCreate(BaseModel):
name: str = Field(..., min_length=2, max_length=50)
card_number: str = Field(..., min_length=16, max_length=19, pattern="^[0-9]{16,19}$")
bank_name: str = Field(..., max_length=100)
class BankCardInfo(BaseModel):
id: int
name: str
card_number: str
bank_name: str
create_time: datetime
class Config:
from_attributes = True