TL;DR
2Checkout API(現Verifone)は、開発者が決済処理・サブスクリプション管理・Eコマース取引をプログラムで自動化できる強力なRESTful APIです。本記事では、初期設定からWebhookの実装・エラー処理まで、プロダクション品質の統合を行うための具体的な手順とコード例を網羅します。
はじめに
決済連携は、オンラインビジネスの収益と成長に直結します。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/
バージョン2はサブスクリプション・Webhookが強化されています。
はじめに:認証設定
ステップ1:2Checkoutアカウント作成
- 2Checkout (Verifone) サインアップページで登録
- ビジネス確認(書類提出)
- アカウント承認(24-48時間)
- コントロールパネルから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"
ステップ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'
}
});
方法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)
});
支払い処理:コアエンドポイント
一度限りの注文を作成
/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();
};
レスポンス例
{
"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"
}
支払いエラーの処理
必ずエラー処理を実装。具体例:
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);
}
一般的なエラーコード
| エラーコード | 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();
};
顧客レスポンス例
{
"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": []
}
顧客詳細の取得
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();
};
顧客情報の更新
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();
};
顧客の削除
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;
};
注: 未払い残高やアクティブなサブスクリプションがある場合は削除できません。まずサブスクリプションをキャンセルしてください。
高度な統合パターン
べき等性で安全なリトライ
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()}`;
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;
};
多通貨価格の取得
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)}`);
サブスクリプションアップグレードの日割り計算
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();
};
一般的な問題のトラブルシューティング
Webhookが届かない
- 診断: 2CheckoutダッシュボードでWebhookログ確認
-
対策:
- エンドポイントは5秒以内に200 OKを返す
- SSL有効 (HTTPS必須)
- 2CheckoutのIP範囲をホワイトリスト
- 署名検証ロジックの見直し
- Webhookシミュレータで事前テスト
サンドボックスのテスト支払い失敗
- サンドボックス専用APIキー・ベースURLを必ず使う
- 正しいテストカード番号利用
- サンドボックスアカウントの有効性確認
サブスクリプションの更新が失敗する
- 顧客の支払い方法有効期限を確認
- コントロールパネルの督促設定を見直し
-
subscription.payment_failedWebhookを確認 -
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();
};
サブスクリプションレスポンス
{
"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"
}
サブスクリプションの更新・キャンセル
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();
};
Webhook連携:リアルタイムイベント処理
Webhookは支払い・サブスクリプションイベントの即時通知に必須。以下の手順で実装。
ステップ1:Webhookエンドポイント設定
- コントロールパネル→インテグレーション > Webhooks
- エンドポイントURL(HTTPS)を登録
- 必要なイベントを選択
- 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')
);
}
主要なWebhookイベント
| イベントタイプ | トリガー | 必要なアクション |
|---|---|---|
order.created |
新規注文 | 確認メール送信 |
order.approved |
支払い成功 | 履行・アクセス許可 |
order.declined |
支払い失敗 | 顧客通知・リトライ |
subscription.renewed |
定期支払い | アクセス延長 |
subscription.payment_failed |
支払い失敗 | 督促処理 |
subscription.cancelled |
キャンセル | 期間終了時アクセス取り消し |
refund.processed |
返金処理 | 残高更新 |
chargeback.received |
チャージバック | 証拠収集 |
Webhookベストプラクティス
- 署名検証は必須(スプーフィング防止)
- 即時200 OK返却(再送防止)
- 非同期処理(バックグラウンドキュー)
- べき等性実装(重複イベント対応)
- 全イベントをログ(トラブル時の証跡)
統合のテスト
サンドボックス環境利用
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'
};
ローカルでWebhookテスト
# ngrokインストール
npm install -g ngrok
# サーバー起動
node server.js
# 公開
ngrok http 3000
# ngrokのURLを2Checkout Webhook設定に登録
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('カード拒否の急増を検知');
}
実世界のユースケース
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)