本文へ移動
JPYC Pay

DEVELOPER DOCUMENTATION

JPYC決済をサービスに組み込む

APIで決済を作成し、購入者をJPYC Payの決済画面へ案内します。確定した支払いは署名付きWebhookで通知されます。APIの金額はJPYC単位の文字列で指定します。

最初の決済

  1. 管理画面に登録し、設定で事業者名、受取ウォレット、受付チェーンを保存します。
  2. 設定の「戻り先ドメイン」に、サービスのHTTPSドメインを登録します。戻り先を指定しない決済リンクも作れます。
  3. 「APIキー」でテスト用のキーを発行し、サーバーの環境変数に保存します。
  4. 下記のAPIで決済を作成し、レスポンスの data.checkout_url を開きます。
curl https://pay.jpyc-service.com/v1/charges   -H "Authorization: Bearer $JPYC_PAY_SECRET_KEY"   -H "Content-Type: application/json"   -H "Idempotency-Key: order_123-payment-1"   -d '{"amount_jpyc":"3000","metadata":{"order_id":"order_123"},"return_url":"https://your-store.example/payment/return","cancel_url":"https://your-store.example/payment/cancel"}'

TypeScript SDK

SDKは配布アーカイブから導入できます。npm install https://pay.jpyc-service.com/sdk/jpyc-pay-sdk-0.2.0.tgz を実行してください。配布ファイルとチェックサム も公開しています。

import { JpycPay } from "@jpyc-pay/sdk";
const pay = new JpycPay(process.env.JPYC_PAY_SECRET_KEY!);
const charge = await pay.charges.create({
  amountJpyc: "3000",
  idempotencyKey: "order_123-payment-1",
  metadata: { orderId: "order_123" },
  returnUrl: "https://your-store.example/payment/return",
});
// checkout_url へ購入者をリダイレクト
// APIキーはサーバーの環境変数で管理してください。

受付チェーンは事業者が設定

APIでチェーンを指定しない場合、加盟店の設定が適用されます。available_chain_ids で決済ごとの選択肢を絞り、chain_id で最初に表示するチェーンを指定できます。加盟店が許可していないチェーンは指定できません。

受取先と選択肢は決済作成時に保存されます。設定の変更は新しい決済から反映します。署名付きの決済試行後はチェーンを変更できません。

送金なしで動作を確認

jpyc_sk_test_ で作成した決済は livemode: false です。決済画面で成功・失敗・確認中を再現できます。本番キーとテストキーで決済・返金・Webhookを分離します。テストキーから実際の送金は実行されません。

本番キーは実際のトークンを送金します。テストネットでの実送金検証も本番キーの経路を使います。チェーンの公開範囲は環境ごとの運用設定に従います。

Webhookで注文を確定

管理画面でHTTPSの受信先を本番・テスト別に登録します。署名は X-JPYC-Signaturet=unix秒,v1=HMAC-SHA256 形式です。JSONとして読み直す前のリクエスト本文を検証してください。

import { constructEvent } from "@jpyc-pay/sdk/webhooks";

export async function POST(request: Request) {
  const rawBody = await request.text();
  let event;
  try {
    event = await constructEvent(
      rawBody,
      request.headers.get("x-jpyc-signature") ?? "",
      process.env.JPYC_PAY_WEBHOOK_SECRET!,
    );
  } catch { return new Response("Invalid signature", { status: 400 }); }

  // DBトランザクション内で event.id を一意制約付きで保存し、
  // charge.succeeded の金額・通貨・注文ID・livemodeを検証して注文を更新。
  // 保存済みのイベントには何もせず200を返します。
  // 保存に失敗したら5xxを返し、Pay側の再配信を受けます。
  return new Response("ok");
}

イベントは charge.succeededcharge.failedcharge.expired です。data.purpose で通常決済・返金送金・手数料を識別できます。返金送金の data.metadata.refund_id から返金APIを参照できます。同じイベントが複数回届くため、event.id を保存して重複処理を防ぎます。

戻り先URLへのアクセスだけでは注文を確定しないでください。Webhook、または秘密キーで取得した決済の状態・金額・注文との対応を確認します。通知に失敗すると再配信され、履歴は管理画面で確認できます。

返金と手数料

POST /v1/refundscharge_idamount_jpyc、任意の reason を渡します。Idempotency-Key は必須です。戻り値の authorization_url を元の受取ウォレットの所有者が開き、署名すると元の支払者へ送金します。処理中の返金額を含めて元の支払額を超える返金はできません。

通常決済の受取額は全額です。利用手数料は別途、月次で請求します。返金に応じて元の手数料を比例配分して調整し、未請求分や以降の請求に反映します。

エラー・期限切れ・通信断

  • 同じ注文に同じ Idempotency-Key を指定すると同じ決済が返ります。内容を変えると409になります。
  • processing / settlement_state_unknown は送金確認中です。新たな決済や署名を作らず、GET /v1/charges/:id/status を約4秒ごとに確認します。
  • 送金APIへの通信断でも資金が動いている可能性があります。SDKはこの場合 SettlementUnknownError を返します。
  • 期限切れは expired。確認中の決済は単純な期限切れ処理の対象から外し、送金記録を照合します。
  • 429はレート制限です。待ち時間を増やして同じ冪等キーで再試行してください。

API一覧

エンドポイント用途
POST /v1/charges決済作成
GET /v1/charges / :id加盟店の決済一覧・詳細
GET /v1/merchant接続先加盟店の確認
POST /v1/webhook-endpoints通知先登録
POST /v1/refunds返金の作成
GET /v1/refunds / :id返金一覧・詳細
GET /v1/charges/:id/status公開状態確認
POST /v1/charges/:id/chain受付チェーンの変更
POST /v1/charges/:id/payx402による署名付き送金
POST /v1/charges/:id/simulateテスト結果の再現
POST /v1/charges/:id/cancel未払い決済のキャンセル

厳密なリクエスト形式とエラーは OpenAPI定義 を参照してください。公開エンドポイントは決済IDがアクセス用の秘密情報として働きます。URLやIDを第三者に不用意に公開しないでください。