PAY.JP
PAY.JP

外部リンク型決済を使う

Checkout v2 を使用して外部リンク型決済を実装します。

外部リンク型決済とは

PAY.JP でホスティングしている外部リンク型決済を使って決済を組み込むには、Checkout SessionAPI API を用いて Checkout v2 を使用します。 Checkout v2 を使用すると、ユーザーを外部リンク型決済ページにリダイレクトするだけで、支払いを受け付けることができます。

外部リンク決済(Checkout v2)の流れ

加盟店が Checkout v2 を組み込むと、ユーザーは以下の流れで外部リンク型決済ページにアクセスし、支払いを行います。

  1. 加盟店サーバーの /create-checkout-session エンドポイントで Checkout Session を生成し、Checkout Session オブジェクトのレスポンスの中にある session.url へユーザーをリダイレクトします。
  2. ユーザーは Checkout v2 の決済ページで支払い情報を入力して決済を行います。
  3. 支払い完了後、PAY.JP が Webhook で結果を通知します。
  4. 支払いが成功した場合は success_url で指定したページへ、失敗した場合は cancel_url で指定したページへ自動的にリダイレクトします。

上記のフロー図において、加盟店サーバーは Checkout Session を作成後、HTTPステータスコード 303 を使用してユーザーのブラウザを session.url にリダイレクトする必要があります。これにより、ユーザーは PAY.JP の決済ページに遷移し、安全に支払いを完了できます。

Checkout Session の状態遷移

Checkout SessionAPIは作成から完了または期限切れまで、以下の3つの状態を持ちます。

状態の種類

状態説明
openCheckout Session 作成時の初期状態。この状態でのみ支払いを受け付けられます
complete支払いまたは設定フローが正常に完了した状態
expiredCheckout Session の有効期限が切れた状態

支払いを受け付ける

1. サーバーサイドで Checkout v2 の支払いページの URL を生成する

Checkout Session を作成することで、ユーザーをリダイレクトさせるための決済ページのURLを生成できます。

この決済ページのURLを生成する際に、line_items パラメーターに商品名、価格、数量などの詳細を設定します。 Checkout v2 はこの情報をもとに決済ページを生成して提供します。商品や価格の考え方については、商品と価格のページで詳しく説明しています。

Checkout Session API では、決済の結果によってユーザーをリダイレクトさせる URL を事前に設定する必要があります。 決済が成功した場合は success_url で指定したページへ、ユーザーが途中で決済をキャンセルした場合は cancel_url で指定したページへ自動的にリダイレクトされます。 決済失敗時はリダイレクトはされず、Checkout v2 の画面上にエラーメッセージが表示されます。

Checkout SessionAPI API を使用して Checkout v2 の決済ページを作成していきます。 作成した Checkout Session のレスポンスに含まれる url がユーザーをリダイレクトさせる決済ページの URL になります。

Checkout Session API を使用して Checkout v2 の決済ページを作成する
app.post('/create-checkout-session', async (req, res) => {
  try {
    const { data: session } = await createCheckoutSession({
      client,
      body: {
        line_items: [
          {
            price: 'price_123abc', // 商品の価格ID
            quantity: 1  // 数量
          }
        ],
        mode: 'payment',
        success_url: 'https://localhost:3000/success',
        cancel_url: 'https://localhost:3000/cancel',
        metadata: {
          order_id: 'order_12345', // 必要であれば加盟店側の注文IDや顧客IDなどを保存しておく
          customer_id: 'customer_67890'
        }
      }
    })
    res.redirect(303, session.url)
  } catch (error) {
    console.error('Checkout session creation failed:', error)
    res.status(500).json({
      error: '支払い画面の生成に失敗しました。'
    })
  }
})

2. ユーザーを Checkout v2 にリダイレクトする

ユーザーを Checkout v2 の決済ページにリダイレクトするための画面を作成します。 先ほど作成したサーバーサイドのエンドポイント (/create-checkout-session) にリクエストを送信することで Checkout Session を作成し、作成した Checkout Session のレスポンスに含まれる url へユーザーをリダイレクトさせます。

ユーザーを Checkout v2 の決済ページにリダイレクトする画面
<form action="/create-checkout-session" method="POST">
  <button type="submit">支払う</button>
</form>

3. 支払い完了時の Webhook を受け取る

Checkout v2 で支払いが完了すると、ユーザーは success_url で指定したページへ自動的にリダイレクトされます。 支払いは非同期で実行され、ユーザーが success_url に到達した時点ではまだ支払いが完了していない可能性があるため、 Webhook で結果を受信して初めて「支払いが完了した」と判断します。

完了が確認できるまでは、支払い処理中の状態として扱い、商品の発送などの重要な処理は行わないようにします。 Webhook での完了処理については、イベントと Webhook のページで詳しく説明しています。

Webhook エンドポイントを登録

支払い完了通知を受け取るために、Webhook エンドポイントを登録します。

1. Webhook エンドポイントを登録

PAY.JP ダッシュボードで Webhook エンドポイントを登録

支払い完了通知を受け取る Webhook エンドポイントを登録します。

  1. PAY.JP ダッシュボード のWebhook を開く
  2. [Webhookを追加] をクリック
  3. 以下を設定
    • URL: https://example.com/webhook
    • [テストモード] か [ライブモード]を選択
  4. [登録] をクリック
  5. 表示される発信元トークンwhook_xxxxx)をコピー

PAY.JP CLI で Webhook エンドポイントを登録

ローカルの開発環境などでは payjp-cli を使うとインターネットに公開されていない環境でも Webhook を受け取ることができます。

payjp listen --forward-to http://localhost:3000/webhook/payjp

2. Webhook を受信するコードを実装

最後に success_url での完了画面と、Webhook での支払い完了時の処理を実装します。

const WEBHOOK_SECRET = process.env.PAYJP_WEBHOOK_SECRET;  // Webhook発信元トークン

// success_url で完了画面
app.get('/success', (req, res) => {
  res.send(`
    <h1>決済が完了しました!</h1>
    <p>ご利用ありがとうございました。</p>
  `)
});

// Webhook 受信エンドポイント
app.post('/webhook', (req, res) => {
  // Webhook Tokenの検証
  const receivedToken = req.headers['x-payjp-webhook-token'];

  if (receivedToken !== WEBHOOK_SECRET) {
    return res.status(401).json({ error: 'Invalid webhook token' });
  }

  const event = req.body;

  // 支払い完了イベントの処理
  if (event.type === 'checkout.session.completed') {
    const session = event.data;
    const orderId = session.metadata.order_id;

    console.log('支払い完了:', orderId);
    // これ以降で商品の発送などの重要な処理を実行します
  }

  res.json({ received: true });
});

3. テストして動作確認

実際の支払いフローでテストを行います。テストカードを使用して正常に支払いが完了することを確認してください。 テストモードで使用できるテストカードはテストカードをご覧ください。