DEV Community

Cover image for 2Checkout API 決済処理 徹底ガイド (2026年)
Akira
Akira

Posted on • Originally published at apidog.com

2Checkout API 決済処理 徹底ガイド (2026年)

TL;DR

2Checkout API(現Verifone)は、開発者が決済処理・サブスクリプション管理・Eコマース取引をプログラムで自動化できる強力なRESTful APIです。本記事では、初期設定からWebhookの実装・エラー処理まで、プロダクション品質の統合を行うための具体的な手順とコード例を網羅します。

Apidogを今すぐ試す


はじめに

決済連携は、オンラインビジネスの収益と成長に直結します。2Checkout API(Verifone)は世界45,000社以上の決済を支え、年間数十億ドル規模のトランザクションを処理しています。本記事では、認証、決済処理、サブスクリプション管理、Webhook、エラー処理まで、実装手順を徹底的に解説します。

💡 ApidogはAPI連携テストを簡素化します。2Checkoutのエンドポイントのテスト、Webhookペイロードの検証、認証のデバッグもワークスペースで完結。OpenAPI仕様インポートやレスポンスのモック、チーム共有も可能です。

2Checkout APIとは?

2Checkout(現Verifone Digital Commerce)は、RESTfulな決済・サブスクリプションAPIを提供します。主な用途は以下です。

  • 単発/定期支払い
  • 顧客・商品管理
  • 注文ライフサイクル追跡
  • 返金・チャージバック処理
  • 税・コンプライアンス自動化
  • 100通貨以上の多通貨決済

主な機能

機能 説明
RESTful設計 JSONペイロード+標準HTTPメソッド(GET/POST/PUT/DELETE)
サンドボックス テスト用環境での決済処理
Webhook 注文イベントのリアルタイム通知
トークン化 カード情報を保存せず安全に決済
グローバル対応 PCI DSS, GDPR, PSD2, 3Dセキュア2.0など国際規格に対応

APIアーキテクチャ概要

バージョン管理されたREST APIです。

https://api.2checkout.com/1/
https://api.2checkout.com/2/
Enter fullscreen mode Exit fullscreen mode

バージョン2はサブスクリプション・Webhookが強化されています。


はじめに:認証設定

ステップ1:2Checkoutアカウント作成

  1. 2Checkout (Verifone) サインアップページで登録
  2. ビジネス確認(書類提出)
  3. アカウント承認(24-48時間)
  4. コントロールパネルからAPI認証情報を取得

ステップ2:APIキー取得

コントロールパネル→インテグレーション > APIキーで以下を取得:

  • プライベートAPIキー(サーバー認証用・厳重管理)
  • パブリックAPIキー(クライアントのトークン化用)
  • Webhookシークレット(Webhook署名検証用)

セキュリティ注意: APIキーはバージョン管理に含めず、環境変数管理を徹底。

# .envファイル例
TWOCHECKOUT_PRIVATE_KEY="your_private_key_here"
TWOCHECKOUT_PUBLIC_KEY="your_public_key_here"
TWOCHECKOUT_WEBHOOK_SECRET="your_webhook_secret_here"
Enter fullscreen mode Exit fullscreen mode

ステップ3:サンドボックスと本番環境

環境 ベースURL ユースケース
サンドボックス https://sandbox.2checkout.com/api/ 開発・テスト
本番 https://api.2checkout.com/ ライブ運用

開発時は必ずサンドボックスの認証情報とベースURLを使うこと。

ステップ4:認証方法

方法1:APIキー認証(推奨)

リクエストヘッダーにプライベートキーを設定。

const response = await fetch('https://api.2checkout.com/1/orders', {
  method: 'GET',
  headers: {
    'X-Api-Key': process.env.TWOCHECKOUT_PRIVATE_KEY,
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  }
});
Enter fullscreen mode Exit fullscreen mode

方法2:HMAC署名認証

より高度なセキュリティ向け。HMAC-SHA256で署名。

const crypto = require('crypto');

function generateSignature(payload, privateKey) {
  const hash = crypto
    .createHmac('sha256', privateKey)
    .update(JSON.stringify(payload))
    .digest('hex');
  return hash;
}

// 使用例
const payload = { order_id: '12345', amount: 99.99 };
const signature = generateSignature(payload, privateKey);

const response = await fetch('https://api.2checkout.com/1/orders', {
  method: 'POST',
  headers: {
    'X-Api-Key': process.env.TWOCHECKOUT_PRIVATE_KEY,
    'X-Signature': signature,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(payload)
});
Enter fullscreen mode Exit fullscreen mode

api-signature


支払い処理:コアエンドポイント

一度限りの注文を作成

/ordersエンドポイントで単発決済を処理。

const createOrder = async (customerData, productData) => {
  const payload = {
    currency: 'USD',
    customer: {
      email: customerData.email,
      first_name: customerData.firstName,
      last_name: customerData.lastName,
      phone: customerData.phone,
      billing_address: {
        address1: customerData.address,
        city: customerData.city,
        state: customerData.state,
        zip: customerData.zip,
        country: customerData.country
      }
    },
    items: [
      {
        name: productData.name,
        quantity: productData.quantity,
        price: productData.price,
        product_code: productData.sku
      }
    ],
    payment_method: {
      type: 'card',
      card_token: customerData.cardToken // クライアント側トークン化
    }
  };

  const response = await fetch('https://api.2checkout.com/1/orders', {
    method: 'POST',
    headers: {
      'X-Api-Key': process.env.TWOCHECKOUT_PRIVATE_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(payload)
  });

  return await response.json();
};
Enter fullscreen mode Exit fullscreen mode

レスポンス例

{
  "order_id": "ORD-2026-001234",
  "status": "approved",
  "amount": 99.99,
  "currency": "USD",
  "customer_id": "CUST-789456",
  "transaction_id": "TXN-9876543210",
  "created_at": "2026-03-20T10:30:00Z"
}
Enter fullscreen mode Exit fullscreen mode

支払いエラーの処理

必ずエラー処理を実装。具体例:

try {
  const result = await createOrder(customer, product);

  if (result.error) {
    switch (result.error.code) {
      case 'CARD_DECLINED':
        // 別カードを促す
        break;
      case 'INSUFFICIENT_FUNDS':
        // 資金不足メッセージ
        break;
      case 'INVALID_CVV':
        // CVV再入力
        break;
      default:
        console.error('Payment failed:', result.error);
    }
  }
} catch (error) {
  // ネットワーク/サーバーエラー
  console.error('API request failed:', error);
}
Enter fullscreen mode Exit fullscreen mode

一般的なエラーコード

エラーコード HTTP 説明 解決策
CARD_DECLINED 402 カード拒否 別の支払い方法を促す
INVALID_CARD 400 カード番号無効 入力値検証
EXPIRED_CARD 400 有効期限切れ 新しい有効期限を要求
INVALID_CVV 400 CVV不一致 CVV再入力を要求
INSUFFICIENT_FUNDS 402 資金不足 代替支払い提案
DUPLICATE_ORDER 409 重複注文 重複チェック
INVALID_CURRENCY 400 通貨サポート外 通貨コード確認
API_KEY_INVALID 401 認証失敗 APIキー確認

顧客管理

サブスクリプションやリピート購入に不可欠な顧客APIの使い方。

顧客の作成

const createCustomer = async (customerData) => {
  const payload = {
    email: customerData.email,
    first_name: customerData.firstName,
    last_name: customerData.lastName,
    phone: customerData.phone,
    company: customerData.company,
    billing_address: {
      address1: customerData.address,
      address2: customerData.address2 || '',
      city: customerData.city,
      state: customerData.state,
      zip: customerData.zip,
      country: customerData.country
    },
    shipping_address: customerData.shippingAddress || null,
    tax_exempt: false,
    language: 'en'
  };

  const response = await fetch('https://api.2checkout.com/1/customers', {
    method: 'POST',
    headers: {
      'X-Api-Key': process.env.TWOCHECKOUT_PRIVATE_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(payload)
  });

  return await response.json();
};
Enter fullscreen mode Exit fullscreen mode

顧客レスポンス例

{
  "customer_id": "CUST-2026-123456",
  "email": "john.doe@example.com",
  "first_name": "John",
  "last_name": "Doe",
  "created_at": "2026-03-20T10:00:00Z",
  "updated_at": "2026-03-20T10:00:00Z",
  "payment_methods": [],
  "subscriptions": [],
  "order_history": []
}
Enter fullscreen mode Exit fullscreen mode

顧客詳細の取得

const getCustomer = async (customerId) => {
  const response = await fetch(
    `https://api.2checkout.com/1/customers/${customerId}`,
    {
      method: 'GET',
      headers: {
        'X-Api-Key': process.env.TWOCHECKOUT_PRIVATE_KEY,
        'Content-Type': 'application/json'
      }
    }
  );

  return await response.json();
};
Enter fullscreen mode Exit fullscreen mode

顧客情報の更新

const updateCustomer = async (customerId, updates) => {
  const response = await fetch(
    `https://api.2checkout.com/1/customers/${customerId}`,
    {
      method: 'PUT',
      headers: {
        'X-Api-Key': process.env.TWOCHECKOUT_PRIVATE_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(updates)
    }
  );

  return await response.json();
};
Enter fullscreen mode Exit fullscreen mode

顧客の削除

const deleteCustomer = async (customerId) => {
  const response = await fetch(
    `https://api.2checkout.com/1/customers/${customerId}`,
    {
      method: 'DELETE',
      headers: {
        'X-Api-Key': process.env.TWOCHECKOUT_PRIVATE_KEY
      }
    }
  );

  return response.status === 204;
};
Enter fullscreen mode Exit fullscreen mode

注: 未払い残高やアクティブなサブスクリプションがある場合は削除できません。まずサブスクリプションをキャンセルしてください。


高度な統合パターン

べき等性で安全なリトライ

X-Idempotency-Keyヘッダーを活用し、重複請求を防止。

const createIdempotentOrder = async (payload, idempotencyKey) => {
  const response = await fetch('https://api.2checkout.com/1/orders', {
    method: 'POST',
    headers: {
      'X-Api-Key': process.env.TWOCHECKOUT_PRIVATE_KEY,
      'Content-Type': 'application/json',
      'X-Idempotency-Key': idempotencyKey
    },
    body: JSON.stringify(payload)
  });

  return await response.json();
};

// 一意なキー生成例
const idempotencyKey = `order_${userId}_${Date.now()}`;
Enter fullscreen mode Exit fullscreen mode

3Dセキュア2.0認証 (EU向け)

const createOrderWith3DS = async (payload) => {
  const response = await fetch('https://api.2checkout.com/1/orders', {
    method: 'POST',
    headers: {
      'X-Api-Key': process.env.TWOCHECKOUT_PRIVATE_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      ...payload,
      three_ds: {
        enabled: true,
        challenge_required: 'preferred', // EU顧客は'mandatory'
        notification_url: 'https://your-site.com/3ds-callback'
      }
    })
  });

  const result = await response.json();

  if (result.three_ds_redirect_url) {
    res.redirect(result.three_ds_redirect_url);
  }

  return result;
};
Enter fullscreen mode Exit fullscreen mode

多通貨価格の取得

const getLocalizedPrice = async (basePrice, targetCurrency) => {
  const response = await fetch(
    `https://api.2checkout.com/1/rates?from=USD&to=${targetCurrency}`,
    {
      headers: {
        'X-Api-Key': process.env.TWOCHECKOUT_PRIVATE_KEY
      }
    }
  );

  const rates = await response.json();
  return basePrice * rates.rate;
};

const eurPrice = await getLocalizedPrice(99.99, 'EUR');
console.log(`Price: EUR ${eurPrice.toFixed(2)}`);
Enter fullscreen mode Exit fullscreen mode

サブスクリプションアップグレードの日割り計算

const upgradeSubscription = async (subscriptionId, newPlanId) => {
  const response = await fetch(
    `https://api.2checkout.com/1/subscriptions/${subscriptionId}/upgrade`,
    {
      method: 'POST',
      headers: {
        'X-Api-Key': process.env.TWOCHECKOUT_PRIVATE_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        plan_id: newPlanId,
        proration: 'immediate',
        invoice_proration: true
      })
    }
  );

  return await response.json();
};
Enter fullscreen mode Exit fullscreen mode

一般的な問題のトラブルシューティング

Webhookが届かない

  • 診断: 2CheckoutダッシュボードでWebhookログ確認
  • 対策:
    1. エンドポイントは5秒以内に200 OKを返す
    2. SSL有効 (HTTPS必須)
    3. 2CheckoutのIP範囲をホワイトリスト
    4. 署名検証ロジックの見直し
    5. Webhookシミュレータで事前テスト

サンドボックスのテスト支払い失敗

  • サンドボックス専用APIキー・ベースURLを必ず使う
  • 正しいテストカード番号利用
  • サンドボックスアカウントの有効性確認

サブスクリプションの更新が失敗する

  • 顧客の支払い方法有効期限を確認
  • コントロールパネルの督促設定を見直し
  • subscription.payment_failed Webhookを確認
  • auto_renewフラグの有効化

通貨換算の不一致

  • 2Checkoutは日次為替レートを利用
  • 「概算」表示+レートの有効期限設定
  • 顧客の現地通貨で取引保存

AVS(住所認証)の失敗

  • 住所オートコンプリート利用
  • 郵便番号必須化
  • ソフトAVS
  • 顧客による住所修正UI提供

サブスクリプション管理

2Checkoutの定期課金APIを利用したワークフロー例。

サブスクリプション作成

const createSubscription = async (customerId, planId) => {
  const payload = {
    customer_id: customerId,
    plan_id: planId,
    start_date: new Date().toISOString(),
    billing_cycle: 'monthly',
    payment_method: {
      type: 'card',
      card_token: 'tok_card_tokenized'
    },
    options: {
      trial_days: 14,
      auto_renew: true
    }
  };

  const response = await fetch('https://api.2checkout.com/1/subscriptions', {
    method: 'POST',
    headers: {
      'X-Api-Key': process.env.TWOCHECKOUT_PRIVATE_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(payload)
  });

  return await response.json();
};
Enter fullscreen mode Exit fullscreen mode

サブスクリプションレスポンス

{
  "subscription_id": "SUB-2026-567890",
  "status": "active",
  "plan_id": "PLAN-PREMIUM-MONTHLY",
  "customer_id": "CUST-789456",
  "current_period_start": "2026-03-20T00:00:00Z",
  "current_period_end": "2026-04-20T00:00:00Z",
  "trial_end": "2026-04-03T00:00:00Z",
  "amount": 29.99,
  "currency": "USD"
}
Enter fullscreen mode Exit fullscreen mode

サブスクリプションの更新・キャンセル

const updateSubscription = async (subscriptionId, updates) => {
  const payload = { ...updates };

  const response = await fetch(
    `https://api.2checkout.com/1/subscriptions/${subscriptionId}`,
    {
      method: 'PUT',
      headers: {
        'X-Api-Key': process.env.TWOCHECKOUT_PRIVATE_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(payload)
    }
  );

  return await response.json();
};

const cancelSubscription = async (subscriptionId, reason = '') => {
  const payload = {
    cancel_at_period_end: false,
    reason: reason
  };

  const response = await fetch(
    `https://api.2checkout.com/1/subscriptions/${subscriptionId}/cancel`,
    {
      method: 'POST',
      headers: {
        'X-Api-Key': process.env.TWOCHECKOUT_PRIVATE_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(payload)
    }
  );

  return await response.json();
};
Enter fullscreen mode Exit fullscreen mode

Webhook連携:リアルタイムイベント処理

Webhookは支払い・サブスクリプションイベントの即時通知に必須。以下の手順で実装。

ステップ1:Webhookエンドポイント設定

  1. コントロールパネル→インテグレーション > Webhooks
  2. エンドポイントURL(HTTPS)を登録
  3. 必要なイベントを選択
  4. Webhookシークレットを保存

ステップ2:Webhookハンドラー実装

const express = require('express');
const crypto = require('crypto');
const app = express();

app.post('/webhooks/2checkout', express.raw({ type: 'application/json' }), async (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const payload = req.body;

  const isValid = verifyWebhookSignature(payload, signature, process.env.TWOCHECKOUT_WEBHOOK_SECRET);

  if (!isValid) {
    console.error('Invalid webhook signature');
    return res.status(401).send('Unauthorized');
  }

  const event = JSON.parse(payload.toString());

  switch (event.type) {
    case 'order.created':
      await handleOrderCreated(event.data);
      break;
    case 'order.approved':
      await handleOrderApproved(event.data);
      break;
    case 'order.declined':
      await handleOrderDeclined(event.data);
      break;
    case 'subscription.created':
      await handleSubscriptionCreated(event.data);
      break;
    case 'subscription.renewed':
      await handleSubscriptionRenewed(event.data);
      break;
    case 'subscription.cancelled':
      await handleSubscriptionCancelled(event.data);
      break;
    case 'refund.processed':
      await handleRefundProcessed(event.data);
      break;
    default:
      console.log('Unhandled event type:', event.type);
  }

  res.status(200).send('OK');
});

function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature, 'hex'),
    Buffer.from(expectedSignature, 'hex')
  );
}
Enter fullscreen mode Exit fullscreen mode

主要なWebhookイベント

イベントタイプ トリガー 必要なアクション
order.created 新規注文 確認メール送信
order.approved 支払い成功 履行・アクセス許可
order.declined 支払い失敗 顧客通知・リトライ
subscription.renewed 定期支払い アクセス延長
subscription.payment_failed 支払い失敗 督促処理
subscription.cancelled キャンセル 期間終了時アクセス取り消し
refund.processed 返金処理 残高更新
chargeback.received チャージバック 証拠収集

Webhookベストプラクティス

  1. 署名検証は必須(スプーフィング防止)
  2. 即時200 OK返却(再送防止)
  3. 非同期処理(バックグラウンドキュー)
  4. べき等性実装(重複イベント対応)
  5. 全イベントをログ(トラブル時の証跡)

統合のテスト

サンドボックス環境利用

const BASE_URL = 'https://sandbox.2checkout.com/api/1';

const TEST_CARDS = {
  APPROVED: '4111111111111111',
  DECLINED: '4000000000000002',
  INSUFFICIENT_FUNDS: '4000000000009995',
  EXPIRED_CARD: '4000000000000069'
};

const TEST_ADDRESS = {
  country: 'US',
  zip: '90210'
};
Enter fullscreen mode Exit fullscreen mode

ローカルでWebhookテスト

# ngrokインストール
npm install -g ngrok

# サーバー起動
node server.js

# 公開
ngrok http 3000
# ngrokのURLを2Checkout Webhook設定に登録
Enter fullscreen mode Exit fullscreen mode

APIテストにはApidog

  • OpenAPI仕様のインポート
  • テストシナリオ作成
  • レスポンスモック
  • Webhook検証
  • チーム共有・環境変数切替も簡単

本番環境デプロイメントチェックリスト

  • [ ] サンドボックス→本番APIキー切替
  • [ ] ベースURLを https://api.2checkout.com/ に変更
  • [ ] Webhook署名検証有効化
  • [ ] 支払い失敗監視
  • [ ] リトライロジック実装
  • [ ] 返金・チャージバックフロー検証
  • [ ] PCI DSS準拠(トークン化利用推奨)
  • [ ] EU顧客向け3Dセキュア2.0有効化
  • [ ] ロギング・監査証跡設定
  • [ ] 障害時ランブック作成

監視とアラート例

// 支払い成功率監視
const successRate = approvedOrders / totalOrders * 100;

if (successRate < 95) {
  sendAlert('支払い成功率が95%を下回りました');
}

// エラーコードごとの集計
const errorBreakdown = errors.reduce((acc, err) => {
  acc[err.code] = (acc[err.code] || 0) + 1;
  return acc;
}, {});

if (errorBreakdown['CARD_DECLINED'] > threshold) {
  sendAlert('カード拒否の急増を検知');
}
Enter fullscreen mode Exit fullscreen mode

実世界のユースケース

Eコマースストア連携

  • 100通貨以上自動対応
  • カート放棄率23%削減
  • EU VAT自動処理
  • 年間200万ドル超処理
  • 最初はホスト型チェックアウト→API直結に移行

SaaSサブスクリプション連携

  • 5,000+アクティブサブスクリプション管理
  • アップグレード時の日割り課金
  • 支払い失敗時の督促自動化
  • Webhook駆動のアクセス制御で解約率15%削減

結論

2Checkout APIを使えば、グローバル決済・サブスクリプション管理の全てが実装可能です。

実装時のポイント:

  • 開発/テストは必ずサンドボックス環境で
  • WebhookはHMAC署名検証を徹底
  • エラーコードごとに適切な処理
  • サブスクリプション全フローを網羅テスト
  • プロダクションでは支払いメトリクス常時監視
  • APIテストとチーム連携にはApidogを活用

FAQセクション

2Checkout APIとは何ですか?

2Checkout API(Verifone)は、決済処理・サブスクリプション・返金・Eコマース自動化のためのRESTful APIです。JSONペイロード、HMAC認証、リアルタイムWebhookをサポート。

2CheckoutはVerifoneと同じですか?

はい。2CheckoutはVerifoneに買収され、Verifone Digital Commerceへブランド変更されました。API仕様・機能は継続しています。

2Checkout APIキーはどのように取得できますか?

コントロールパネルのインテグレーション > APIキーから、プライベートキー・パブリックキーを生成できます。

2Checkoutにはサンドボックス環境がありますか?

はい。https://sandbox.2checkout.com/api/を利用し、テスト用APIキーで安全に検証できます。

2Checkoutはどのような支払い方法をサポートしていますか?

Visa/Mastercard/Amex/Discover/PayPal/Apple Pay/Google Pay/現地決済など100+の国・通貨に対応。

Webhookを安全に処理するには?

X-Webhook-SignatureをWebhookシークレットでHMAC-SHA256検証。イベントは非同期で処理し、即時200 OKを返すこと。

サブスクリプションの支払いが失敗した場合、どうなりますか?

subscription.payment_failed Webhookが発火。再試行ロジック後、失敗が続くとsubscription.cancelled Webhookが送信されます。

2CheckoutはPCI DSSに準拠していますか?

はい。PCI DSSレベル1認定。トークン化でカード情報をサーバーに保持せず、PCI範囲を最小化可能です。

サンドボックスでサブスクリプションをテストできますか?

はい。ライフサイクル全体(トライアル・更新・アップグレード等)のテストができます。テストカード4111111111111111利用。

API経由で払い戻しを処理するには?

注文IDと金額を/refundsにPOST。完了時はrefund.processed Webhookで通知されます。

Top comments (0)