Обновление состояния пользователя в базе данных после запуска облачной функции HTTP - проверка полосы - PullRequest
0 голосов
/ 11 июля 2020

Я храню пользователей в базе данных firebase в реальном времени и полосе для обработки платежей. Авторизованный пользователь может нажать кнопку и будет перенаправлен в Stripe Checkout. После совершения платежа пользователь снова перенаправляется на success_url в приложении. Затем я хотел бы обновить объект пользователя в базе данных - просто сохраните информацию об успешном платеже и его идентификатор.

Проблема : я не знаю, как найти пользователя, который совершил платеж после переадресации на success_url. Я хотел бы обновить данные пользователя в базе данных после оплаты.

Идея : я могу сохранить payment_intent в профиле пользователя, так как эта информация отправляется на сторону клиента с помощью сеанс. А затем, после завершения платежа, я мог найти payment_intent и обновить пользователя, у которого были эти данные. Но хороший ли это подход? Есть ли лучший способ найти пользователя?

Мой код основан на HTTP-запросах Firebase Cloud Function. Следуя инструкциям Stripe для приема платежа, я создаю сеанс для пользователя, который хочет произвести платеж:

export const payment = functions.https.onRequest((request, response) => {
  cors(request, response, async () => {
    response.set("Access-Control-Allow-Headers", "Content-Type");
    response.set("Access-Control-Allow-Credentials", "true");
    response.set("Access-Control-Allow-Origin", "*");
    await stripe.checkout.sessions.create(
      {
        payment_method_types: ["card"],
        line_items: [
          {
            price_data: {
              currency: "usd",
              product_data: {
                name: "Test"
              },
              unit_amount: 1000
            },
            quantity: 1
          }
        ],
        mode: "payment",
        success_url: "https://example.com/success",
        cancel_url: "https://example.com/cancel"
      },
      function(err: Error, session: any) {
        response.send(session); 
        // the session is sent to the client and can be used to finalise a transaction
      }
    );
  });
});

На стороне клиента я использую ax ios для вызова запрос облачной функции payment, а затем я передаю sessionId на Stripe.redirectToCheckout, который запускает перенаправление проверки:

let sessionId = "";
await axios.post("payment function url request")
    .then(response => {
        sessionId = response.data.id;
    });
const stripe: any = await loadStripe("stripe key");
stripe.redirectToCheckout({
    sessionId: sessionId
});

После того, как клиент завершает платеж в Stripe Checkout, он перенаправляется на URL-адрес, указанный как success_url, рекомендуется запускать веб-перехватчик из полосы после завершения проверки. Это позволяет запускать другую облачную функцию, которая отправляет ответ клиентской стороне об успешном платеже response.json({ received: true }):

export const successfulPayment = functions.https.onRequest(
  (request, response) => {
    const sig = request.headers["stripe-signature"];
    let event;

    try {
      event = stripe.webhooks.constructEvent(
        request.rawBody,
        sig,
        endpointSecret
      );
    } catch (err) {
      return response.status(400).send(`Webhook Error: ${err.message}`);
    }
    // Handle the checkout.session.completed event
    // Should I update the user data in the database here?
    if (event.type === "checkout.session.completed") {
      const session = event.data.object;
      console.log(`Event passed: ${session}`);
    }
    // Return a response to acknowledge receipt of the event
    response.json({ received: true });
    // Or how do I use this response to then update the user from the client side?
  }
);

Я буду очень признателен за любую помощь и предложения:)

1 Ответ

1 голос
/ 12 июля 2020

Спасибо за вопрос, kabugh!

Далее я хотел бы обновить объект пользователя в базе данных - просто сохраните информацию об успешном платеже и его идентификатор.

Во-первых, вы, вероятно, не захотите использовать успешный URL как сигнал для сохранения успешного платежа. Возможно, клиент закрывает свой браузер, соединение inte rnet между вашим сервером и клиентом разрывается, или что клиент просто уходит после успешной оплаты, но до перехода по URL-адресу успеха. Вместо этого настоятельно рекомендуется использовать веб-перехватчики, особенно прослушивая событие checkout.session.completed. Из URL-адреса успешного выполнения вы можете получить сеанс оформления заказа и показать статус покупателю, если он там окажется, но вы не хотите использовать это для выполнения или в качестве источника истины для статуса платежа.

Я могу сохранить payment_intent в профиле пользователя, поскольку эта информация отправляется на клиентскую сторону с сеансом. А затем, после завершения платежа, я мог найти payment_intent и обновить пользователя, у которого были эти данные. Но хороший ли это подход? Есть ли лучший способ найти пользователя?

Я полагаю, вы имеете в виду идентификатор сеанса оформления заказа, а не идентификатор платежа. Идентификатор PaymentIntent не будет создан до тех пор, пока пользователь не будет перенаправлен. Да, это хорошая идея и хорошая практика - хранить ссылку на идентификатор сеанса проверки с профилем пользователя где-нибудь в вашей базе данных. Вы также можете установить значение metadata в сеансе оформления заказа при его создании с некоторой ссылкой на идентификатор пользователя в вашей системе. Таким образом, когда вы получаете событие веб-перехватчика checkout.session.completed, вы можете искать пользователя по идентификатору на основе идентификатора, хранящегося в metadata, или идентификатора сеанса оформления заказа, хранящегося в профиле пользователя, как обсуждалось ранее.

рекомендуется запускать веб-перехватчик из полосы после завершения проверки. Он позволяет запускать другую облачную функцию, которая отправляет ответ клиентской стороне об успешном ответе на платеж. json ({Received: true})

Обратите внимание, что событие webhook является запросом POST с серверов Stripe прямо на ваш сервер. Он никоим образом не будет отображать или отправлять ответ браузеру или клиенту клиента. Ответ веб-перехватчика от вашего сервера возвращается в Stripe, и нет концепции общего сеанса между этими тремя сторонами. При отправке response.json({ received: true }) в результате обработчика веб-перехватчика он отправляется обратно в Stripe, а не в браузер клиента.

...