Stripe Issuing卡支付拦截Webhook开发求助:需手动审批支付
Stripe Issuing 支付手动审批Webhook 问题修复
代码中的核心问题
- Flask路由函数参数错误:webhook函数无法直接接收
event参数,需从请求中获取原始数据并完成Stripe签名验证 - Stripe事件结构访问错误:事件的业务数据存储在
event['data']['object']节点下,直接访问event['data']['settings']会导致KeyError - Customer邮箱获取逻辑错误:Payment Attempt对象中的
customer字段是Stripe Customer的ID,而非完整对象,需通过API查询才能获取邮箱 - 签名验证逻辑位置错误:
stripe.Webhook.construct_event必须放在路由函数内部处理请求,而非__main__代码块 - 缺少Stripe API密钥初始化:调用Stripe API前必须设置有效的API密钥
- 缺少响应返回:Webhook必须返回2xx状态码,否则Stripe会持续重试事件
- 审批逻辑不符合需求:当前代码自动允许未拦截的支付,而需求是所有支付默认拦截,通知后手动审批,需调整逻辑
修正后的完整代码
import stripe from flask import Flask, request, jsonify # 初始化Flask应用 app = Flask(__name__) # 设置Stripe API密钥(替换为你的实际密钥) stripe.api_key = "sk_test_your_api_key_here" # 设置Webhook签名密钥(替换为你的实际密钥) WEBHOOK_SECRET = "whsec_your_webhook_secret_here" # 模拟邮件发送函数,需根据实际需求实现(比如用SMTP或第三方邮件服务) def send_admin_notification(payment_attempt_id, amount, currency, customer_email): subject = f"待审批支付请求: {payment_attempt_id}" body = f""" 收到一笔待审批的支付请求: 支付ID: {payment_attempt_id} 金额: {amount} {currency} 持卡人邮箱: {customer_email} 请通过Stripe Dashboard或调用API手动审批该支付。 """ # 这里替换为实际的邮件发送逻辑,比如使用smtplib或SendGrid等 print(f"发送通知邮件: {subject}\n{body}") @app.route('/webhook', methods=['POST']) def webhook(): # 获取请求原始数据和签名头 payload = request.data sig_header = request.headers.get('STRIPE_SIGNATURE') event = None # 验证Webhook签名,防止伪造请求 try: event = stripe.Webhook.construct_event( payload, sig_header, WEBHOOK_SECRET ) except ValueError as e: # 无效的请求数据 return jsonify({"error": str(e)}), 400 except stripe.error.SignatureVerificationError as e: # 签名验证失败 return jsonify({"error": str(e)}), 400 # 只处理支付尝试事件 if event['type'] != 'issuing.card.payment_attempted': return jsonify({"status": "ignored"}), 200 payment_attempt = event['data']['object'] # 确认支付已被默认拦截(需提前在Stripe后台配置Card/Cardholder的默认拦截规则) if payment_attempt['settings']['blocked']: # 通过Customer ID查询获取持卡人邮箱 customer = stripe.Customer.retrieve(payment_attempt['customer']) customer_email = customer['email'] # 通知管理员处理审批 send_admin_notification( payment_attempt['id'], payment_attempt['amount'], payment_attempt['currency'], customer_email ) # 返回成功响应,告知Stripe已接收事件 return jsonify({"status": "processed"}), 200 if __name__ == '__main__': # 启动Flask服务,生产环境建议使用Gunicorn等WSGI服务器 app.run(port=4242, debug=True)
关键补充说明
- 默认拦截配置:需在Stripe后台为目标Issuing Card或Cardholder设置
默认拦截所有支付,这样所有支付尝试都会触发issuing.card.payment_attempted事件且settings.blocked为True - 手动审批方式:收到通知后,你可以通过两种方式审批:
- 在Stripe Dashboard中找到对应的Payment Attempt,手动修改
Blocked状态为False - 调用Stripe API完成审批:
stripe.issuing.PaymentAttempt.update( "pa_xxxxxx", blocked=False )
- 在Stripe Dashboard中找到对应的Payment Attempt,手动修改
- 邮件函数实现:
send_admin_notification需要你根据实际环境实现,比如使用Python的smtplib模块连接邮件服务器,或使用SendGrid、Mailgun等第三方邮件服务
内容的提问来源于stack exchange,提问作者Gonzalo Pena
相关产品推荐
相关产品推荐

