DEV Community

Cover image for 2026年版 iPay API 決済連携ガイド
Akira
Akira

Posted on • Originally published at apidog.com

2026年版 iPay API 決済連携ガイド

要約

iPay APIは、開発者が決済処理・請求書発行・金融取引をプログラムで統合できるRESTful APIです。OAuth 2.0またはAPIキー認証で利用し、支払い・返金・取引・照合のためのエンドポイントを提供。PCI DSS要件やレート制限にも準拠しています。このガイドは、認証設定・決済処理・Webhook統合・セキュリティ・デプロイ戦略の実装方法をステップごとに解説します。

今すぐApidogを試してみよう


はじめに

世界のデジタル決済処理市場は年間8兆ドルを超えています。Eコマース、SaaS、マーケットプレイスなどの開発者にとって、決済API統合は必須です。安全かつコンプライアンス対応で顧客からの支払いを受け入れるため、失敗時の自動再試行、照合、詐欺検出などの自動化が重要です。

このガイドでは、決済API統合プロセスの全体像を具体的な手順・サンプルコードとともに解説します。認証・決済・返金・Webhook・PCI DSS・デプロイまで、実装に役立つノウハウをまとめました。

💡 Apidogで決済APIテストを効率化

Apidogはサンドボックス決済のテスト、Webhook署名検証、レスポンスチェック、インポート/モック/シナリオ共有まで対応。実装前後の統合テストに最適です。

注意: 本ガイドはiPayおよび類似決済APIの一般的な実装パターンを解説しています。エンドポイントや認証詳細は必ず公式ドキュメントで確認してください。


iPay APIとは?

iPayのような決済APIは、金融取引を処理するRESTfulインターフェースです。主なユースケースは:

  • 支払いの承認・確定
  • 返金・チャージバック
  • 取引履歴・レポート
  • 顧客トークン化(カード保存)
  • サブスクリプション・定期請求
  • 請求書生成・管理
  • 照合・決済
  • 不正検出・防止

主な機能

機能 説明
RESTful API JSONベースのエンドポイント
OAuth 2.0 + APIキー 安全な認証
Webhook リアルタイム決済通知
トークン化 安全なカード保存
3Dセキュア SCA準拠
PCI DSS レベル1準拠
多通貨対応 100+通貨
不正対策ツール リスクスコアリング等

支払いフローの概要

┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│   Customer  │───▶│   Merchant  │───▶│  Payment    │
│   (Browser) │    │   (Server)  │    │  Gateway    │
└─────────────┘    └─────────────┘    └─────────────┘
     │                    │                    │
     │  1. Enter Card     │                    │
     │───────────────────▶│                    │
     │                    │                    │
     │  2. Tokenize       │                    │
     │───────────────────▶│  3. Create Intent  │
     │                    │───────────────────▶│
     │                    │                    │
     │                    │  4. Confirm Payment│
     │                    │───────────────────▶│
     │                    │                    │
     │                    │  5. Result         │
     │                    │◀───────────────────│
     │                    │                    │
     │  6. Receipt        │                    │
     │◀───────────────────│                    │
Enter fullscreen mode Exit fullscreen mode

API環境

環境 URL 用途
サンドボックス https://sandbox.ipay.com/api 開発・テスト
本番環境 https://api.ipay.com/api ライブ取引

開始する: 認証設定

ステップ1: iPayアカウントの作成

  1. iPay販売者登録ページにアクセス
  2. 事業確認(KYB)を完了
  3. 必要書類を提出(事業登録/銀行口座/身分証明)
  4. 承認を待つ(1~3営業日)

ステップ2: API資格情報の取得

  1. iPayマーチャントダッシュボードにログイン
  2. 設定 > APIキー
  3. 新しいAPIキーを作成
  4. 資格情報を安全にコピーし、環境変数で管理
# .env(git管理しないこと)
IPAY_API_KEY="live_xxxxxxxxxxxxxxxxxxxx"
IPAY_API_SECRET="secret_xxxxxxxxxxxxxxxxxxxx"
IPAY_WEBHOOK_SECRET="whsec_xxxxxxxxxxxxxxxxxxxx"
Enter fullscreen mode Exit fullscreen mode

セキュリティ注意: サンドボックスと本番で異なるキーを必ず利用。

ステップ3: 認証方法を理解する

方法 最適用途 セキュリティ
Basic認証 サーバー間通信
OAuth 2.0 マルチテナント より高
JWT マイクロサービス

ステップ4: 認証済みAPIコールの実装

APIクライアントをリユーザブルに実装します。

const IPAY_BASE_URL = process.env.IPAY_SANDBOX
  ? 'https://sandbox.ipay.com/api'
  : 'https://api.ipay.com/api';

const ipayRequest = async (endpoint, options = {}) => {
  const apiKey = process.env.IPAY_API_KEY;
  const apiSecret = process.env.IPAY_API_SECRET;
  const authHeader = Buffer.from(`${apiKey}:${apiSecret}`).toString('base64');

  const response = await fetch(`${IPAY_BASE_URL}${endpoint}`, {
    ...options,
    headers: {
      'Authorization': `Basic ${authHeader}`,
      'Content-Type': 'application/json',
      'Idempotency-Key': options.idempotencyKey || generateIdempotencyKey(),
      ...options.headers
    }
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`iPay API Error: ${error.message}`);
  }

  return response.json();
};

function generateIdempotencyKey() {
  return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}

// 使用例
const account = await ipayRequest('/account');
console.log(`Merchant: ${account.business_name}`);
Enter fullscreen mode Exit fullscreen mode

決済処理

支払いインテントの作成

const createPayment = async (paymentData) => {
  const payment = {
    amount: paymentData.amount,
    currency: paymentData.currency || 'USD',
    customer: paymentData.customerId,
    payment_method: paymentData.paymentMethodId,
    confirm: true,
    description: paymentData.description,
    metadata: {
      orderId: paymentData.orderId,
      customerId: paymentData.customerId
    },
    capture_method: paymentData.captureMethod || 'automatic',
    statement_descriptor: paymentData.statementDescriptor || 'MYCOMPANY'
  };

  const response = await ipayRequest('/payments', {
    method: 'POST',
    body: JSON.stringify(payment),
    idempotencyKey: paymentData.idempotencyKey
  });

  return response;
};

// 使用例
const payment = await createPayment({
  amount: 2999, // $29.99
  currency: 'USD',
  customerId: 'cus_12345',
  paymentMethodId: 'pm_67890',
  description: 'Order #ORD-001',
  orderId: 'ORD-001',
  statementDescriptor: 'MYCOMPANY INC'
});

console.log(`支払いステータス: ${payment.status}`);
console.log(`支払いID: ${payment.id}`);
Enter fullscreen mode Exit fullscreen mode

支払いステータスフロー

requires_payment_method → requires_confirmation → requires_action
                         → processing → requires_capture → succeeded
                                                        → failed
                                                        → canceled
Enter fullscreen mode Exit fullscreen mode

支払い方法

方法 種類 用途
card クレジット/デビット 標準支払い
bank_transfer ACH, SEPA 低手数料送金
digital_wallet Apple/Google Pay モバイル決済
buy_now_pay_later Klarna, Afterpay等 分割払い

カード情報のトークン化

const tokenizeCard = async (cardData) => {
  // 生カード情報はサーバー送信禁止。必ずクライアントでトークン化。
  const response = await fetch(`${IPAY_BASE_URL}/tokens`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${CLIENT_PUBLISHABLE_KEY}`
    },
    body: JSON.stringify({
      card: {
        number: cardData.number,
        exp_month: cardData.expMonth,
        exp_year: cardData.expYear,
        cvc: cardData.cvc
      }
    })
  });

  const token = await response.json();
  return token; // token.idをサーバーへ渡す
};

// サーバー側: トークンで支払い方法作成
const createPaymentMethod = async (tokenId, customerId) => {
  const response = await ipayRequest('/payment_methods', {
    method: 'POST',
    body: JSON.stringify({
      type: 'card',
      token: tokenId,
      customer: customerId
    })
  });

  return response;
};
Enter fullscreen mode Exit fullscreen mode

3Dセキュア認証(SCA)

const createPaymentWith3DS = async (paymentData) => {
  const payment = await createPayment({
    ...paymentData,
    confirmation_token: true
  });

  if (payment.status === 'requires_action') {
    // クライアントで3Dセキュア認証を実行
    return {
      requiresAction: true,
      clientSecret: payment.client_secret,
      nextAction: payment.next_action
    };
  }

  return { success: true, payment };
};

// クライアント: iPay.jsやSDKで認証チャレンジを処理
Enter fullscreen mode Exit fullscreen mode

返金管理

全額返金

const refundPayment = async (paymentId, reason = null) => {
  const refund = {
    payment: paymentId,
    reason: reason || 'requested_by_customer'
  };

  const response = await ipayRequest('/refunds', {
    method: 'POST',
    body: JSON.stringify(refund),
    idempotencyKey: `refund_${paymentId}_${Date.now()}`
  });

  return response;
};

// 使用例
const refund = await refundPayment('pay_12345', 'duplicate');
console.log(`返金ステータス: ${refund.status}`);
console.log(`返金ID: ${refund.id}`);
Enter fullscreen mode Exit fullscreen mode

一部返金

const partialRefund = async (paymentId, amount, reason = null) => {
  const refund = {
    payment: paymentId,
    amount: amount,
    reason: reason || 'requested_by_customer'
  };

  const response = await ipayRequest('/refunds', {
    method: 'POST',
    body: JSON.stringify(refund),
    idempotencyKey: `refund_${paymentId}_${amount}_${Date.now()}`
  });

  return response;
};

// 使用例
const refund = await partialRefund('pay_12345', 1500, 'partial_ship');
console.log(`返金済み: $${refund.amount / 100}`);
Enter fullscreen mode Exit fullscreen mode

返金理由コード

理由コード 説明
duplicate 重複請求
fraudulent 不正取引
requested_by_customer 顧客要求
order_canceled 注文キャンセル
product_not_received 商品未配達
product_not_as_described 商品説明と異なる

顧客管理

顧客の作成

const createCustomer = async (customerData) => {
  const customer = {
    email: customerData.email,
    name: customerData.name,
    phone: customerData.phone,
    metadata: {
      internalId: customerData.internalId,
      tier: customerData.tier
    }
  };

  const response = await ipayRequest('/customers', {
    method: 'POST',
    body: JSON.stringify(customer)
  });

  return response;
};

// 使用例
const customer = await createCustomer({
  email: 'customer@example.com',
  name: 'John Doe',
  phone: '+1-555-0123',
  internalId: 'USR-12345',
  tier: 'premium'
});

console.log(`顧客が作成されました: ${customer.id}`);
Enter fullscreen mode Exit fullscreen mode

顧客に支払い方法を紐付け

const attachPaymentMethod = async (paymentMethodId, customerId) => {
  const response = await ipayRequest(`/payment_methods/${paymentMethodId}/attach`, {
    method: 'POST',
    body: JSON.stringify({ customer: customerId })
  });

  return response;
};

// 使用例
await attachPaymentMethod('pm_67890', 'cus_12345');
Enter fullscreen mode Exit fullscreen mode

顧客の支払い方法一覧

const getCustomerPaymentMethods = async (customerId) => {
  const response = await ipayRequest(`/customers/${customerId}/payment_methods`);
  return response;
};

// 使用例
const methods = await getCustomerPaymentMethods('cus_12345');
methods.data.forEach(method => {
  console.log(`${method.card.brand} (下4桁: ${method.card.last4})`);
  console.log(`有効期限: ${method.card.exp_month}/${method.card.exp_year}`);
});
Enter fullscreen mode Exit fullscreen mode

Webhook

Webhookの設定手順

  1. iPayダッシュボードにログイン
  2. 開発者 > Webhook
  3. エンドポイントを追加 をクリック
  4. HTTPS URLを入力
  5. イベントを選択して購読

Webhookイベント

イベント トリガー
payment.succeeded 支払い完了時
payment.failed 支払い拒否時
payment.refunded 返金処理完了時
payment.disputed チャージバック申請時
customer.created 新規顧客作成時
customer.subscription.updated サブスクリプション変更時

Webhook受信・署名検証・処理

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

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

  // 署名検証
  const isValid = verifyWebhookSignature(payload, signature, process.env.IPAY_WEBHOOK_SECRET);

  if (!isValid) {
    console.error('無効なWebhook署名');
    return res.status(401).send('Unauthorized');
  }

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

  switch (event.type) {
    case 'payment.succeeded':
      await handlePaymentSucceeded(event.data);
      break;
    case 'payment.failed':
      await handlePaymentFailed(event.data);
      break;
    case 'payment.refunded':
      await handlePaymentRefunded(event.data);
      break;
    case 'payment.disputed':
      await handlePaymentDisputed(event.data);
      break;
    default:
      console.log('未処理のイベントタイプ:', 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')
  );
}

async function handlePaymentSucceeded(data) {
  console.log(`支払いが成功しました: ${data.id}`);
  // 注文ステータス更新
  await db.orders.update(data.metadata.orderId, {
    status: 'paid',
    paymentId: data.id,
    paidAt: new Date()
  });
  await sendOrderConfirmation(data.metadata.orderId);
}

async function handlePaymentFailed(data) {
  console.log(`支払いが失敗しました: ${data.id} - ${data.failure_code}`);
  await sendPaymentFailedEmail(data.customer, data.failure_message);
  await db.orders.update(data.metadata.orderId, {
    status: 'payment_failed',
    failureReason: data.failure_message
  });
}
Enter fullscreen mode Exit fullscreen mode

セキュリティとコンプライアンス

PCI DSS要件

要件 実装例
安全なネットワーク HTTPS・ファイアウォール・設定管理
カードデータ保護 CVV非保存・PAN暗号化
脆弱性管理 定期アップデート・アンチウイルス
アクセス制御 最小特権・MFA・固有ID
監視 ロギング・侵入検知
セキュリティポリシー 文書化・定期トレーニング

セキュリティベストプラクティス

// 1. トークン化利用(生カードデータは触らない)
const token = await tokenizeCard(cardData);

// 2. べき等性キーで重複防止
const idempotencyKey = `pay_${orderId}_${Date.now()}`;

// 3. 金額検証(改ざん防止)
if (req.body.amount !== calculatedAmount) {
  throw new Error('Amount mismatch - possible tampering');
}

// 4. ロギング(カード・機密情報は絶対に記録しない)
logger.info('Payment attempted', {
  orderId,
  amount,
  currency,
  customerId,
  timestamp: new Date().toISOString()
});

// 5. 環境変数でAPIキー管理
const apiKey = process.env.IPAY_API_KEY;

// 6. レート制限
const paymentLimiter = rateLimit({
  windowMs: 60000,
  max: 10 // 1分あたり10回まで
});
Enter fullscreen mode Exit fullscreen mode

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

  • [ ] PCI DSS自己評価質問票を完了
  • [ ] すべてのエンドポイントでHTTPS利用
  • [ ] APIキーはシークレット管理
  • [ ] Webhook署名検証を実装
  • [ ] べき等性対応
  • [ ] ロギング(機密情報除外)
  • [ ] 不正検出ルール設定
  • [ ] 返金・異議申立てフローのテスト
  • [ ] 決済失敗時の運用Runbook作成
  • [ ] 監視・アラート設定
  • [ ] バックアップ決済プロセッサの実装

実世界のユースケース

Eコマースのチェックアウト

  • 課題: 手動決済・高いカゴ落ち率
  • 解決: トークン化カードによるワンページ決済
  • 結果: コンバージョン率35%向上・即時決済

SaaSのサブスクリプション請求

  • 課題: 請求書生成・回収の手間
  • 解決: 自動再試行付サブスク決済
  • 結果: 期日通り95%、管理時間80%削減

マーケットプレイスのエスクロー

  • 課題: 複雑な分割支払い
  • 解決: スケジュール送金付きインテント
  • 結果: 業者への自動支払い、不正減少

まとめ

決済API統合のポイント:

  • 生カードデータは絶対に取り扱わず、トークン化を徹底
  • すべての支払い操作でべき等性実装
  • Webhook署名検証で不正防止
  • PCI DSS完全準拠
  • 本番前はサンドボックスで徹底テスト
  • ApidogでAPIテスト&コラボレーションを効率化

よくある質問

iPay APIで認証するには?

APIキー+シークレットでBasic認証、またはOAuth 2.0(マルチテナント向け)を利用。

顧客のカード情報は保存できますか?

はい、PCI DSS準拠なら可能。必ずトークン化し、iPayのボルトに保管してください。

支払い失敗時のベストプラクティスは?

指数バックオフで再試行・顧客通知・代替支払い手段の提示を実装。

べき等性とは?

同じキーの重複リクエストで結果が重複しないよう保証することで、二重請求を防げます。

テストカードでの支払いテスト方法は?

iPay公式ドキュメントのテストカード番号+サンドボックス環境を使用。

Webhook署名とは?

WebhookがiPayから発信されていることを保証する暗号署名です。


Top comments (0)