如何在Stripe Webhook中调用FastAPI异步函数,现有方案是否有误?
错误根本原因
- 依赖注入机制误用:FastAPI的
Depends()只有在框架处理HTTP请求时才会自动解析注入对应实例,你手动调用get_current_user()路由函数时,authorize参数拿到的是原始的Depends对象,不是实例化后的AuthJWT对象,因此触发属性不存在报错。 - 业务逻辑错误:Stripe webhook请求是Stripe官方服务器发送的,不会携带你站点用户的JWT凭证,就算解决依赖问题也无法拿到当前登录用户ID,这个实现逻辑从根上就不成立。
正确实现方案
核心思路
创建Stripe验证会话时,通过metadata字段绑定当前发起验证的用户ID,webhook收到验证成功事件时,直接从事件数据中取出用户ID更新对应的字段即可,不需要依赖用户登录态。
修改后代码示例
1. 创建验证会话时绑定用户ID
@app.post('/create-verification-session') # 新增依赖获取当前登录用户ID async def create_verification_session(request: Request, authorize: AuthJWT = Depends()): authorize.jwt_required() current_user_id = authorize.get_jwt_subject() verification_session = stripe.identity.VerificationSession.create( type='document', # 将用户ID存入会话元数据,后续webhook事件会携带该信息 metadata={ "user_id": current_user_id } ) return verification_session.client_secret
2. 抽离用户验证状态更新逻辑
# 不要把更新逻辑写为路由,封装为接收用户ID参数的通用函数 async def update_user_verification_status(user_id: str): await UserModel.filter(id=user_id).update(id_verified = True)
3. 调整webhook处理逻辑
@app.post('/verification-session-webhook') async def webhook(request: Request ): webhook_secret = os.getenv('STRIPE_WEBHOOK_SECRET') data = await request.body() signature = request.headers.get('stripe-signature') try: event = stripe.Webhook.construct_event( payload=data, sig_header=signature, secret=webhook_secret ) event_data = event['data']['object'] except stripe.error.SignatureVerificationError as e: print(str(e)) return {'error': str(e)} event_type = event['type'] if event_type == 'identity.verification_session.created': print("Started verification") print(event_data.url) if event_type == 'identity.verification_session.verified': print("All the verification checks passed") # 从事件元数据中取出关联的用户ID user_id = event_data.get('metadata', {}).get('user_id') if user_id: await update_user_verification_status(user_id) return {'status': "success"}
原来的/user、/user/verify路由如果有其他业务使用可以保留,不需要删除,只需保证webhook逻辑不直接调用带依赖注入的路由函数即可。
内容的提问来源于stack exchange,提问作者Jiman Kim
相关产品推荐
相关产品推荐

