Next.js에서 Stripe Webhook (payment_intent.succeeded) 받기

Striep + 각 언어의 구현 예는 공식 문서 에 실려 있습니다.
Next.js의 경우 body-parser에서 body를 raw로 설정하지 못하고 StripeSignatureVerificationError라는 오류가 발생했습니다.
공식 문서와는 조금 다른 구현으로 잘 되었으므로 소개합니다.

Stripe에서 로컬 서버로 Webhook을 수신하기 위한 외부 게시 설정



로컬 서버를 시작한 상태에서 ngrok에서 외부에서도 두드릴 수 있도록 합니다. (Stripe CLI를 사용해도 실현 가능합니다만 이번은 ngrok로.)
$ yarn dev
$ ngrok http 3000

게시된 URL은 Striep의 관리 화면 설정에 사용됩니다.

Stripe의 Webohook 설정



Stripe의 관리 화면으로 들어갑니다.
테스트 데이터를 표시하는 동안 확인을 선택하여 개발 > Webhook으로 이동합니다.

이번에는 전송 이벤트에 payment_intent.succeeded를 사용하고 있습니다.



코드 예



pages/api/stripe-webhook.ts
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
// Webhookの署名シークレットキー
const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET_KEY;

// bodyParseを無効
export const config = {
  api: {
    bodyParser: false,
  },
}

export default async(req: any, res: any) => {
  const rawBody = await webhookPayloadParser(req);
  const stripeSignature = req.headers['stripe-signature'];

  let event = null;
  try {
    event = stripe.webhooks.constructEvent(rawBody, stripeSignature, endpointSecret);
  } catch (err) {
    // invalid signature
    res.status(400).end();
    return;
  }

  let intent = null;
  switch (event['type']) {
    case 'payment_intent.succeeded':
      intent = event.data.object;
      // 購入情報の書き込み処理など
      await createUserCheckoutPostByAdmin();
      console.log("Succeeded:", intent.id);
      break;
    case 'payment_intent.payment_failed':
      intent = event.data.object;
      const message = intent.last_payment_error && intent.last_payment_error.message;
      console.log('Failed:', intent.id, message);
      break;
  }
};

const webhookPayloadParser = (req: any): Promise<any> =>
  new Promise((resolve) => {
    let data = "";
    req.on("data", (chunk: string) => {
      data += chunk;
    });
    req.on("end", () => {
      resolve(Buffer.from(data).toString());
    });
  }
);

참고


  • Check the webhook signatures
  • RFC - add rawBody to NextApiRequest · Discussion #13405 · vercel/next.js · GitHub
  • API Routes: API Middlewares | Next.js
  • 좋은 웹페이지 즐겨찾기