2025-07-09 05:22:28 +08:00

255 lines
8.0 KiB
Python

"""
支付视图
"""
from flask import Blueprint, render_template, request, jsonify, session, redirect, url_for, flash
from app.models.payment import Payment
from app.models.order import Order
from app.utils.decorators import login_required
from config.database import db
from datetime import datetime
import time
import random
payment_bp = Blueprint('payment', __name__, url_prefix='/payment')
@payment_bp.route('/process', methods=['POST'])
@login_required
def process():
"""处理支付请求"""
try:
user_id = session['user_id']
payment_sn = request.json.get('payment_sn')
payment_method = request.json.get('payment_method')
if not payment_sn:
return jsonify({'success': False, 'message': '支付流水号不能为空'})
# 获取支付记录
payment = Payment.query.filter_by(payment_sn=payment_sn).first()
if not payment:
return jsonify({'success': False, 'message': '支付记录不存在'})
order = payment.order
if order.user_id != user_id:
return jsonify({'success': False, 'message': '订单不存在'})
if not order.can_pay():
return jsonify({'success': False, 'message': '订单不可支付'})
# 根据支付方式处理
if payment_method == 'wechat':
# 微信支付
result = process_wechat_pay(payment)
elif payment_method == 'alipay':
# 支付宝支付
result = process_alipay(payment)
elif payment_method == 'bank':
# 银行卡支付
result = process_bank_pay(payment)
elif payment_method == 'simulate':
# 模拟支付
result = process_simulate_pay(payment)
else:
return jsonify({'success': False, 'message': '不支持的支付方式'})
return jsonify(result)
except Exception as e:
return jsonify({'success': False, 'message': f'支付处理失败: {str(e)}'})
def process_wechat_pay(payment):
"""处理微信支付"""
# TODO: 接入真实的微信支付API
# 目前返回模拟的支付二维码
# 模拟生成支付二维码数据
qr_code_url = f"weixin://wxpay/bizpayurl?pr={payment.payment_sn}"
return {
'success': True,
'payment_type': 'qrcode',
'qr_code_url': qr_code_url,
'payment_sn': payment.payment_sn,
'amount': float(payment.amount),
'message': '请使用微信扫码支付'
}
def process_alipay(payment):
"""处理支付宝支付"""
# TODO: 接入真实的支付宝API
# 目前返回模拟的跳转链接
pay_url = f"https://mapi.alipay.com/gateway.do?service=create_direct_pay_by_user&payment_sn={payment.payment_sn}"
return {
'success': True,
'payment_type': 'redirect',
'pay_url': pay_url,
'payment_sn': payment.payment_sn,
'amount': float(payment.amount),
'message': '正在跳转到支付宝...'
}
def process_bank_pay(payment):
"""处理银行卡支付"""
# TODO: 接入银行支付网关
# 目前返回模拟的网银链接
bank_url = f"https://pay.bank.com/pay?order={payment.payment_sn}"
return {
'success': True,
'payment_type': 'redirect',
'pay_url': bank_url,
'payment_sn': payment.payment_sn,
'amount': float(payment.amount),
'message': '正在跳转到网银...'
}
def process_simulate_pay(payment):
"""处理模拟支付"""
return {
'success': True,
'payment_type': 'simulate',
'payment_sn': payment.payment_sn,
'amount': float(payment.amount),
'message': '模拟支付模式,可直接完成支付'
}
@payment_bp.route('/callback/wechat', methods=['POST'])
def wechat_callback():
"""微信支付回调"""
try:
# TODO: 验证微信支付回调签名
# 目前模拟处理
callback_data = request.get_data()
# 解析回调数据,获取支付结果
# 模拟成功的回调处理
return handle_payment_success(request.form.get('payment_sn'), 'wechat_success_' + str(datetime.now().timestamp()))
except Exception as e:
return f"FAIL: {str(e)}"
@payment_bp.route('/callback/alipay', methods=['POST'])
def alipay_callback():
"""支付宝支付回调"""
try:
# TODO: 验证支付宝回调签名
# 目前模拟处理
return handle_payment_success(request.form.get('payment_sn'), 'alipay_success_' + str(datetime.now().timestamp()))
except Exception as e:
return f"FAIL: {str(e)}"
def handle_payment_success(payment_sn, third_party_sn):
"""处理支付成功"""
try:
payment = Payment.query.filter_by(payment_sn=payment_sn).first()
if not payment:
return "FAIL: Payment not found"
if payment.status == Payment.STATUS_SUCCESS:
return "SUCCESS" # 已经处理过的支付
# 更新支付状态
payment.status = Payment.STATUS_SUCCESS
payment.third_party_sn = third_party_sn
payment.paid_at = datetime.utcnow()
# 更新订单状态
order = payment.order
order.status = Order.STATUS_PENDING_SHIPMENT
db.session.commit()
return "SUCCESS"
except Exception as e:
db.session.rollback()
return f"FAIL: {str(e)}"
@payment_bp.route('/check_status/<payment_sn>')
@login_required
def check_status(payment_sn):
"""检查支付状态"""
try:
user_id = session['user_id']
payment = Payment.query.filter_by(payment_sn=payment_sn).first()
if not payment or payment.order.user_id != user_id:
return jsonify({'success': False, 'message': '支付记录不存在'})
return jsonify({
'success': True,
'status': payment.status,
'status_text': payment.get_status_text(),
'paid_at': payment.paid_at.isoformat() if payment.paid_at else None
})
except Exception as e:
return jsonify({'success': False, 'message': f'查询失败: {str(e)}'})
@payment_bp.route('/simulate_success/<payment_sn>', methods=['POST'])
@login_required
def simulate_success(payment_sn):
"""模拟支付成功(开发测试用)"""
try:
user_id = session['user_id']
payment = Payment.query.filter_by(payment_sn=payment_sn).first()
if not payment or payment.order.user_id != user_id:
return jsonify({'success': False, 'message': '支付记录不存在'})
if payment.status == Payment.STATUS_SUCCESS:
return jsonify({'success': False, 'message': '订单已支付'})
# 模拟支付成功
result = handle_payment_success(payment_sn, f'SIMULATE_{int(time.time())}_{random.randint(1000, 9999)}')
if result == "SUCCESS":
return jsonify({'success': True, 'message': '支付成功'})
else:
return jsonify({'success': False, 'message': result})
except Exception as e:
return jsonify({'success': False, 'message': f'模拟支付失败: {str(e)}'})
@payment_bp.route('/simulate_fail/<payment_sn>', methods=['POST'])
@login_required
def simulate_fail(payment_sn):
"""模拟支付失败(开发测试用)"""
try:
user_id = session['user_id']
payment = Payment.query.filter_by(payment_sn=payment_sn).first()
if not payment or payment.order.user_id != user_id:
return jsonify({'success': False, 'message': '支付记录不存在'})
if payment.status == Payment.STATUS_SUCCESS:
return jsonify({'success': False, 'message': '订单已支付,无法模拟失败'})
# 模拟支付失败
payment.status = Payment.STATUS_FAILED
payment.third_party_sn = f'SIMULATE_FAIL_{int(time.time())}_{random.randint(1000, 9999)}'
db.session.commit()
return jsonify({'success': True, 'message': '模拟支付失败'})
except Exception as e:
db.session.rollback()
return jsonify({'success': False, 'message': f'模拟支付失败操作失败: {str(e)}'})