增加微信支付的逻辑
This commit is contained in:
@@ -83,13 +83,87 @@ async def recharge(
|
||||
|
||||
@router.post("/wechat/callback")
|
||||
async def wechat_callback(request: Request, db: AsyncSession = Depends(get_db)):
|
||||
data = await request.json()
|
||||
if not await verify_wechat_callback(data, db):
|
||||
raise HTTPException(status_code=400, detail="签名验证失败")
|
||||
order_no = data.get("out_trade_no")
|
||||
if order_no:
|
||||
await process_payment_success_by_order_no(db, order_no)
|
||||
return {"code": "SUCCESS", "message": "OK"}
|
||||
# 读取微信支付回调数据
|
||||
body_bytes = await request.body()
|
||||
body_str = body_bytes.decode("utf-8")
|
||||
|
||||
# 获取配置
|
||||
from app.services.payment import _get_payment_configs, _is_mock_mode, _get_wechat_client
|
||||
db_configs = await _get_payment_configs(db)
|
||||
|
||||
# 检查 mock 模式
|
||||
if _is_mock_mode(db_configs):
|
||||
try:
|
||||
import json
|
||||
data = json.loads(body_str) if body_str else {}
|
||||
order_no = data.get("out_trade_no")
|
||||
if order_no:
|
||||
await process_payment_success_by_order_no(db, order_no)
|
||||
logger.info(f"Mock WeChat callback processed: order_no={order_no}")
|
||||
return {"code": "SUCCESS", "message": "OK"}
|
||||
except Exception as e:
|
||||
logger.exception(f"Mock WeChat callback error: {e}")
|
||||
return {"code": "SUCCESS", "message": "OK"} # 微信要求即使处理失败也返回成功
|
||||
|
||||
# 真实模式:使用 wechatpayv3 SDK 验证回调并解析数据
|
||||
try:
|
||||
mch_id = db_configs.get("payment_wechat_mch_id", "")
|
||||
private_key = db_configs.get("payment_wechat_private_key", "")
|
||||
cert_serial_no = db_configs.get("payment_wechat_cert_serial_no", "")
|
||||
api_v3_key = db_configs.get("payment_wechat_api_v3_key", "")
|
||||
gateway = db_configs.get("payment_wechat_gateway", "")
|
||||
|
||||
client = _get_wechat_client(mch_id, private_key, cert_serial_no, api_v3_key, gateway)
|
||||
if not client:
|
||||
logger.error("WeChat client not initialized for callback")
|
||||
return {"code": "SUCCESS", "message": "OK"}
|
||||
|
||||
# 从请求头获取必要信息
|
||||
headers = dict(request.headers)
|
||||
timestamp = headers.get("Wechatpay-Timestamp", "")
|
||||
nonce = headers.get("Wechatpay-Nonce", "")
|
||||
signature = headers.get("Wechatpay-Signature", "")
|
||||
serial_no = headers.get("Wechatpay-Serial", "")
|
||||
|
||||
# 验证签名
|
||||
is_verified = client.verify(
|
||||
timestamp=timestamp,
|
||||
nonce=nonce,
|
||||
body=body_str,
|
||||
signature=signature,
|
||||
serial_no=serial_no
|
||||
)
|
||||
|
||||
if not is_verified:
|
||||
logger.warning("WeChat callback signature verification failed")
|
||||
raise HTTPException(status_code=400, detail="签名验证失败")
|
||||
|
||||
# 解密回调数据
|
||||
decrypted_data = client.decrypt(body_str)
|
||||
if not decrypted_data:
|
||||
logger.error("WeChat callback decryption failed")
|
||||
raise HTTPException(status_code=400, detail="数据解密失败")
|
||||
|
||||
# 处理支付成功回调
|
||||
if decrypted_data.get("event_type") == "TRANSACTION.SUCCESS":
|
||||
resource = decrypted_data.get("resource", {})
|
||||
order_no = resource.get("out_trade_no", "")
|
||||
transaction_id = resource.get("transaction_id", "")
|
||||
amount_info = resource.get("amount", {})
|
||||
total_amount = amount_info.get("total", 0) / 100 # 转换为元
|
||||
|
||||
if order_no:
|
||||
await process_payment_success_by_order_no(db, order_no, transaction_id, total_amount)
|
||||
logger.info(
|
||||
f"WeChat callback processed: order_no={order_no}, "
|
||||
f"transaction_id={transaction_id}, amount={total_amount}"
|
||||
)
|
||||
|
||||
return {"code": "SUCCESS", "message": "OK"}
|
||||
except Exception as e:
|
||||
logger.exception(f"WeChat callback processing error: {e}")
|
||||
# 微信支付要求即使处理失败也返回成功,避免重复回调
|
||||
return {"code": "SUCCESS", "message": "OK"}
|
||||
|
||||
|
||||
@router.post("/alipay/callback")
|
||||
@@ -183,13 +257,19 @@ async def cancel_order(
|
||||
if order.status != "pending":
|
||||
raise HTTPException(status_code=400, detail=f"订单状态为{order.status},无法取消")
|
||||
|
||||
# If it's an Alipay order, call close API first
|
||||
# If it's an Alipay or WeChat order, call close API first
|
||||
db_configs = await _get_payment_configs(db)
|
||||
if order.payment_method == "alipay":
|
||||
db_configs = await _get_payment_configs(db)
|
||||
try:
|
||||
await _close_alipay_order(db, order, db_configs)
|
||||
except Exception as e:
|
||||
logger.exception(f"Failed to close Alipay order {order_no}: {e}")
|
||||
elif order.payment_method == "wechat":
|
||||
try:
|
||||
from app.services.payment import _close_wechat_order
|
||||
await _close_wechat_order(db, order, db_configs)
|
||||
except Exception as e:
|
||||
logger.exception(f"Failed to close WeChat order {order_no}: {e}")
|
||||
|
||||
order.status = "cancelled"
|
||||
await db.flush()
|
||||
|
||||
Reference in New Issue
Block a user