ペイメントリンクAPI
Omiseペイメ ントリンク APIを使用してペイメントリンク作成及び管理を自動化。多くのリンク生成、既存システムとの統合、またはダイナミック支払い体験を作成する必要があるビジネスに最適。
概要
ペイメントリンク APIでは以下が可能:
- プログラムによるペイメントリンク作成
- リンク詳細及びステータス取得
- リンク設定を更新
- すべてのペイメントリンクをリスト
- リンクパフォーマンスを追跡
- 支払いイベント向けWebhookを処理
認証
すべてのAPIリクエストはシークレットキー使用の認証が必要:
curl https://api.omise.co/links \
-u skey_test_xxx:
重要:
- テストモード用に
skey_test_xxxを使用 - ライブモード用に
skey_live_xxxを使用 - シークレットキーをクライアント側のコードで公開しない
- シークレットキーをセキュアに保つ
APIエンドポイント
ベースURL
https://api.omise.co
利用可能なエンドポイント
| メソッド | エンドポイント | 説明 |
|---|---|---|
| POST | /links | ペイメントリンク作成 |
| GET | /links/:id | ペイメントリンク取得 |
| PATCH | /links/:id | ペイメントリンク更新 |
| GET | /links | すべてのペイメントリンクをリスト |
ペイメントリンク作成
基本作成
シンプルなペイメントリンク作成:
const omise = require('omise')({
secretKey: 'skey_test_xxx'
});
omise.links.create({
amount: 100000, // 最小通貨単位での金額(1,000.00 THB)
currency: 'thb',
title: '商品購入',
description: 'プレミアムウィジェット購入',
multiple: true // マルチユースリンク
}, function(error, link) {
if (error) {
console.error('エラー:', error);
} else {
console.log('リンク作成:', link.payment_uri);
}
});
レスポンス:
{
"object": "link",
"id": "payl_test_5xyx8z94w46ixr9l",
"livemode": false,
"location": "/links/payl_test_5xyx8z94w46ixr9l",
"amount": 100000,
"currency": "thb",
"title": "商品購入",
"description": "プレミアムウィジェット購入",
"multiple": true,
"payment_uri": "https://pay.omise.co/links/payl_test_5xyx8z94w46ixr9l",
"used": false,
"charges": {
"object": "list",
"data": [],
"total": 0
},
"created_at": "2026-02-06T10:30:00Z"
}
cURL使用
curl https://api.omise.co/links \
-u skey_test_xxx: \
-d "amount=100000" \
-d "currency=thb" \
-d "title=商品購入" \
-d "description=プレミアムウィジェット購入" \
-d "multiple=true"
Python使用
import omise
omise.api_secret = 'skey_test_xxx'
link = omise.Link.create(
amount=100000,
currency='thb',
title='商品購入',
description='プレミアムウィジェット購入',
multiple=True
)
print(f"リンクURL: {link.payment_uri}")
PHP使用
<?php
require_once 'vendor/autoload.php';
define('OMISE_SECRET_KEY', 'skey_test_xxx');
$link = OmiseLink::create([
'amount' => 100000,
'currency' => 'thb',
'title' => '商品購入',
'description' => 'プレミアムウィジェット購入',
'multiple' => true
]);
echo "リンクURL: " . $link['payment_uri'];
?>
Ruby使用
require 'omise'
Omise.api_key = 'skey_test_xxx'
link = Omise::Link.create({
amount: 100000,
currency: 'thb',
title: '商品購入',
description: 'プレミアムウィジェット購入',
multiple: true
})
puts "リンクURL: #{link.payment_uri}"
リクエストパラメータ
必須パラメータ
| パラメータ | 型 | 説明 |
|---|---|---|
amount | integer | 最小通貨単位での金額(例: THB用サタン) |
currency | string | 3文字のISO通貨コード(例: thb, usd) |
title | string | 顧客に表示されるリンクタイトル(最大200文字) |
オプショナルパラメータ
| パラメータ | 型 | デフォルト | 説明 |
|---|---|---|---|
description | string | null | 詳細説明(最大1000文字) |
multiple | boolean | false | 複数使用を許可(true)またはシングルユース(false) |
metadata | object | カスタムメタデータ(キー・バリュー ペア) |
高度な作成例
シングルユースペイメントリンク
請求書に最適:
omise.links.create({
amount: 250000, // 2,500.00 THB
currency: 'thb',
title: '請求書 #INV-001',
description: 'コンサルティングサービスの支払い',
multiple: false, // シングルユースのみ
metadata: {
invoice_id: 'INV-001',
customer_id: 'CUST-123',
customer_email: 'customer@example.com'
}
}, function(error, link) {
if (!error) {
console.log('請求書リンク:', link.payment_uri);
console.log('リンク ID:', link.id);
}
});
メタデータ付きリンク
カスタム情報を保存:
omise.links.create({
amount: 150000,
currency: 'thb',
title: 'コンサルテーション予約',
description: '1時間のコンサルテーションセッション',
multiple: true,
metadata: {
service_type: 'consultation',
duration: '60_minutes',
category: 'business',
booking_date: '2026-03-15',
time_slot: '14:00',
consultant_id: 'CONS-456'
}
}, function(error, link) {
if (!error) {
console.log('予約リンク作成');
// link.idをデータベースに保存
}
});
複数通貨リンク
異なる通貨でリンク作成:
// 国際顧客向けUSDリンク
omise.links.create({
amount: 5000, // $50.00
currency: 'usd',
title: '国際商品',
description: '世界中の配送利用可能',
multiple: true
}, function(error, usdLink) {
console.log('USDリンク:', usdLink.payment_uri);
});
// 国内顧客向けTHBリンク
omise.links.create({
amount: 150000, // 1,500.00 THB
currency: 'thb',
title: 'タイ商品',
description: 'タイ国内の顧客向け',
multiple: true
}, function(error, thbLink) {
console.log('THBリンク:', thbLink.payment_uri);
});
ペイメントリンク取得
特定リンク取得
IDでリンク取得:
omise.links.retrieve('payl_test_5xyx8z94w46ixr9l', function(error, link) {
if (!error) {
console.log('リンクステータス:', link.used ? '使用済み' : 'アクティブ');
console.log('総チャージ数:', link.charges.total);
console.log('作成日:', link.created_at);
}
});
cURL使用:
curl https://api.omise.co/links/payl_test_5xyx8z94w46ixr9l \
-u skey_test_xxx:
レスポンス:
{
"object": "link",
"id": "payl_test_5xyx8z94w46ixr9l",
"livemode": false,
"amount": 100000,
"currency": "thb",
"title": "商品購入",
"description": "プレミアムウィジェット購入",
"multiple": true,
"payment_uri": "https://pay.omise.co/links/payl_test_5xyx8z94w46ixr9l",
"used": false,
"charges": {
"object": "list",
"data": [
{
"object": "charge",
"id": "chrg_test_xxx",
"amount": 100000,
"status": "successful",
"created_at": "2026-02-06T11:00:00Z"
}
],
"total": 1
},
"created_at": "2026-02-06T10:30:00Z"
}
すべてのリンクをリスト
すべてのリンクのページ分割済みリストを取得:
omise.links.list({
limit: 20,
offset: 0,
order: 'reverse_chronological'
}, function(error, list) {
if (!error) {
console.log('総リンク:', list.total);
list.data.forEach(function(link) {
console.log(`${link.title}: ${link.payment_uri}`);
});
}
});
cURL使用:
curl https://api.omise.co/links?limit=20&offset=0 \
-u skey_test_xxx:
リストパラメータ:
| パラメータ | 型 | デフォルト | 説明 |
|---|---|---|---|
limit | integer | 20 | ページあたりのリンク数(最大100) |
offset | integer | 0 | スキップするリンク数 |
order | string | chronological | ソート順: chronological または reverse_chronological |
from | string | null | フィルタ リンク作成開始日(ISO 8601) |
to | string | null | フィルタ リンク作成終了日(ISO 8601) |
ペイメントリンク更新
リンク詳細を更新(限定フィール):
omise.links.update('payl_test_5xyx8z94w46ixr9l', {
description: '詳細情報を含むアップデート商品説明',
metadata: {
updated_at: '2026-02-06',
reason: 'price_change',
updated_by: 'admin'
}
}, function(error, link) {
if (!error) {
console.log('リンク更新成功');
}
});
cURL使用:
curl https://api.omise.co/links/payl_test_5xyx8z94w46ixr9l \
-X PATCH \
-u skey_test_xxx: \
-d "description=アップデート商品説明"
更新可能なフィール:
description- リンク説明metadata- カスタムメタデータ
更新不可なフィール:
amount- 金額変更不可currency- 通貨変更不可title- タイトル変更不可multiple- 型変更不可
注: 大きな変更の場合は、新しいリンク作成して古いものを無効化。
実用的な統合例
例1: eコマース商品リンク
各商品のリンク生成:
const products = [
{ id: 'PROD-001', name: 'Tシャツ赤', price: 45000 },
{ id: 'PROD-002', name: 'Tシャツ青', price: 45000 },
{ id: 'PROD-003', name: 'Tシャツ緑', price: 45000 }
];
products.forEach(product => {
omise.links.create({
amount: product.price,
currency: 'thb',
title: product.name,
description: `${product.name}を購入`,
multiple: true,
metadata: {
product_id: product.id,
product_name: product.name,
category: 'apparel'
}
}, function(error, link) {
if (!error) {
// link.payment_uriをデータベースに保存
console.log(`${product.name}: ${link.payment_uri}`);
// データベースに保存
saveToDatabase({
product_id: product.id,
payment_link: link.payment_uri,
link_id: link.id
});
}
});
});
例2: ダイナミック請求書生成
オンデマンドで請求書リンク作成:
function createInvoiceLink(invoice) {
return new Promise((resolve, reject) => {
omise.links.create({
amount: invoice.total,
currency: invoice.currency,
title: `請求書 ${invoice.number}`,
description: `${invoice.description}の支払い`,
multiple: false, // シングルユース
metadata: {
invoice_number: invoice.number,
customer_id: invoice.customer_id,
customer_email: invoice.customer_email,
due_date: invoice.due_date,
items: JSON.stringify(invoice.items)
}
}, function(error, link) {
if (error) {
reject(error);
} else {
resolve(link);
}
});
});
}
// 使用方法
const invoice = {
number: 'INV-2026-001',
total: 350000, // 3,500.00 THB
currency: 'thb',
description: 'ウェブ開発サービス',
customer_id: 'CUST-123',
customer_email: 'customer@example.com',
due_date: '2026-03-06',
items: [
{ description: 'ホームページデザイン', amount: 150000 },
{ description: 'お問い合わせページ', amount: 100000 },
{ description: 'モバイルレスポンシブ', amount: 100000 }
]
};
createInvoiceLink(invoice)
.then(link => {
console.log('請求書リンク:', link.payment_uri);
// 顧客にメール送信
sendInvoiceEmail(invoice.customer_email, {
invoice_number: invoice.number,
payment_link: link.payment_uri,
amount: invoice.total,
due_date: invoice.due_date
});
})
.catch(error => {
console.error('請求書リンク作成エラー:', error);
});
例3: イベント登録システム
チケット付きリンク生成:
const events = {
'workshop-2026': {
name: 'ウェブ開発ワークショップ 2026',
tickets: [
{ type: 'early_bird', price: 150000, available: 50 },
{ type: 'regular', price: 200000, available: 100 },
{ type: 'vip', price: 350000, available: 20 }
]
}
};
async function generateEventLinks(eventId, event) {
const links = [];
for (const ticket of event.tickets) {
const link = await new Promise((resolve, reject) => {
omise.links.create({
amount: ticket.price,
currency: 'thb',
title: `${event.name} - ${ticket.type.replace('_', ' ').toUpperCase()} チケット`,
description: `${event.name}に登録`,
multiple: true,
metadata: {
event_id: eventId,
ticket_type: ticket.type,
tickets_available: ticket.available
}
}, (error, link) => {
if (error) reject(error);
else resolve(link);
});
});
links.push({
ticket_type: ticket.type,
link: link.payment_uri,
link_id: link.id
});
}
return links;
}
// イベント向けリンク生成
generateEventLinks('workshop-2026', events['workshop-2026'])
.then(links => {
console.log('イベントリンク生成:');
links.forEach(l => {
console.log(`${l.ticket_type}: ${l.link}`);
});
});
例4: 定期購読支払いリンク
月間支払いリンク作成:
function generateMonthlyLink(subscription) {
const currentDate = new Date();
const month = currentDate.toLocaleString('ja-JP', { month: 'long' });
const year = currentDate.getFullYear();
return omise.links.create({
amount: subscription.monthly_amount,
currency: 'thb',
title: `${subscription.plan_name} - ${month} ${year}`,
description: `${subscription.plan_name}サブスクリプションの月間支払い`,
multiple: false, // 毎月ユニークなリンク
metadata: {
subscription_id: subscription.id,
customer_id: subscription.customer_id,
plan: subscription.plan_name,
billing_month: `${year}-${currentDate.getMonth() + 1}`,
auto_generated: 'true'
}
});
}
// 例: すべてのアクティブ定期購読向けに生成
const activeSubscriptions = [
{
id: 'SUB-001',
customer_id: 'CUST-123',
plan_name: 'プレミアム',
monthly_amount: 99000
},
{
id: 'SUB-002',
customer_id: 'CUST-456',
plan_name: 'ビジネス',
monthly_amount: 299000
}
];
activeSubscriptions.forEach(subscription => {
generateMonthlyLink(subscription)
.then(link => {
console.log(`${subscription.customer_id}向けリンク:`, link.payment_uri);
// 顧客にメール送信
emailCustomer(subscription.customer_id, {
subject: '月間定期購読支払い',
payment_link: link.payment_uri
});
})
.catch(error => {
console.error(`${subscription.id}エラー:`, error);
});
});
例5: 一括リンク生成
多くのリンクを効率的に生成:
async function bulkCreateLinks(items) {
const results = {
successful: [],
failed: []
};
// レート制限を避けるため、バッチ処理
const batchSize = 10;
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
const promises = batch.map(item =>
new Promise((resolve) => {
omise.links.create({
amount: item.amount,
currency: 'thb',
title: item.title,
description: item.description,
multiple: true,
metadata: item.metadata || {}
}, (error, link) => {
if (error) {
resolve({ success: false, item, error });
} else {
resolve({ success: true, item, link });
}
});
})
);
const batchResults = await Promise.all(promises);
batchResults.forEach(result => {
if (result.success) {
results.successful.push(result);
} else {
results.failed.push(result);
}
});
// レート制限遅延
if (i + batchSize < items.length) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
return results;
}
// 使用方法
const products = [
{ title: '商品 A', amount: 50000, description: '説明 A' },
{ title: '商品 B', amount: 75000, description: '説明 B' },
{ title: '商品 C', amount: 100000, description: '説明 C' },
// ... 他の商品
];
bulkCreateLinks(products)
.then(results => {
console.log(`作成成功: ${results.successful.length}`);
console.log(`失敗: ${results.failed.length}`);
// 成功したリンクをエクスポート
const csv = results.successful.map(r =>
`${r.item.title},${r.link.payment_uri}`
).join('\n');
console.log('\nCSVエクスポート:\n', csv);
});
Webhooks統合
支払いリンクイベントについてリアルタイム通知を受け取り:
Webhooks設定
- ダッシュボードでWebhookエンドポイント設定
- 支払いリンクイベントをリッスン
- Webhook署名を確認
- イベント処理
Webhookイベント
const express = require('express');
const app = express();
app.post('/webhooks/omise', express.json(), (req, res) => {
const event = req.body;
switch(event.key) {
case 'charge.create':
handleChargeCreated(event.data);
break;
case 'charge.complete':
handleChargeCompleted(event.data);
break;
case 'charge.failed':
handleChargeFailed(event.data);
break;
}
res.sendStatus(200);
});
function handleChargeCompleted(charge) {
// チャージがペイメントリンク由来か確認
if (charge.source && charge.source.type === 'link') {
const linkId = charge.source.id;
console.log('リンク向け支払い受信:', linkId);
// リンク詳細を取得
omise.links.retrieve(linkId, (error, link) => {
if (!error) {
const metadata = link.metadata;
// メタデータに基づいて処理
if (metadata.invoice_id) {
markInvoicePaid(metadata.invoice_id);
} else if (metadata.product_id) {
fulfillOrder(metadata.product_id, charge);
}
// 確認メール送信
sendConfirmationEmail(charge.customer_email, {
amount: charge.amount,
description: link.title
});
}
});
}
}
app.listen(3000);
Webhook署名検証
Webhook真正性を確認:
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const computed = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return computed === signature;
}
app.post('/webhooks/omise', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['omise-signature'];
const secret = process.env.WEBHOOK_SECRET;
if (!verifyWebhook(req.body, signature, secret)) {
return res.status(401).send('無効な署名');
}
const event = JSON.parse(req.body);
// イベント処理...
res.sendStatus(200);
});
エラーハンドリング
一般的なエラー
omise.links.create({
amount: 100000,
currency: 'thb',
title: '商品'
}, function(error, link) {
if (error) {
switch(error.code) {
case 'invalid_amount':
console.error('無効な金額:', error.message);
break;
case 'invalid_currency':
console.error('通貨非サポート:', error.message);
break;
case 'authentication_failure':
console.error('無効なAPIキー:', error.message);
break;
default:
console.error('エラー:', error.message);
}
}
});