Как получить доступ к метаданным сессии оформления заказа в веб-хуке Stripe для методов оплаты в режиме подписки

Я интегрирую Stripe Checkout в Django-приложение и обрабатываю webhooks для обновления информации о пользователе на основе событий оплаты. Однако я сталкиваюсь с проблемами доступа к метаданным, связанным с Checkout Session, когда работаю с payment_method объектами.

Контекст:

У меня следующая настройка для Stripe Checkout:

  • StripeCheckoutMonthlyView и StripeCheckoutYearlyView: оба создают Checkout Session с метаданными (например, user_id, plan_type).
  • Webhook Handler (stripe_webhook): Обрабатывает различные типы событий от Stripe.

Проблема:

В событии payment_method.attached мне нужно получить доступ к метаданным, которые были включены в Checkout Session. Однако объект payment_method не включает метаданные и не ссылается непосредственно на Checkout Session.

Вот как выглядит мой обработчик вебхука:

@csrf_exempt
def stripe_webhook(request):
    payload = request.body
    event = None

    print('Stripe Webhook Received!')

    try:
        event = stripe.Event.construct_from(
            json.loads(payload), stripe.api_key
        )
    except ValueError as e:
        # Invalid payload
        return HttpResponse(status=400)

    if event.type == 'payment_intent.succeeded':
        # Handle payment_intent.succeeded event
        pass
    elif event.type == 'payment_method.attached':
        payment_method = event.data.object
        # Issue: Payment method does not include metadata or session_id
        pass
    elif event.type == 'checkout.session.completed':
        session = event.data.object
        # Retrieve session metadata here
        pass
    else:
        print('Unhandled event type {}'.format(event.type))

    return HttpResponse(status=200)

Что мне нужно:

Мне нужно обновить информацию о пользователе на основе метаданных, которые были включены в Checkout Session. А именно:

  1. Получить метаданные в payment_method.attached событии.
  2. Получение метаданных из Checkout Session при обработке payment_method событий.

Попытка решения:

Я пытался использовать payment_intent_data:

class StripeCheckoutMonthlyView(APIView):
   def post(self, request, *args, **kwargs):
        # try:
        checkout_session = stripe.checkout.Session.create(
            line_items=[
                {
                    'price': settings.STRIPE_PRICE_ID_MONTHLY,
                    'quantity': 1,
                },
            ],
            payment_method_types=['card'],
            mode='subscription',
            success_url=settings.SITE_URL + '/pagamento/?success=true&session_id={CHECKOUT_SESSION_ID}',
            cancel_url=settings.SITE_URL + '/?canceled=true',
            metadata={'user_id': request.user.id,
                        'plan_type': 'monthly'},
            payment_intent_data={
                'metadata': {
                    'user_id': request.user.id,
                }
            }
        )
        return Response({'url': checkout_session.url,
                            'id': checkout_session.id,
                            }, status=status.HTTP_200_OK)

и затем используйте его в соответствующей функции:

def add_info_card(payment_method):
    """
    Update the user's card details and payment date based on the payment intent.
    
    Args:
        payment_method: The payment intent object from Stripe containing card and charge details.
        user: The user object retrieved from the database.
    """
    print('Payment Method: ', payment_method)
    user = get_object_or_404(User, id=payment_method.metadata.user_id)

    last4 = payment_method['card']['last4']
    payment_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    brand_card = payment_method['card']['brand']

    print('Last 4: ', last4)
    print('Payment Date: ', payment_date)
    
    # Update the user with card details and payment date
    user.card_last4 = last4
    user.brand_card = brand_card
    user.payment_date = payment_date
    user.save()
    print(f"User {user.id} updated with card details and payment date.")

но получил ошибку:

stripe._error.InvalidRequestError: Request req_td3acLmE4ziQqi: You can not pass `payment_intent_data` in `subscription` mode.

Вопросы:

  1. Как я могу получить доступ к Checkout Session метаданным при обработке payment_method событий?
  2. Каким образом лучше всего связать payment_method с Checkout Session метаданными в веб-хуке?

Для кассовой сессии с режимом subscription метаданные должны быть установлены в разделе subscription_data.metadata.

Метаданные будут доступны в следующих местах:

Метаданные не будут доступны для объектов Payment Method или Payment Intent.

Вернуться на верх