Menu
Sections
BitVoy EC Checkout API

Stablecoin Payment for
Your Online Store

独自ECサイトにUSDC / JPYC / USDTなどのステーブルチェックアウトをAPI連携で導入。 Intent発行 → チェックアウトページリダイレクト → Webhook通知の3ステップで、 ステーブルコインによる支払いを即日受付できます。

特長

ECサイトにステーブルチェックアウトを導入するための、すべての機能を備えています。

シンプルなAPI連携

REST APIでIntent(チェックアウト要求)を発行し、ユーザーをBitVoyチェックアウトページにリダイレクトするだけ。複雑なブロックチェーン処理はBitVoyが全て代行します。

Webhook通知

チェックアウト完了時にWebhookで即座に通知。HMAC署名付きで改ざん検知も万全です。注文ステータスの自動更新に最適です。

リアルタイム為替レート

CoinGecko APIを利用し、JPY / USD等の法定通貨価格をリアルタイムでステーブルコインに変換。サーバーサイドで正確な金額を算出できます。

複数通貨 × 複数チェーン

顧客が好みのステーブルコインとチェーンを選択可能。

USDC JPYC USDT
Polygon Kaia Avalanche Base

ガスレスチェックアウト

SMARTモードではERC-4337 Paymasterがガス代をスポンサー。FASTモードでもRelayerが代理送信し、USDC/JPYCはガス代無料です。顧客はガス代を気にせずチェックアウトできます。

直接入金

チェックアウトが完了すると、指定のウォレットアドレスに直接送金されます。中間の保管はなく、数秒で資金を受け取れます。

WalletConnect対応

MetaMaskやRainbow等のWalletConnect対応ウォレットからもチェックアウト可能。BitVoyアカウントを持たない顧客にも対応でき、決済の間口が広がります。


チェックアウトフロー

スニペットがIntent発行からチェックアウトページへのリダイレクトまでを自動で処理します。チェックアウト完了後、WebhookとリダイレクトでECサイトに結果が通知されます。

ECサイト
注文確定
チェックアウト
BitVoy
Intent自動発行
(スニペット)
BitVoy
チェックアウトページ
パスキー認証
+ 送金
Webhook
intent.succeeded
注文確定処理
完了ページ
return_url
リダイレクト

詳細シーケンス

Payment Sequence Diagram

Intent ステータス遷移

CREATED PRESENTED AUTHORIZED PROCESSING SUCCEEDED
ステータス説明
CREATEDIntent発行済み、ユーザー未操作
PRESENTEDユーザーがチェックアウト画面を表示
AUTHORIZEDパスキー認証・送金承認完了
PROCESSINGトランザクション送信済み、チェーン確認待ち
SUCCEEDEDチェックアウト完了(ブロック確認済み)
FAILED送金失敗またはトランザクション revert
EXPIRED有効期限切れ(デフォルト15分)
CANCELEDユーザーがキャンセル

チェックアウトモードと payment_url

Intent発行時のリクエストで execution_mode を指定することで、顧客の決済手段を選択できます。レスポンスには payment_url が1つ返され、その内容はモードによって異なります。

execution_mode対象ユーザー説明
FAST(デフォルト) BitVoyユーザー BitVoyウォレットでパスキー認証 → 送金。アカウント登録済みの顧客向け。
SMART BitVoyユーザー Account Abstraction(ERC-4337)によるガスレス決済。Avalanche / Base 対応。
WC 外部ウォレットユーザー MetaMask・Rainbow等のWalletConnect対応ウォレットで直接決済。BitVoyアカウント不要。
Intent発行
POST /checkout/create
execution_mode 指定
ECサイト
payment_url を取得
ユーザーをリダイレクト
BitVoy
チェックアウト
(モードに応じた画面)

スニペットで簡単導入

HTMLに数行のコードを貼るだけで、チェックアウトボタンが表示されます。Intent発行・為替変換・チェーン選択はすべてスニペットが自動で処理します。APIの直接呼び出しは不要です。

スニペットコード

<div id="bitvoy-checkout"
     data-client-id="YOUR_CLIENT_ID"
     data-amount="3000"
     data-shop-currency="JPY"
     data-currencies="USDC,JPYC"
     data-order-ref="order_12345"
     data-return-url="https://myshop.com/thanks"
     data-metadata='{"user_id":"12345"}'
     data-lang="ja">
</div>
<script src="https://bitvoy.org/checkout/button.js" async></script>

主なパラメータ

属性必須説明
data-client-id必須登録時に発行されたクライアントID
data-amount必須チェックアウト金額(法定通貨建て)
data-shop-currency任意ストアの表示通貨(デフォルト: JPY)
data-currency任意デフォルトの決済通貨(デフォルト: USDC)
data-currencies任意選択可能なステーブルコイン(カンマ区切り。例: USDC,JPYC,USDT)
data-chains-filter任意表示するチェーンを限定(カンマ区切り。例: polygon,avalanche)
data-order-ref任意注文番号(重複チェックアウト防止)
data-return-url任意チェックアウト完了後のリダイレクト先URL
data-metadata任意ECサイト固有の追加情報(JSONオブジェクト)。user_id を指定すると管理画面の決済一覧・検索・CSV出力に反映される
data-lang任意表示言語(ja / en。省略時はブラウザ言語)
data-wc任意WalletConnectボタンの表示(デフォルト: true。false で非表示)

チェーン選択はスニペットのUIで顧客が行います。通貨ごとに対応チェーンが自動表示されます。


導入手順

1

クライアント登録

登録フォームから申請してください。以下の情報をご用意いただきます:

登録完了後、以下の認証情報が発行されます:

2

スニペットを設置

チェックアウトページに上記のスニペットコードを貼り付け、data-client-id に発行されたクライアントIDを設定します。 金額・通貨・注文番号はサーバーサイドでHTMLに埋め込んでください。

3

Webhook受信エンドポイントを実装

intent.succeeded イベントを受け取り、注文ステータスを「支払い済み」に更新します。 必ず X-BitVoy-Signature を検証してください。

4

チェックアウト完了ページを実装

data-return-url に指定したURLでユーザーを受け取り、注文完了画面を表示します。 クエリパラメータに intent_idtxid が付与されます。


API リファレンス

スニペットを使用せず、独自のチェックアウトUIを実装したい場合に利用できるAPIです。Intent発行・ステータス確認・Webhook検証をサーバーサイドから直接制御できます。

サンプル実装として MerchantKit(ZIP) を提供しています。Express サーバー・Webhook 受信・PKCE フローを含む動作確認用サンプルです。

ベースURL: https://bitvoy.org

POST /checkout/create

Checkout Intent を発行します。ECサイトのサーバーサイドから呼び出してください。

認証

サーバーサイドからの呼び出しには X-Signature ヘッダー(HMAC-SHA256)が必要です。

X-Signature: HEX(HMAC-SHA256(JSON.stringify(requestBody), webhook_secret))

フロントエンド(スニペット)から呼び出す場合は Origin ヘッダーのドメイン照合で認証されるため X-Signature は不要です。

リクエストパラメータ

パラメータ必須説明
client_id必須クライアントID
amount必須shop_currency 建ての金額(例: "3000" = 3000 JPY)。APIサーバー側でステーブルコインへ変換されます。
chain必須polygon / kaia / avalanche / base
shop_currency任意ストアの表示通貨(デフォルト: サイト設定 or JPY)。amount の基準通貨として使用。
currency任意決済ステーブルコイン: USDC / JPYC / USDT(デフォルト: サイト設定の default_currency
order_ref任意ECサイト側の注文番号(Webhook / ステータス確認で使用)
execution_mode任意FAST(デフォルト)/ SMART(ガスレス)/ WC(WalletConnect)
return_url任意チェックアウト完了後のリダイレクト先URL(登録済みURLのみ有効)
lang任意決済画面の表示言語: ja / en
metadata任意ECサイト固有の追加情報(JSONオブジェクト、最大4KB)。user_id を指定すると管理画面の決済一覧・検索・CSV出力に反映される

レスポンス例

{
  "intent_id": "int_01KK8VGFWGNQ62CAB3MA1N69B7",
  "payment_url": "https://bitvoy.org/oidc/authorize?...&state=int_xxx",
  "amount": "22.5",
  "currency": "USDC",
  "chain": "avalanche",
  "expires_at": "2026-03-20T09:15:00.000Z"
}

payment_url はモードによって内容が異なります。FAST / SMART モードはBitVoyウォレット(OIDC)URL、WC モードはWalletConnect URL(https://bitvoy.org/wc/pay/...)が返されます。

amountshop_currencycurrency に変換後のステーブルコイン金額(人間が読める単位)です。

GET /checkout/status/{intent_id}

Intentのステータスとチェックアウト結果を確認します。認証不要。

レスポンス例(SUCCEEDED)

{
  "intent_id": "int_01KK8VGFWGNQ62CAB3MA1N69B7",
  "status": "SUCCEEDED",
  "amount": "22.5",
  "currency": "USDC",
  "chain": "avalanche",
  "order_ref": "ORDER-12345",
  "created_at": "2026-03-20T09:00:00.000Z",
  "expires_at": "2026-03-20T09:15:00.000Z",
  "result": {
    "tx_hash": "0xf7a41da56eb6b4b276bc3c7d84d94d6944cc8fc9...",
    "paid_at": "2026-03-20T09:01:00.000Z"
  }
}

GET /checkout/rate

法定通貨 → ステーブルコインの換算レートを取得します。

クエリパラメータ

パラメータ必須説明
client_id必須クライアントID
currency必須決済ステーブルコイン: USDC / JPYC / USDT
shop_currency任意変換元通貨(デフォルト: サイト設定 or JPY
amount任意指定すると converted_amount も返す

レスポンス例

{
  "rate": 0.0075,
  "shop_currency": "JPY",
  "pay_currency": "USDC",
  "converted_amount": 22.5
}

Webhook通知

Intentのステータスが変化するたびに、登録された webhook_url にPOSTリクエストが送信されます。

イベント一覧

イベントタイミング
intent.succeededチェックアウト完了時
intent.failedチェックアウト失敗時
intent.expired有効期限切れ時
intent.canceledユーザーがキャンセル時
intent.refunded返金完了時

Webhookペイロード例(intent.succeeded)

{
  "event": "intent.succeeded",
  "timestamp": "2026-03-20T09:01:00.000Z",
  "intent": {
    "intent_id": "int_01KK8VGFWGNQ62CAB3MA1N69B7",
    "status": "SUCCEEDED",
    "order_ref": "ORDER-12345",
    "amount": "100000000000000000000",
    "currency": "JPYC",
    "chain": "avalanche",
    "network": "mainnet",
    "payee": {
      "type": "address",
      "address": "0x1234...abcd"
    },
    "created_at": "2026-03-20T09:00:00.000Z",
    "expires_at": "2026-03-20T09:15:00.000Z",
    "result": {
      "paid_at": "2026-03-20T09:01:00.000Z",
      "tx_hash": "0xf7a41da56eb6b4b276bc3c7d84...",
      "chain": "avalanche",
      "network": "mainnet",
      "paid_amount": "100000000000000000000"
    }
  }
}

Webhookペイロード例(intent.refunded)

{
  "event": "intent.refunded",
  "timestamp": "2026-03-20T10:00:00.000Z",
  "intent": {
    "intent_id": "int_01KK8VGFWGNQ62CAB3MA1N69B7",
    "status": "SUCCEEDED",
    "order_ref": "ORDER-12345",
    "amount": "100000000000000000000",
    "currency": "JPYC",
    "chain": "avalanche",
    "network": "mainnet",
    "payee": {
      "type": "address",
      "address": "0x1234...abcd"
    },
    "created_at": "2026-03-20T09:00:00.000Z",
    "expires_at": "2026-03-20T09:15:00.000Z",
    "result": {
      "paid_at": "2026-03-20T09:01:00.000Z",
      "tx_hash": "0xf7a41da56eb6b4b276bc3c7d84...",
      "chain": "avalanche",
      "network": "mainnet",
      "paid_amount": "100000000000000000000"
    }
  },
  "refund": {
    "refund_id": "abc123def456...",
    "refund_to": "0xabcd...1234",
    "amount": "100000000000000000000",
    "currency": "JPYC",
    "chain": "avalanche",
    "tx_hash": "0xe3b2c91a47fd8b5e276dc3d94...",
    "refunded_at": "2026-03-20T10:00:00.000Z"
  }
}

注意: Webhookペイロード内の amount / paid_amount はminor unit(JPYC: 18桁、USDC: 6桁)です。

Webhookヘッダー

Webhookリクエストには以下のヘッダーが付与されます:

Header説明
X-BitVoy-Delivery配信ID(同一イベントのリトライ間で不変。受信側の重複排除キーとして使用可能)
X-BitVoy-Eventイベント名(例: intent.succeeded
X-BitVoy-Timestamp送信時刻(ISO 8601)
X-BitVoy-SignatureHMAC-SHA256署名(下記参照)

署名検証

Webhookリクエストには X-BitVoy-Signature ヘッダーが付与されます:

X-BitVoy-Signature: sha256=HEX(HMAC-SHA256(payload, webhook_secret))

実装例

Node.js (Express)

Intent発行(チェックアウト)

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

const BITVOY_API = 'https://bitvoy.org';
const CLIENT_ID = process.env.BITVOY_CLIENT_ID;
const WEBHOOK_SECRET = process.env.BITVOY_WEBHOOK_SECRET;

// チェックアウト: Intent発行 → リダイレクト
app.post('/checkout', async (req, res) => {
  const { orderId, amount, chain } = req.body;

  const body = {
    client_id: CLIENT_ID,
    order_ref: orderId,
    amount: amount,            // 例: "3000" (3000 JPY)
    shop_currency: 'JPY',       // ストアの通貨 → ステーブルコインに自動変換
    currency: 'USDC',           // 決済ステーブルコイン
    chain: chain,               // 例: "avalanche"
    execution_mode: 'FAST',     // FAST / SMART / WC
    return_url: `https://shop.example.com/orders/${orderId}/complete`,
    metadata: { user_id: String(req.session.userId) }
  };

  // X-Signature: HMAC-SHA256(JSON.stringify(body), webhook_secret)
  const signature = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(JSON.stringify(body))
    .digest('hex');

  const resp = await fetch(`${BITVOY_API}/checkout/create`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Signature': signature
    },
    body: JSON.stringify(body)
  });

  const data = await resp.json();

  // intent_id を注文に紐付けて保存
  await saveIntentToOrder(orderId, data.intent_id);

  // payment_url にユーザーをリダイレクト(モードに応じた内容が返される)
  res.json({ payment_url: data.payment_url });
});

Webhook受信

const crypto = require('crypto');

app.post('/webhook/bitvoy', express.raw({ type: 'application/json' }), async (req, res) => {
  // 1. 署名を検証
  const signature = req.headers['x-bitvoy-signature'];
  const expected = 'sha256=' + crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(req.body)
    .digest('hex');

  if (signature !== expected) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  const payload = JSON.parse(req.body);

  // 2. intent.succeeded イベントを処理
  if (payload.event === 'intent.succeeded') {
    const { intent_id, order_ref, result } = payload.intent;

    // 注文を「支払い済み」に更新
    await updateOrderStatus(order_ref, {
      status: 'paid',
      tx_hash: result.tx_hash,
      paid_at: result.paid_at,
      intent_id: intent_id
    });
  }

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

チェックアウト完了ページ(return_url)

// ユーザーがBitVoyチェックアウトページから戻ってくるURL
app.get('/orders/:orderId/complete', async (req, res) => {
  const { intent_id, txid } = req.query;
  const order = await getOrder(req.params.orderId);

  // Webhookが先に到達していれば、既に paid になっている
  // まだの場合はポーリングで確認
  if (order.status !== 'paid' && intent_id) {
    const resp = await fetch(
      `${BITVOY_API}/checkout/status/${intent_id}`
    );
    const intent = await resp.json();
    if (intent.status === 'SUCCEEDED') {
      await updateOrderStatus(order.id, { status: 'paid' });
    }
  }

  res.render('order-complete', { order, txid });
});

Python (Flask)

Intent発行

import hmac, hashlib, json, requests, os

BITVOY_API = 'https://bitvoy.org'
CLIENT_ID = os.environ['BITVOY_CLIENT_ID']
WEBHOOK_SECRET = os.environ['BITVOY_WEBHOOK_SECRET']

@app.route('/checkout', methods=['POST'])
def checkout():
    data = request.get_json()
    order_id = data['order_id']

    body = {
        'client_id': CLIENT_ID,
        'order_ref': order_id,
        'amount': data['amount'],     # 例: "3000" (3000 JPY)
        'shop_currency': 'JPY',         # ストアの通貨 → ステーブルコインに自動変換
        'currency': 'USDC',
        'chain': 'base',
        'execution_mode': 'FAST',
        'return_url': f'https://shop.example.com/orders/{order_id}/complete',
    }

    # X-Signature: HMAC-SHA256(JSON.stringify(body), webhook_secret)
    body_str = json.dumps(body, separators=(',', ':'))
    signature = hmac.new(
        WEBHOOK_SECRET.encode(), body_str.encode(), hashlib.sha256
    ).hexdigest()

    resp = requests.post(
        f'{BITVOY_API}/checkout/create',
        data=body_str,
        headers={'Content-Type': 'application/json', 'X-Signature': signature}
    )

    intent = resp.json()
    return jsonify({'payment_url': intent['payment_url']})

Webhook検証

import hmac, hashlib

@app.route('/webhook/bitvoy', methods=['POST'])
def webhook():
    payload = request.get_data()
    sig = request.headers.get('X-BitVoy-Signature', '')

    expected = 'sha256=' + hmac.new(
        WEBHOOK_SECRET.encode(), payload, hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(sig, expected):
        return jsonify({'error': 'Invalid signature'}), 401

    data = request.get_json()
    if data['event'] == 'intent.succeeded':
        intent = data['intent']
        update_order(intent['order_ref'], status='paid',
                     tx_hash=intent['result']['tx_hash'])

    return jsonify({'received': True})

フロントエンド(チェックアウトボタン)

フロントエンドからはECサイト自身のバックエンド経由でIntent発行し、受け取った payment_url にリダイレクトします。execution_mode をバックエンドに渡すことでBitVoy / WalletConnect を切り替えられます。

<button id="pay-bitvoy">BitVoyウォレットで支払う</button>
<button id="pay-wc">外部ウォレットで支払う(MetaMask等)</button>

<script>
async function createCheckout(executionMode) {
  const res = await fetch('/checkout', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      order_id: 'ORDER-12345',
      amount: '3000',    // JPY建て金額
      chain: 'avalanche',
      execution_mode: executionMode
    })
  });
  return res.json();
}

// BitVoyウォレット(FAST / SMART モード)で決済
document.getElementById('pay-bitvoy').addEventListener('click', async () => {
  const { payment_url } = await createCheckout('FAST');
  window.location.href = payment_url;
});

// 外部ウォレット(WalletConnect)で決済
document.getElementById('pay-wc').addEventListener('click', async () => {
  const { payment_url } = await createCheckout('WC');
  window.location.href = payment_url;
});
</script>

よくある質問

Shopifyじゃなくても使えますか?

はい。BitVoy EC Checkout APIはプラットフォーム非依存のREST APIです。Node.js、Python、PHP、Ruby、Go等、どのバックエンドからでもHTTPリクエストで連携できます。

既存の決済方法(クレジットカード等)に影響はありますか?

ありません。BitVoyはチェックアウト時の追加の決済手段として導入するだけで、既存のチェックアウトフローとは独立して動作します。

対応しているステーブルコインとチェーンは?

USDC、JPYC、USDTに対応しています。チェーンはPolygon、Kaia、Avalanche、Baseをサポートしています。FASTモードでは全4チェーン(USDC: Polygon/Avalanche/Base、JPYC: Kaia/Polygon/Avalanche)、SMARTモードではAvalancheとBaseに対応しています。

ガスレスチェックアウトの仕組みは?

ERC-4337 Account Abstraction を利用し、Paymasterが顧客のガス代を肩代わりします。execution_mode: "SMART" を指定するだけで有効になり、顧客はガス代を意識せずステーブルコインのみで決済できます。

為替レートはどのように計算されますか?

Intent発行時に amount(法定通貨建て)と shop_currency(例: JPY)を渡すだけで、BitVoyサーバー側がCoinGeckoベースのリアルタイムレートで自動変換します。変換後のステーブルコイン金額はレスポンスの amount フィールドで確認できます。事前にレートを確認したい場合は GET /checkout/rate エンドポイントをご利用ください。

手数料はかかりますか?

FASTモード: チェックアウト額の1.0%(USDC/JPYCはガス代無料、USDTは初回のみ承認ガス代あり)。最低取引金額: USDC/USDT $0.99、JPYC ¥99
SMARTモード: チェックアウト額の0.5% + 固定手数料/件(USDC/USDT $0.15、JPYC ¥20)。ガス代完全無料(弊社負担)。最低取引金額: USDC/USDT $0.01、JPYC ¥1

入金のタイミングは?

顧客がステーブルコインで支払うと、ブロックチェーン上のトランザクション確定後(通常数秒)に、設定した入金先ウォレットアドレスへ直接送金されます。中間の保管はありません。

Webhookが届かない場合は?

Webhookが届かない場合でも、GET /checkout/status/{intent_id} でステータスをポーリングできます。return_url へのリダイレクト時にも intent_idstatus が付与されるため、チェックアウト結果を確実に確認できます。

同じ注文で二重チェックアウトは発生しますか?

発生しません。order_ref にはクライアントごとにユニーク制約があるため、同じ注文番号で重複してIntentを発行することはできません。

返品・返金はどうなりますか?

ブロックチェーン上のトランザクションは取り消しできないため、返金はストア側からお客様のウォレットアドレスへ送金する形になります。Shop DashboardのRefundモードから返金先アドレスを確認・編集して送金を実行でき、完了時に intent.refunded Webhookで通知されます。ECサイト上での返金処理も通常通り記録可能です。

旧API(/oidc-payment/intents)のドキュメントは EC Payment API V1 を参照してください。

導入のご相談

ステーブルチェックアウトの導入に興味がありましたら、お気軽にお問い合わせください。