IMPLEMENTATION GUIDE
⚙️ 導入パターン詳細
4種類の導入パターンと実装コード例。プロジェクトの要件に応じて最適な方式を選べます。
📋 4パターン比較
| Client SDK + Server API | Checkout(ホスティング型) | Checkout(埋め込みQR型) | Server SDK のみ | |
|---|---|---|---|---|
| 導入工数 | 中〜高 | 最低 約20分 | 低 約40分 | 中 |
| UI自由度 | ★★★★★ 完全自由 | ★★ 一部カスタマイズ可 | ★★ QR表示のみ | ★★★★★ 自由(バックエンドのみ) |
| PCI-DSS対応 | 非保持化対応 | 完全非保持 | 完全非保持 | 非保持化対応 |
| 主な用途 | EC・予約サイト・会員サービス | サービスサイト・チケット・セルフオーダー | 券売機・自販機・精算機・店頭タブレット | サブスク・バッチ決済 |
| 必要な実装 | JS/iOS/Android SDK + Server API | リダイレクトURLのみ | QR表示処理のみ | Server SDK |
| resource値 | web / ios / android |
Codes API(resource不要) | cpm / mpm |
用途に応じて |
🎨 パターン1: Client SDK + Server API
最も柔軟でブランド体験を統一できる方式。決済画面までフルカスタムUIを提供したい場合に選択。
クライアント側(HTML/JS)
<!-- elepay JavaScript SDK --> <script src="https://js.elepay.io/v1/elepay.js"></script> <script> const elepay = new Elepay('pk_test_xxx', { locale: 'ja' // ja / en / zh-CN / zh-TW / auto }); // 1. サーバーから charge オブジェクトを取得 const response = await fetch('/api/create-charge', { method: 'POST', body: JSON.stringify({ amount: 5980 }) }); const charge = await response.json(); // 2. 決済モーダル起動 elepay.handleCharge(charge).then(result => { if (result.type === 'success') { // 決済成功 - サーバーWebhookで最終確認 window.location.href = '/thanks'; } else if (result.type === 'cancel') { // ユーザーがキャンセル } }).catch(err => { console.error(err); }); </script>
サーバー側(Node.js)
const express = require('express'); const axios = require('axios'); const app = express(); app.post('/api/create-charge', async (req, res) => { const { amount } = req.body; const response = await axios.post('https://api.elepay.io/charges', { amount, currency: 'JPY', paymentMethod: 'creditcard', resource: 'web', // 必須 orderNo: 'ORDER_' + Date.now(), description: '商品購入', extra: { frontUrl: 'https://shop.example.com/callback' } }, { auth: { username: process.env.ELEPAY_SECRET_KEY, password: '' } }); res.json(response.data); });
⚡ パターン2: Checkout(ホスティング型)— 最速導入
elepayがホスティングする決済ページにリダイレクト。約20分で導入完了。リンクを貼るだけ。
// サーバー側: Codes API で決済リンク作成 const response = await axios.post('https://api.elepay.io/codes', { amount: 5980, currency: 'JPY', orderNo: 'CK_' + Date.now(), // EasyCheckout では orderNo 必須 description: 'お申込み料金' // resource は EasyCheckout では指定不要(指定するとエラー) }, { auth: { username: 'sk_test_xxx', password: '' } }); // レスポンスの code.url にリダイレクト // 例: https://pay.elepay.io/c/xxxxx res.redirect(response.data.url);
💡 決済完了後のリダイレクトURLは管理画面の「簡単決済」セクションで設定(API側のextra.frontUrlではない)
📱 パターン3: Checkout(埋め込みQR型)
画面にQRコードを表示し、お客様のスマホで決済。無人端末・店頭タブレット向け。
// 1. Code 作成(QR表示用) const code = await axios.post('https://api.elepay.io/codes', { amount: 350, currency: 'JPY', orderNo: 'KIOSK_' + Date.now(), description: 'コーラ500ml' }, { auth: { username: 'sk_test_xxx', password: '' } }); // 2. code.url を QRコード化して画面に表示 const qr = new QRCode(document.getElementById("qr"), code.data.url); // 3. Webhook (charge.captured) 受信で商品搬出指示 app.post('/webhook', (req, res) => { if (req.body.type === 'charge.captured') { dispenseProduct(req.body.data.orderNo); } res.sendStatus(200); });
🔁 パターン4: Server SDK のみ(サブスク・バッチ)
バックエンド処理中心。サブスク継続課金・トークン保存課金・バッチ決済処理に最適。
// Node.js: elepay-node SDK const elepay = require('elepay-node')('sk_test_xxx'); // サブスク 初回登録: トークン保存 const firstCharge = await elepay.charges.create({ amount: 2980, currency: 'JPY', resource: 'web', paymentMethod: 'creditcard', saveCard: true, customerId: 'cust_xxx', description: 'Pro プラン 初月' }); // 毎月のバッチ: 保存トークンで自動課金 const recurring = await elepay.charges.create({ amount: 2980, currency: 'JPY', resource: 'web', paymentMethod: 'creditcard', customerId: 'cust_xxx', // トークンで自動課金 description: 'Pro プラン 2026年4月分' });
🔔 Webhook 受信実装(共通)
どの導入パターンでも、決済結果はWebhookで確実に受信して処理する。
const crypto = require('crypto'); app.post('/webhook', express.raw({type:'application/json'}), (req, res) => { // 署名検証 const signature = req.headers['x-elepay-signature']; const expected = crypto.createHmac('sha256', WEBHOOK_SECRET) .update(req.body).digest('hex'); if (signature !== expected) { return res.status(401).send('invalid signature'); } const event = JSON.parse(req.body); switch (event.type) { case 'charge.captured': // 決済確定 → 注文確定処理 fulfillOrder(event.data.orderNo); break; case 'charge.failed': // 決済失敗 → ユーザー通知 notifyFailure(event.data.orderNo); break; case 'charge.refunded': // 返金完了 → 内部処理 handleRefund(event.data); break; } res.sendStatus(200); });
↩️ 返金 API
全額・一部返金をAPI経由で実行。売上作成日より90日以内まで対応。
// 全額返金(amountは実質必須) const refund = await axios.post( `https://api.elepay.io/charges/${chargeId}/refunds`, { amount: 5980, // 元の金額を明示的に渡す reason: 'お客様都合のキャンセル' }, { auth: { username: 'sk_test_xxx', password: '' } } ); // 一部返金 const partial = await axios.post( `https://api.elepay.io/charges/${chargeId}/refunds`, { amount: 2000, reason: '一部返品' }, { auth: { username: 'sk_test_xxx', password: '' } } ); // レスポンス: { id: 're_xxx', status: 'refunded', amount: 5980, ... }
🔑 API認証 / 環境切替
| 項目 | Test環境 | Live環境 |
|---|---|---|
| 公開鍵(Client) | pk_test_xxx | pk_live_xxx |
| 秘密鍵(Server) | sk_test_xxx | sk_live_xxx |
| API Endpoint | https://api.elepay.io | |
| 管理画面 | dashboard.sterasmartone.com | |
⚠️ 秘密鍵は絶対にクライアント側コードに含めない。環境変数で管理すること。
⚠️ 開発のみのテスト用アカウントは提供されない(実際のサービス情報・特商法ページが必要)
⚠️ 実装上の注意事項
orderNoは最大20桁、一意であること(重複するとエラー40022)- Capture API(POST /charges/{id}/capture)は
amountが実質必須。空bodyで呼ぶとステータスが変わらない - Refund API も
amountが実質必須。全額返金でも元の金額を明示的に渡す - 返金処理は非同期。リクエスト後すぐに返金済みにならない場合がある
- クライアント側の結果のみを信用せず、必ずWebhookまたはServer APIで検証
- LinePay/Alipay/UnionPay/PayPay は
handleCharge成功コールバックではなくextra.frontUrlへリダイレクト - 実際のChargeステータス:
pending/waiting/uncaptured/captured/refunded/revoked/failedなど