Python中Stripe支付完成后发送邮件失败问题排查
问题:Stripe收据邮件无法送达排查
背景
- 基于Flask集成Stripe Checkout的教程开发,数据库包含
User表(存储用户邮箱等信息)和Payments表(支持未登录捐赠,存储金额、邮箱字段) - 尝试添加Stripe官方收据功能的Python代码后,邮件始终无法送达
相关代码(routes.py)
from flask import Blueprint , render_template, redirect, url_for, request, abort, flash from app.payment.forms import EmptyForm, EmailForm import stripe payment = Blueprint('payment', __name__, template_folder='templates') from flask_login import current_user from app import db from app.models import User, Payments from redmail import outlook import os @payment.route('/donations', methods = ['POST', 'GET']) def donations(): form = EmailForm() if form.validate_on_submit(): price_of_donation_form = str(int(float(request.form["number"]) *100)) if not price_of_donation_form: flash('You did not type in a donation price.') return redirect( url_for('payment.donations.html'), code=307 ) email_form = form.email.data payment_db = Payments(price_of_donation=price_of_donation_form, item_name='Donate' , email=email_form) db.session.add(payment_db) db.session.commit() flash('donations are successful') return redirect(url_for('payment.order', item_name_db=payment_db.item_name), code=307) return render_template('stripe_payment/donations.html', form=form, title=' Give donations') @payment.route('/order/<item_name_db>', methods=['POST']) def order(item_name_db): payment_db = Payments.query.filter_by(item_name=item_name_db).first_or_404() checkout_session = stripe.checkout.Session.create( line_items=[ { 'price_data': { 'product_data': { 'name': payment_db.item_name, }, 'unit_amount': payment_db.price_of_donation, 'currency': "usd", }, 'quantity': 1, }, ], customer_email=payment_db.email, payment_method_types=['card'], mode='payment', success_url=request.host_url + 'order/success', cancel_url=request.host_url + 'order/cancel', ) # send email after payment/donation stripe.PaymentIntent.create ( amount=payment_db.price_of_donation, currency="usd", payment_method_types=["card"], receipt_email=payment_db.email, description="3% of your purchase goes toward our ocean cleanup effort!", ) return redirect(checkout_session.url) @payment.route('/order/success') def success(): return render_template('success.html', data=data) @payment.route('/order/cancel') def cancel(): return render_template('cancel.html')
问题排查与修复方案
1. PaymentIntent创建时机与关联错误
你在用户未完成支付时就手动创建了PaymentIntent,但这个Intent和用户实际通过Checkout完成的支付没有关联,不会被触发支付,自然不会触发收据邮件。
使用Stripe Checkout时,系统会自动创建关联的PaymentIntent,无需手动调用stripe.PaymentIntent.create。
2. 代码语法错误
stripe.PaymentIntent.create的调用存在缩进和语法错误,导致代码无法正常执行:
# 错误写法 stripe.PaymentIntent.create ( # 参数... )
正确写法应该是:
stripe.PaymentIntent.create( amount=payment_db.price_of_donation, currency="usd", payment_method_types=["card"], receipt_email=payment_db.email, description="3% of your purchase goes toward our ocean cleanup effort!", )
3. 正确的收据配置方式
方式一:让Stripe自动发送收据
- 先在Stripe后台开启自动收据:进入设置→客户设置→收据,确保「成功付款后自动发送收据」已启用
- 在创建Checkout Session时,明确指定
receipt_email参数(已传customer_email的情况下,Stripe会默认使用该邮箱,但明确指定更稳妥):
checkout_session = stripe.checkout.Session.create( # 其他参数... customer_email=payment_db.email, receipt_email=payment_db.email, # 新增:指定收据接收邮箱 # 其他参数... )
方式二:通过Webhook触发自定义邮件
如果需要发送自定义邮件(而非Stripe默认收据),需监听checkout.session.completed事件:
- 在Stripe后台配置Webhook端点,指向你的Flask接口(如
/webhook/stripe) - 在Flask中实现Webhook处理函数,收到支付成功事件后发送邮件:
@payment.route('/webhook/stripe', methods=['POST']) def stripe_webhook(): payload = request.get_data(as_text=True) sig_header = request.headers.get('Stripe-Signature') event = None try: event = stripe.Webhook.construct_event( payload, sig_header, os.environ.get('STRIPE_WEBHOOK_SECRET') ) except ValueError as e: return '', 400 except stripe.error.SignatureVerificationError as e: return '', 400 if event['type'] == 'checkout.session.completed': session = event['data']['object'] # 获取支付信息,发送自定义邮件 email = session['customer_email'] # 用redmail发送邮件的逻辑 outlook.send( subject='感谢你的捐赠', receivers=[email], html='<h1>捐赠收据</h1><p>你的捐赠金额为:...</p>' ) return '', 200
4. 额外排查点
- 检查Stripe日志:进入Stripe后台→开发→日志,查看是否有PaymentIntent错误或邮件发送失败记录
- 测试环境限制:测试模式下,Stripe仅会向测试邮箱(如
test@example.com)发送收据,真实邮箱无法收到,需切换生产模式或使用指定测试邮箱 - 验证邮箱格式:确认
Payments表中存储的邮箱格式有效,无拼写错误
内容的提问来源于stack exchange,提问作者trewbth
相关产品推荐
相关产品推荐

