feat(all): 同步最新进度
This commit is contained in:
6
core/routers/pay/__init__.py
Normal file
6
core/routers/pay/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
# -*- coding = utf-8 -*-
|
||||
# @Time : 2025/2/24 上午9:03
|
||||
# @File : __init__.py.py
|
||||
# @Software : PyCharm
|
||||
# @Author : xingc
|
||||
# @Desc :
|
||||
109
core/routers/pay/routes.py
Normal file
109
core/routers/pay/routes.py
Normal file
@@ -0,0 +1,109 @@
|
||||
# -*- coding = utf-8 -*-
|
||||
# @Time : 2025/2/24 上午9:03
|
||||
# @File : routes.py
|
||||
# @Software : PyCharm
|
||||
# @Author : xingc
|
||||
# @Desc :
|
||||
import logging
|
||||
|
||||
import xmltodict
|
||||
from fastapi import APIRouter, Request, HTTPException, status, Depends, BackgroundTasks
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from core.base import schema as base_schema
|
||||
from core.db.crud import CRUD
|
||||
from core.db.engine import get_async_session
|
||||
from core.db.models import Order
|
||||
from core.routers.auth.schema import LoginUser
|
||||
from core.routers.auth.services import get_current_user
|
||||
from core.utils.helper import generate_keyname, generate_order_number
|
||||
from core.wechat.api import wechat_pay_api
|
||||
|
||||
from . import schema
|
||||
from .actions import actions_after_payment
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
pay_router = APIRouter(prefix='/pay', tags=['支付模块'])
|
||||
|
||||
|
||||
@pay_router.post(
|
||||
'/order/create',
|
||||
summary='订单创建',
|
||||
response_model=base_schema.BaseResponse[schema.CreateOrderOut]
|
||||
)
|
||||
async def create_order(
|
||||
request: Request,
|
||||
payload: schema.CreateOrderIn,
|
||||
login_user: LoginUser = Depends(get_current_user),
|
||||
db_session: AsyncSession = Depends(get_async_session),
|
||||
):
|
||||
client_ip = (
|
||||
request.headers.get('X-Real-IP') or
|
||||
request.headers.get('x-real-ip') or
|
||||
request.client.host
|
||||
)
|
||||
out_trade_no = generate_order_number()
|
||||
prepay_id = wechat_pay_api.create_unified_order(
|
||||
**payload.dict(exclude_none=True),
|
||||
out_trade_no=out_trade_no,
|
||||
spbill_create_ip=client_ip
|
||||
)
|
||||
payment_params = wechat_pay_api.generate_payment_params(prepay_id)
|
||||
db_crud = CRUD(db_session, Order)
|
||||
order: Order = await db_crud.create(
|
||||
data={
|
||||
'order_id': out_trade_no,
|
||||
'user_id': login_user.user_id,
|
||||
'product_id': payload.product_id,
|
||||
'total_fee': payload.total_fee,
|
||||
'status': base_schema.OrderStatusType.WAIT_PAYMENT
|
||||
},
|
||||
filters={
|
||||
'out_trade_no': out_trade_no,
|
||||
}
|
||||
)
|
||||
return {'data': {'payment_params': payment_params, 'order_id': order.order_id}}
|
||||
|
||||
|
||||
@pay_router.post('/wechat/notify', summary='处理支付结果通知', response_model=base_schema.BaseResponse)
|
||||
async def wechat_notify(
|
||||
request: Request,
|
||||
background_tasks: BackgroundTasks,
|
||||
db_session: AsyncSession = Depends(get_async_session)
|
||||
):
|
||||
body = await request.body()
|
||||
logger.debug(body.decode())
|
||||
result = xmltodict.parse(body.decode())
|
||||
|
||||
# 验证签名
|
||||
params = result['xml']
|
||||
sign = params.pop('sign')
|
||||
local_sign = wechat_pay_api.generate_sign(params)
|
||||
if sign != local_sign:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail='签名验证失败'
|
||||
)
|
||||
|
||||
# 处理支付结果
|
||||
db_crud = CRUD(db_session, Order)
|
||||
record = {
|
||||
'out_trade_no': params['out_trade_no'],
|
||||
'transaction_id': params['transaction_id']
|
||||
}
|
||||
if params['return_code'] == 'SUCCESS' and params['result_code'] == 'SUCCESS':
|
||||
record.update({
|
||||
'notify_total_fee': params['total_fee'],
|
||||
'status': base_schema.OrderStatusType.OK
|
||||
})
|
||||
result = {'code': 200, 'message': 'OK'}
|
||||
background_tasks.add_task(actions_after_payment, notify_params=params)
|
||||
else:
|
||||
result = {'code': 400, 'message': '支付失败'}
|
||||
record.update({
|
||||
'status': base_schema.OrderStatusType.FAIL,
|
||||
})
|
||||
|
||||
await db_crud.update(data=record, filters={'order_id': record['out_trade_no']})
|
||||
|
||||
return result
|
||||
28
core/routers/pay/schema.py
Normal file
28
core/routers/pay/schema.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# -*- coding = utf-8 -*-
|
||||
# @Time : 2025/2/24 下午9:51
|
||||
# @File : schema.py
|
||||
# @Software : PyCharm
|
||||
# @Author : xingc
|
||||
# @Desc :
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class CreateOrderIn(BaseModel):
|
||||
product_id: int
|
||||
openid: str
|
||||
total_fee: int
|
||||
body: str
|
||||
|
||||
|
||||
class PaymentParamsOut(BaseModel):
|
||||
appId: str
|
||||
timeStamp: str
|
||||
nonceStr: str
|
||||
package: str
|
||||
package: str
|
||||
signType: str
|
||||
|
||||
|
||||
class CreateOrderOut(BaseModel):
|
||||
payment_params: PaymentParamsOut
|
||||
order_id: str
|
||||
Reference in New Issue
Block a user