- ホーム
- 開発者向け
数分で暗号資産決済を導入
REST API は NOWPayments v1 と互換性があり、エンドポイント、フィールド、ステータス値、通貨コードも共通です。認証には x-api-key を使用し、ステータスの更新は署名付き IPN で受け取ります。
https://omniwallet.ewin888.com/api/v1/https://omniwallet-dev.ewin888.com/api/v1/クイックスタート
- 01
API キーを取得
アカウントを登録して管理画面にログインし、「開発者 → API キー」でキーを作成します。続いて「IPN」で IPN シークレットを設定します。まずはテスト環境で連携を完了させることをおすすめします。
- 02
決済を作成
POST /v1/paymentを呼び出し、金額、価格通貨、支払通貨を指定します。レスポンスに含まれるpay_addressがこの決済専用のアドレス、pay_amountが支払額です。POST /v1/paymentcurlcurl -X POST "https://omniwallet.ewin888.com/api/v1/payment" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: order-A-1024" \ -d '{ "price_amount": 120, "price_currency": "usd", "pay_currency": "usdttrc20", "order_id": "A-1024", "order_description": "Pro plan, 12 months", "ipn_callback_url": "https://example.com/ipn" }'レスポンスJSON{ "payment_id": 355446374401130, "payment_status": "waiting", "pay_address": "TJ8nq3M5yVfQ9C2dWkPz7aH4sLrE6uXbGt", "price_amount": 120, "price_currency": "usd", "pay_amount": 120.02, "pay_currency": "usdttrc20", "order_id": "A-1024", "network": "TRC20", "expiration_estimate_date": "2026-10-02T09:15:00.000Z", "omni_payment_url": "https://omniwallet.ewin888.com/payment/4fKq9ZtR2mXcL8vBnW1pYs" } - 03
顧客に支払いを案内
アドレスと金額(または QR コード)を顧客に表示します。代わりに
POST /v1/invoiceでホスト型請求書ページを作成し、レスポンスのinvoice_urlへ顧客をリダイレクトすることもできます。POST /v1/invoicecurlcurl -X POST "https://omniwallet.ewin888.com/api/v1/invoice" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "price_amount": 49.9, "price_currency": "usd", "order_id": "A-1025", "order_description": "Starter plan", "ipn_callback_url": "https://example.com/ipn", "success_url": "https://example.com/thanks", "cancel_url": "https://example.com/cart" }'レスポンスJSON{ "id": "355447603200201", "order_id": "A-1025", "price_amount": "49.9", "price_currency": "usd", "pay_currency": null, "invoice_url": "https://omniwallet.ewin888.com/invoice/8hTz2QpLm4XwN7cVb1RkYe", "success_url": "https://example.com/thanks", "cancel_url": "https://example.com/cart", "created_at": "2026-10-01T09:20:00.000Z" } - 04
IPN を受信
決済ステータスが変わるたびに、指定された
IPN の検証ipn_callback_urlへ POST で通知します。まず署名を検証してから、payment_statusに応じて注文を更新してください。 - 05
本番環境に切り替え
加盟店審査を通過したら、本番環境で新しい API キーと IPN シークレットを作成し、ベース URL を本番環境のものに切り替えます。
IPN 署名の検証
IPN シークレットを使って「キーをアルファベット順に並べ替えた JSON」の HMAC-SHA512 を計算し、16進数の文字列として x-omni-sig ヘッダーに設定します。送信するリクエストボディはこの並べ替え済みの JSON そのものなので、受信した生のボディに対してそのまま検証できます。
- 署名は定数時間で比較してください
- IPN は重複したり順不同で届いたりすることがあるため、
payment_idとステータスで重複を排除し、必要に応じてGET /v1/payment/{id}を呼び出して最新のステータスを取得してください - 200番台のステータスコードを返すと受信完了とみなされ、それ以外のレスポンスやタイムアウトの場合は自動で再送されます
import crypto from 'node:crypto';
import express from 'express';
const app = express();
const IPN_SECRET = process.env.OMNI_IPN_SECRET;
// Keep the raw body: the signature covers the exact bytes we send.
app.post('/ipn', express.raw({ type: 'application/json' }), (req, res) => {
const received = String(req.get('x-omni-sig') || '');
const expected = crypto
.createHmac('sha512', IPN_SECRET)
.update(req.body)
.digest('hex');
const valid = received.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected));
if (!valid) return res.status(401).send('invalid signature');
const payment = JSON.parse(req.body.toString('utf8'));
// Idempotent update: the same status can be delivered more than once.
// await orders.applyStatus(payment.order_id, payment.payment_status);
res.sendStatus(200);
});
app.listen(3000);<?php
$secret = getenv('OMNI_IPN_SECRET');
$raw = file_get_contents('php://input');
$received = $_SERVER['HTTP_X_OMNI_SIG'] ?? '';
// The signature covers the exact bytes we send.
$expected = hash_hmac('sha512', $raw, $secret);
if (!hash_equals($expected, $received)) {
http_response_code(401);
exit('invalid signature');
}
$payment = json_decode($raw, true);
// Idempotent update: the same status can be delivered more than once.
// apply_status($payment['order_id'], $payment['payment_status']);
http_response_code(200);import hashlib
import hmac
import json
import os
from flask import Flask, abort, request
app = Flask(__name__)
IPN_SECRET = os.environ["OMNI_IPN_SECRET"].encode()
@app.post("/ipn")
def ipn():
raw = request.get_data() # the exact bytes we signed
expected = hmac.new(IPN_SECRET, raw, hashlib.sha512).hexdigest()
received = request.headers.get("x-omni-sig", "")
if not hmac.compare_digest(expected, received):
abort(401)
payment = json.loads(raw)
# Idempotent update: the same status can be delivered more than once.
# apply_status(payment["order_id"], payment["payment_status"])
return "", 200{
"actually_paid": 120.02,
"actually_paid_at_fiat": 120,
"invoice_id": null,
"order_description": "Pro plan, 12 months",
"order_id": "A-1024",
"outcome_amount": 119.42,
"outcome_currency": "usdttrc20",
"parent_payment_id": null,
"pay_address": "TJ8nq3M5yVfQ9C2dWkPz7aH4sLrE6uXbGt",
"pay_amount": 120.02,
"pay_currency": "usdttrc20",
"payment_id": 355446374401130,
"payment_status": "finished",
"price_amount": 120,
"price_currency": "usd",
"purchase_id": null,
"updated_at": "2026-10-01T09:17:42.000Z"
}決済ステータス
ステータス値は NOWPayments と同じです。
| ステータス | 説明 |
|---|---|
waiting支払い待ち | 顧客の支払いを待機中 |
confirming確認中 | トランザクションを検知し、ブロックの承認を待機中 |
confirmed確認済み | 入金を確認済み |
sending精算中 | ご指定のウォレットへ精算中 |
partially_paid一部支払い | 支払額が不足しており、顧客は期限までに不足分を追加で支払い可能 |
finished完了 | 支払いが完了 |
failed失敗 | 支払いが失敗(制裁リストへの該当など) |
refunded返金済み | 支払者へ返金済み |
expired期限切れ | 期限内に支払われず失効 |
NOWPayments からの移行
API に互換性があるため、ほとんどのコードは変更する必要がありません。
- ベース URL を変更
https://api.nowpayments.io/v1/を、下記の OmniWallet の URL に置き換えます。 - OmniWallet の API キーに切り替えヘッダー名は同じく
x-api-keyです。 - IPN の検証を更新OmniWallet の IPN シークレットと
x-omni-sigヘッダーを使うように変更します。既存のコードを一切変更したくない場合は、管理画面で互換ヘッダーx-nowpayments-sigを有効にできます。 - 対応通貨を確認通貨コードは同じですが(例:
usdttrc20、usdcsol)、利用できるのは当社が対応している通貨のみです。GET /v1/merchant/coinsまたは対応通貨ページでご確認ください。 - 出金設定を確認出金時は従来どおり
POST /v1/authで有効期間5分の JWT を取得します。加えて、出金権限を持つ API キーには IP ホワイトリストの設定が必須で、送金先アドレスも事前にホワイトリストへ登録する必要があります。
- https://api.nowpayments.io/v1/
+ https://omniwallet.ewin888.com/api/v1/変わらない点
- エンドポイントのパスと HTTP メソッド
- リクエストとレスポンスのフィールド名
- 決済と出金のステータス値
- 通貨コード
- IPN の署名アルゴリズム
注意が必要な相違点
- IPN の署名ヘッダーは
x-omni-sigです(x-nowpayments-sigを同時に送信することも可能) - OmniWallet 独自の拡張フィールドは
omni_で始まります - 法定通貨での出金には対応していません(HTTP 501 を返します)
- 精算は常に管理画面で登録したウォレットへ送金されます
- テスト環境では実際のブロックチェーンのテストネットを使用します
テスト環境(サンドボックス)
テスト環境は本番とは独立したデプロイ環境で、各チェーンのテストネットに接続されています。API は本番環境とまったく同じです。
- アカウント、API キー、データは本番環境と分離されているため、別途登録が必要です(加盟店審査は自動で承認されます)
- 各テストネットのテスト用コインで支払いができ、トランザクションはテストネットのブロックエクスプローラーで確認できます
- テスト用コインに実際の価値はありません。メインネットの資産をテスト環境のアドレスに送金しないでください
| ネットワーク | テストネット | 利用可能な通貨コード |
|---|---|---|
| Ethereum | Ethereum Sepolia | eth usdc |
| BNB Smart Chain | BNB Smart Chain Testnet | bnbbsc usdtbsc |
| Polygon | Polygon Amoy | maticmainnet usdcmatic |
| Avalanche C-Chain | Avalanche Fuji | avax usdcavax |
| Arbitrum | Arbitrum Sepolia | etharb usdcarb |
| Base | Base Sepolia | ethbase usdcbase |
| Optimism | OP Sepolia | ethop usdcop |
| TRON | TRON Nile | trx usdttrc20 |
| Solana | Solana Devnet | sol usdcsol |
| Bitcoin | Bitcoin Testnet4 | btc |
冪等性とリトライ
リソースを作成するすべての POST リクエストに Idempotency-Key ヘッダーを付与できます。ネットワークのタイムアウトが発生しても、同じキーで再送すれば、決済や出金が重複して作成されることはありません。
- 同じキー・同じ内容:最初の結果を返します
- 同じキー・異なる内容:422
IDEMPOTENCY_KEY_REUSEDを返します - 最初のリクエストがまだ処理中:409
IDEMPOTENCY_IN_FLIGHTを返します(しばらくしてから再試行してください)
POST /api/v1/payout HTTP/1.1
Host: omniwallet.ewin888.com
x-api-key: YOUR_API_KEY
Authorization: Bearer YOUR_JWT
Idempotency-Key: 6c0a8e6e-3f5b-4f7a-9a52-1f0c2d9b7e41
Content-Type: application/json