paystack-transactions について
Paystack Transactions は、Paystack 決済を組み込む開発者向けのスキルです。取引の開始と検証、管理、保存済み認証による請求、レポート用エンドポイントを説明します。
主な機能
- 01取引の開始と検証
- 02取引記録の一覧表示と取得
- 03保存済み認証による請求
- 04取引履歴と集計の確認
- 05取引データの CSV エクスポート
- 06認証に対する一部金額の請求
活用シーン
- 01決済チェックアウトフローの構築
- 02注文処理前の決済検証
- 03再利用可能な顧客認証への請求
- 04取引記録の確認やエクスポート
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ rexedge/ paystack --skill paystack-transactionsインストール後、Claude Code で/paystack-transactionsを入力して読み込まれたか確認します。
詳細
Paystack Transactions
Transactions API を使用すると、インテグレーション上で決済を作成、管理できます。初期化から検証まで、トランザクションのライフサイクル全体を対象としています。
依存関係:
paystackRequestヘルパーと環境設定を利用するには、paystack-setup が必要です。
トランザクションのライフサイクル
Initialize (server) → Complete (client/redirect) → Verify (server) + Webhook
エンドポイント
| メソッド | エンドポイント | 説明 |
|---|---|---|
| POST | /transaction/initialize | トランザクションを初期化します |
| GET | /transaction/verify/:reference | トランザクションを検証します |
| GET | /transaction | トランザクションの一覧を取得します |
| GET | /transaction/:id | トランザクションを取得します |
| POST | /transaction/charge_authorization | 保存済みの認証情報を使って課金します |
| GET | /transaction/timeline/:id_or_reference | トランザクションのタイムラインを表示します |
| GET | /transaction/totals | トランザクションの合計を取得します |
| GET | /transaction/export | トランザクションを CSV 形式でエクスポートします |
| POST | /transaction/partial_debit | 認証情報に対して一部金額を引き落とします |
トランザクションの初期化
POST /transaction/initialize
決済を作成し、authorization_url(リダイレクト用)と access_code(Popup/InlineJS 用)を返します。
パラメーター(本文)
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
amount | string | はい | サブユニット(コボ)単位の金額です。"50000" = NGN 500 |
email | string | はい | 顧客のメールアドレス |
reference | string | いいえ | 一意の参照値です。使用できるのは英数字と - . = のみです |
currency | string | いいえ | NGN、USD、GHS、ZAR、KES。デフォルトはインテグレーションの通貨です |
callback_url | string | いいえ | ダッシュボードのコールバック URL を上書きします |
channels | array | いいえ | ["card","bank","ussd","qr","mobile_money","bank_transfer","eft","apple_pay"] |
plan | string | いいえ | サブスクリプション型決済のプランコード |
invoice_limit | integer | いいえ | サブスクリプションの最大課金回数 |
metadata | string | いいえ | custom_fields 配列を含む JSON 文字列 |
subaccount | string | いいえ | サブアカウントコード。例:ACCT_8f4s1eq7ml6rlzj |
split_code | string | いいえ | 分割コード。例:SPL_98WF13Eb3w |
transaction_charge | integer | いいえ | 分割時の定額手数料の上書き値(サブユニット単位) |
bearer | string | いいえ | Paystack の手数料を負担する側を指定します。"account" または "subaccount" です |
レスポンス
{
"status": true,
"message": "Authorization URL created",
"data": {
"authorization_url": "https://checkout.paystack.com/3ni8kdavz62431k",
"access_code": "3ni8kdavz62431k",
"reference": "re4lyvq3s3"
}
}
サーバーアクションの例(Next.js)
"use server";
import { paystackRequest } from "@/lib/paystack";
export async function initializePayment(email: string, amountInNaira: number) {
const result = await paystackRequest<{
authorization_url: string;
access_code: string;
reference: string;
}>("/transaction/initialize", {
method: "POST",
body: JSON.stringify({
email,
amount: Math.round(amountInNaira * 100).toString(),
callback_url: `${process.env.NEXT_PUBLIC_APP_URL}/payment/callback`,
}),
});
return result.data;
}
クライアント側の Popup(InlineJS)
"use client";
import PaystackInline from "@paystack/inline-js";
function PayButton({ email, amount }: { email: string; amount: number }) {
const handlePay = async () => {
// 1. Initialize on server
const { access_code } = await initializePayment(email, amount);
// 2. Open Popup with access_code
const popup = new PaystackInline();
popup.openIframe({
accessCode: access_code,
onSuccess: (response) => {
// 3. Verify on server — NEVER trust this alone
verifyTransaction(response.reference);
},
onClose: () => console.log("Payment window closed"),
});
};
return <button onClick={handlePay}>Pay ₦{amount}</button>;
}
リダイレクト方式
初期化後、ユーザーを authorization_url にリダイレクトします。Paystack はクエリー文字列に ?trxref=REFERENCE&reference=REFERENCE を付けて、ユーザーを callback_url にリダイレクトします。直ちにサーバー側で検証してください。
// app/payment/callback/page.tsx
import { paystackRequest } from "@/lib/paystack";
export default async function PaymentCallback({
searchParams,
}: {
searchParams: Promise<{ reference?: string }>;
}) {
const { reference } = await searchParams;
if (!reference) return <p>No reference provided</p>;
const result = await paystackRequest<{ status: string; amount: number }>(
`/transaction/verify/${encodeURIComponent(reference)}`
);
if (result.data.status === "success") {
return <p>Payment successful!</p>;
}
return <p>Payment failed: {result.data.status}</p>;
}
トランザクションの検証
GET /transaction/verify/:reference
決済後は必ずサーバー側で検証してください。reference はコールバック URL のクエリパラメーターに含まれているか、Popup の onSuccess から返されます。
const result = await paystackRequest<{
id: number;
status: "success" | "failed" | "abandoned";
reference: string;
amount: number;
currency: string;
channel: string;
paid_at: string;
authorization: {
authorization_code: string;
reusable: boolean;
card_type: string;
last4: string;
bank: string;
};
customer: { email: string; id: number };
}>(`/transaction/verify/${encodeURIComponent(reference)}`);
result.data.status === "success" を確認し、注文を履行する前に result.data.amount が想定金額と一致することを検証してください。
トランザクションの一覧表示
GET /transaction
クエリパラメーター
| パラメーター | 型 | 説明 |
|---|---|---|
perPage | integer | 1 ページあたりのレコード数(デフォルトは 50) |
page | integer | ページ番号(デフォルトは 1) |
customer | integer | 顧客 ID で絞り込みます |
terminalid | string | Terminal ID で絞り込みます |
status | string | "success"、"failed"、または "abandoned" |
from | datetime | 開始日時。例:2024-01-01T00:00:00.000Z |
to | datetime | 終了日時 |
amount | integer | 金額(サブユニット単位)で絞り込みます |
const params = new URLSearchParams({ status: "success", perPage: "20" });
const result = await paystackRequest<Transaction[]>(`/transaction?${params}`);
トランザクションの取得
GET /transaction/:id
数値 ID を指定して、単一のトランザクションを取得します。
const result = await paystackRequest<Transaction>(`/transaction/${transactionId}`);
チャージのオーソリ
POST /transaction/charge_authorization
保存済みの顧客カードに請求します(authorization.reusable === true の場合)。
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
amount | string | はい | サブユニット単位の金額 |
email | string | はい | 顧客のメールアドレス |
authorization_code | string | はい | 例:AUTH_72btv547 |
reference | string | いいえ | 一意の取引参照 |
currency | string | いいえ | 通貨コード |
queue | boolean | いいえ | スケジュール済み/一括請求の場合は true に設定します |
const result = await paystackRequest<Transaction>(
"/transaction/charge_authorization",
{
method: "POST",
body: JSON.stringify({
authorization_code: "AUTH_72btv547",
email: "[email protected]",
amount: "20000",
}),
}
);
取引のタイムライン
GET /transaction/timeline/:id_or_reference
取引の段階的な履歴(試行された決済方法、成功/失敗、所要時間)を返します。
const result = await paystackRequest<{
start_time: number;
time_spent: number;
attempts: number;
errors: number;
success: boolean;
history: Array<{ type: string; message: string; time: number }>;
}>(`/transaction/timeline/${reference}`);
取引の合計
GET /transaction/totals
合計取引量と件数を返します。from、to、perPage、page のクエリパラメーターをサポートしています。
const result = await paystackRequest<{
total_transactions: number;
total_volume: number;
total_volume_by_currency: Array<{ currency: string; amount: number }>;
pending_transfers: number;
}>("/transaction/totals");
取引のエクスポート
GET /transaction/export
CSV のダウンロードリンクを返します。すべての一覧フィルターに加えて、settled、settlement、payment_page をサポートしています。
const params = new URLSearchParams({ from: "2024-01-01", status: "success" });
const result = await paystackRequest<{ path: string }>(
`/transaction/export?${params}`
);
// result.data.path is a time-limited S3 URL to the CSV
部分デビット
POST /transaction/partial_debit
オーソリに紐づく顧客の利用可能残高から一部を引き落とします。従量課金に便利です。
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
authorization_code | string | はい | 前回の取引で取得したオーソリコード |
currency | string | はい | NGN または GHS |
amount | string | はい | サブユニット単位の金額 |
email | string | はい | オーソリコードに紐づく顧客のメールアドレス |
reference | string | いいえ | 一意の参照 |
at_least | string | いいえ | 全額の引き落としに失敗した場合に請求する最低金額 |
const result = await paystackRequest<Transaction>(
"/transaction/partial_debit",
{
method: "POST",
body: JSON.stringify({
authorization_code: "AUTH_72btv547",
currency: "NGN",
amount: "20000",
email: "[email protected]",
at_least: "10000",
}),
}
);
重要な注意事項
- 取引 ID は符号なし 64 ビット整数です。精度の損失を避けるため、TypeScript では
stringとして保存してください - 決済後は必ずサーバー側で検証してください。クライアント側のコールバックだけを信用しないでください
- 金額の検証:検証後、
result.data.amountが想定した金額と一致することを必ず確認してください - 成功した取引の
authorization_codeは、authorization.reusable === trueの場合、保存して今後の請求に再利用できます - メタデータはダッシュボード表示用の
custom_fieldsをサポートしています。送信前に JSON を文字列化してください