NOWPayments 互換 API

ChatGPT で開くClaude で開く

パス、x-api-key ヘッダー、リクエストとレスポンスのフィールド、ステータス、x-nowpayments-sig の IPN 署名は NOWPayments のドキュメントに従うため、既存のコードは通常、新しいベース URL、API key、IPN secret を用意するだけで動きます。ほかのサービスからの移行ですか?移行の概要をご覧ください。

内部では通常の blockwallets の請求です。受取アドレスはあなたのもの、決済ページは当社のホスト型決済ページで、支払いはオンチェーンで承認され、2つ目のノードでも照合されて初めて有効になります。以下では、3つのステップに続けて、各 API の対応範囲と元のサービスとの違いを説明します。実装していないパラメーターは、黙って無視されることなくエラーを返します。

3つのステップ

  1. 加盟店アカウントを取得し(トップページから申し込み)、管理画面「開発者 › 連携とキー」の「サイトのドメイン」にドメインを追加します。コールバック URL(ipn_callback_url)とリダイレクト URL(success_url / cancel_url / redirect_url)は、これらのドメイン上、またはコールバック URL のドメイン上である必要があります。キーが漏えいしても、Webhook を別の場所に向けることはできません。
  2. 加盟店管理画面の「開発者 › 連携とキー」で互換の認証情報を発行します。本番用とテスト用が1組ずつあり、NOWPayments は API key + IPN secret、Coinbase Commerce は API key + webhook shared secret です。表示は一度だけで、当社にはハッシュ / 暗号文だけを保存します。
  3. コードを下記のベース URL に向け、新しいキーを使います。まずテスト用の認証情報でテストネット上で動かし、そのあと本番に切り替えてください。
移行前移行後認証ヘッダーWebhook 署名
https://api.nowpayments.io/v1https://blockwallets.io/nowpayments/v1x-api-keyx-nowpayments-sig(HMAC-SHA512)

NOWPayments

JavaScript
- const NP = "https://api.nowpayments.io/v1";
+ const NP = "https://blockwallets.io/nowpayments/v1";

const res = await fetch(`${NP}/payment`, {
  method: "POST",
  headers: { "x-api-key": process.env.NOWPAYMENTS_API_KEY, "content-type": "application/json" },
  body: JSON.stringify({
    price_amount: 49.9, price_currency: "usd", pay_currency: "usdttrc20",
    order_id: "A-1001", order_description: "Pro plan",
    ipn_callback_url: "https://shop.example/ipn/nowpayments",
  }),
});
const { payment_id, pay_address, pay_amount } = await res.json();

対応エンドポイント

エンドポイント備考
GET /status{"message":"OK"}、キー不要
GET /currencies · /merchant/coins · /full-currencies現在受け付けられる通貨(ティッカーは下記)。fixed_rate は無視されます
GET /min-amount · GET /estimate最低額と見積もり。価格指定は USD のみ(USDT / USDC は 1:1)
POST /payment決済を作成。pay_address / pay_amount をすぐ返します(ホワイトラベル)
POST /invoiceインボイスを作成。invoice_url は当社のホスト型決済ページで、お客様が通貨とネットワークを選びます
POST /invoice-paymentインボイスの通貨を選び、決済を返します
GET /payment/:id決済の状態
GET /payment/一覧:limit(1〜500)/ page / orderBy / dateFrom / dateTo / invoiceId。sortBy は created_at のみ
POST /auth一覧に必要なのは x-api-key だけで JWT は不要です。この呼び出しは検証されないプレースホルダーのトークンを返すので、「ログインしてから一覧」というコードもそのまま動きます(メールアドレス / パスワードは検証しません)

非対応:払い出し、換算、カストディのサブパートナー、サブスクリプション、update-merchant-estimate、法定通貨での決済。これらのパスは 404 を返します。

IPN コールバック

決済が最終ステータスになると、作成時に指定された ipn_callback_url に POST します。x-nowpayments-sig = HMAC-SHA512(IPN secret, キーで再帰的に並べ替えた JSON) で、NOWPayments の検証コードとまったく同じです。送信するボディはすでに並べ替え済みのコンパクトな JSON なので、生のボディに対する HMAC でも検証できます(PHP / Python では、非常に小さい小数の再エンコードが JS と異なることがあるため、こちらが最も安全です)。失敗したコールバックは 1 分後、5 分後、30 分後、…と再試行し、合計 8 回です。

Node.js
import crypto from "node:crypto";

// Same as the NOWPayments docs (our body is already sorted, so hashing the raw body works too)
function sortObject(obj) {
  return Object.keys(obj).sort().reduce((r, k) => {
    r[k] = obj[k] && typeof obj[k] === "object" ? sortObject(obj[k]) : obj[k];
    return r;
  }, {});
}
function verifyIpn(params, sig, ipnSecret) {
  const hmac = crypto.createHmac("sha512", ipnSecret).update(JSON.stringify(sortObject(params))).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(hmac), Buffer.from(sig || ""));
}
// verifyIpn(req.body, req.headers["x-nowpayments-sig"], process.env.NOWPAYMENTS_IPN_SECRET)
PHP
$raw = file_get_contents('php://input');
$data = json_decode($raw, true);
tksort($data);  // the recursive ksort from the NOWPayments docs
$hmac = hash_hmac('sha512', json_encode($data, JSON_UNESCAPED_SLASHES), trim($ipnSecret));
$ok = hash_equals($hmac, $_SERVER['HTTP_X_NOWPAYMENTS_SIG'] ?? '');
payment_statusタイミング送信される IPN
waiting支払い待ち(通貨がまだ選ばれていないインボイスも含む)—
confirmingオンチェーンで支払いを検知、承認待ち—(照会すると確認できます)
finished支払済み(超過払いを含む。actually_paid は実際に届いた額)✓
partially_paid不足:期限前なら、お客様は同じアドレスに追加で送金できます(最初の不足時に1回送信)。期限になってもなお不足している場合は、もう一度送信します✓
expired未払いのまま期限切れ✓
refunded管理画面から決済の全額を返金し、送金済み—(照会すると確認できます)

confirmed、sending、failed は送信されません。承認されると finished になって残高に計上され、転送は行いません。

通貨ティッカー

通貨ネットワークpay_currencynetwork最低額
USDTTRONusdttrc20trx$1
USDTBNB Chainusdtbsc usdtbep20bsc$1
USDCBNB Chainusdcbsc usdcbep20bsc$1
USDTEthereumusdterc20eth$5
USDCEthereumusdc usdcerc20eth$5
USDCBaseusdcbasebase$1
USDTPolygonusdtmatic usdtpolygonmatic$1
USDCPolygonusdcmatic usdcpolygonmatic$1
USDTArbitrumusdtarbarbitrum$1
USDCArbitrumusdcarbarbitrum$1
USDTOptimismusdtopop$1
USDCOptimismusdcopop$1
USDTAvalancheusdtarc20 usdtavax / usdtavaxcavaxc$1
USDCAvalancheusdcarc20 usdcavax / usdcavaxcavaxc$1
USDTX Layerusdtxlayerxlayer$1
USDCX Layerusdcxlayerxlayer$1
USD1BNB Chainusd1bscbsc$1
FDUSDBNB Chainfdusdbscbsc$1
DAIEthereumdai daierc20eth$5
DAIArbitrumdaiarbarbitrum$1
DAIBasedaibasebase$1
BTCBitcoinbtcbtc$5
LTCLitecoinltcltc$1
DOGEDogecoindogedoge$1
BCHBitcoin Cashbchbch$1
TRXTRONtrxtrx$1
BNBBNB Chainbnbbsc bnbbsc$1
ETHEthereumetheth$5
ETHBaseethbasebase$1
ETHArbitrumetharbarbitrum$1
ETHOptimismethopop$1
POLPolygonmaticmainnet pol / polmainnet / maticmatic$1
AVAXAvalancheavaxc avaxavaxc$1
OKBX Layerokbxlayerxlayer$1
USDTSolanausdtsolsol$1
USDCSolanausdcsolsol$1
SOLSolanasolsol$1
USDTTONusdttonton$1
TONTONtonton$1

NOWPayments との相違点

テストモード

テスト用の認証情報で作成したチャージと決済は各チェーンのテストネットで動き、その Webhook はテスト用の IPN secret / shared secret で署名されます。本番とは完全に分離されており、テスト用のキーから本番の決済は見えません。

そのほか(決済ページ、承認、ネットワークと最低額、返金)はメインのドキュメントのとおりに動作します。