DEVELOPER DOCUMENTATION
JPYC決済をサービスに組み込む
APIで決済を作成し、購入者をJPYC Payの決済画面へ案内します。確定した支払いは署名付きWebhookで通知されます。APIの金額はJPYC単位の文字列で指定します。
最初の決済
- 管理画面に登録し、設定で事業者名、受取ウォレット、受付チェーンを保存します。
- 設定の「戻り先ドメイン」に、サービスのHTTPSドメインを登録します。戻り先を指定しない決済リンクも作れます。
- 「APIキー」でテスト用のキーを発行し、サーバーの環境変数に保存します。
- 下記の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-Signature の t=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.succeeded、charge.failed、charge.expired です。data.purpose で通常決済・返金送金・手数料を識別できます。返金送金の data.metadata.refund_id から返金APIを参照できます。同じイベントが複数回届くため、event.id を保存して重複処理を防ぎます。
戻り先URLへのアクセスだけでは注文を確定しないでください。Webhook、または秘密キーで取得した決済の状態・金額・注文との対応を確認します。通知に失敗すると再配信され、履歴は管理画面で確認できます。
返金と手数料
POST /v1/refunds に charge_id、amount_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/pay | x402による署名付き送金 |
| POST /v1/charges/:id/simulate | テスト結果の再現 |
| POST /v1/charges/:id/cancel | 未払い決済のキャンセル |
厳密なリクエスト形式とエラーは OpenAPI定義 を参照してください。公開エンドポイントは決済IDがアクセス用の秘密情報として働きます。URLやIDを第三者に不用意に公開しないでください。