メインコンテンツへスキップ

Node.js ライブラリ (omise-node)

omise-node ライブラリは、TypeScript 定義、Promise/async-await サポート、および優れた Express と NestJS 統合を備えた、Omise API への最新の Node.js インターフェースを提供します。

インストール

npm の使用

npm install omise

Yarn の使用

yarn add omise

pnpm の使用

pnpm add omise

要件

  • Node.js 12 以上 (Node.js 12 は 2022 年 4 月に EOL に達したため Node.js 16+ を推奨)
  • パッケージ管理用の npm、yarn、または pnpm
  • TypeScript 4.0+ (オプション、TypeScript プロジェクト用)

クイックスタート

基本的な構成

const omise = require('omise')({
secretKey: 'skey_test_123456789',
publicKey: 'pkey_test_123456789',
omiseVersion: '2019-05-29'
});

TypeScript の構成

omise-node ライブラリには 組み込み TypeScript 定義 が含まれており、別の @types/omise パッケージは必要ありません。

import Omise from 'omise';

const omise = Omise({
secretKey: process.env.OMISE_SECRET_KEY!,
publicKey: process.env.OMISE_PUBLIC_KEY!,
omiseVersion: '2019-05-29'
});

// 型安全なAPIコール
import type { Charges, Tokens } from 'omise';

// チャージは完全な型推論を持つ
const charge: Charges.ICharge = await omise.charges.create({
amount: 100000,
currency: 'thb',
card: 'tokn_test_123'
});

// トークンレスポンスは完全に型付けされる
const token: Tokens.IToken = await omise.tokens.create({
card: {
number: '4242424242424242',
expiration_month: 12,
expiration_year: 2027,
security_code: '123',
name: 'JOHN DOE'
}
});

TypeScript の機能:

  • ✅ 組み込み型定義 (@types パッケージ不要)
  • ✅ VS Code での完全な IntelliSense サポート
  • ✅ 型安全なリクエスト/レスポンスオブジェクト
  • ✅ 支払い方法、通貨、ステータス向けの列挙型
  • ✅ 厳密な null チェックのサポート
  • ✅ 高度な使用向けのジェネリック型パラメータ

型定義の場所: 公式の TypeScript 定義は omise-node リポジトリ で保持されています。

Express 構成

// config/omise.js
require('dotenv').config();

module.exports = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY,
publicKey: process.env.OMISE_PUBLIC_KEY,
omiseVersion: '2019-05-29'
});

環境変数

.env ファイルを作成:

# 開発/テスト
OMISE_SECRET_KEY=skey_test_123456789
OMISE_PUBLIC_KEY=pkey_test_123456789

# 本番環境
# OMISE_SECRET_KEY=skey_live_123456789
# OMISE_PUBLIC_KEY=pkey_live_123456789

一般的な操作

チャージの作成

Promise で

const omise = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY
});

omise.charges.create({
amount: 100000, // 1,000.00 THB
currency: 'THB',
card: 'tokn_test_123',
description: 'Order #1234',
metadata: {
order_id: '1234',
customer_name: 'John Doe'
}
})
.then(charge => {
if (charge.paid) {
console.log(`チャージ成功: ${charge.id}`);
} else {
console.log(`チャージ失敗: ${charge.failure_message}`);
}
})
.catch(err => {
console.error('エラー:', err.message);
});

Async/Await で

async function createCharge(token, amount) {
try {
const charge = await omise.charges.create({
amount,
currency: 'THB',
card: token,
description: 'Order #1234',
metadata: {
order_id: '1234',
customer_name: 'John Doe'
}
});

if (charge.paid) {
console.log(`チャージ成功: ${charge.id}`);
return charge;
} else {
throw new Error(charge.failure_message);
}
} catch (error) {
console.error('チャージ失敗:', error);
throw error;
}
}

TypeScript で

interface ChargeMetadata {
order_id: string;
customer_name: string;
}

interface CreateChargeParams {
amount: number;
currency: string;
card: string;
metadata: ChargeMetadata;
}

async function createCharge(params: CreateChargeParams): Promise<Omise.Charges.ICharge> {
const charge = await omise.charges.create({
amount: params.amount,
currency: params.currency,
card: params.card,
metadata: params.metadata
});

return charge;
}

3D セキュアで

async function createSecureCharge(token, amount, returnUri) {
const charge = await omise.charges.create({
amount,
currency: 'THB',
card: token,
return_uri: returnUri
});

if (charge.authorized) {
if (charge.authorize_uri) {
// 3D セキュアのために顧客を authorize_uri にリダイレクト
return { redirect: charge.authorize_uri };
} else {
// 3D セキュアなしでチャージ完了
return { success: true, charge };
}
}

throw new Error(charge.failure_message);
}

チャージの取得

// Promise ベース
omise.charges.retrieve('chrg_test_123')
.then(charge => {
console.log(`金額: ${charge.amount}`);
console.log(`通貨: ${charge.currency}`);
console.log(`ステータス: ${charge.status}`);
});

// Async/await
async function getCharge(chargeId) {
const charge = await omise.charges.retrieve(chargeId);
return charge;
}

チャージのリスト表示

async function listCharges(options = {}) {
const charges = await omise.charges.list({
limit: 20,
offset: 0,
order: 'reverse_chronological',
...options
});

charges.data.forEach(charge => {
console.log(`${charge.id}: ${charge.amount} ${charge.currency}`);
});

return charges;
}

// 日付フィルタでチャージをリスト表示
const weekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
const charges = await omise.charges.list({
from: weekAgo.toISOString().split('T')[0],
to: new Date().toISOString().split('T')[0]
});

顧客の作成

async function createCustomer(email, description, metadata = {}) {
const customer = await omise.customers.create({
email,
description,
metadata
});

console.log(`顧客作成: ${customer.id}`);
return customer;
}

// 使用方法
const customer = await createCustomer(
'customer@example.com',
'John Doe',
{ user_id: '12345', account_type: 'premium' }
);

顧客へのカード保存

// カードトークンで顧客を更新
async function addCardToCustomer(customerId, token) {
const customer = await omise.customers.update(customerId, {
card: token
});

console.log(`カード保存: ${customer.default_card}`);
return customer;
}

// カード付きで顧客を作成
async function createCustomerWithCard(email, token) {
const customer = await omise.customers.create({
email,
card: token
});

return customer;
}

顧客カードのリスト表示

async function listCustomerCards(customerId) {
const customer = await omise.customers.retrieve(customerId);

customer.cards.data.forEach(card => {
console.log(`${card.brand} ending in ${card.last_digits}`);
console.log(`有効期限: ${card.expiration_month}/${card.expiration_year}`);
});

return customer.cards.data;
}

払い戻しの作成

// 全額返金
async function refundCharge(chargeId) {
const refund = await omise.charges.refund(chargeId);
return refund;
}

// 部分払い戻し
async function partialRefund(chargeId, amount, metadata = {}) {
const refund = await omise.charges.refund(chargeId, {
amount,
metadata
});

console.log(`返金 ${refund.id}: ${refund.amount} ${refund.currency}`);
return refund;
}

// 使用方法
await partialRefund('chrg_test_123', 25000, {
reason: 'customer_request',
ticket_id: 'TICKET-123'
});

転送の作成

async function createTransfer(amount, recipientId, metadata = {}) {
const transfer = await omise.transfers.create({
amount,
recipient: recipientId,
metadata
});

console.log(`転送 ${transfer.id}: ${transfer.amount}`);
return transfer;
}

代替決済方法

ソースの作成

// PromptPay QR
async function createPromptPaySource(amount) {
const source = await omise.sources.create({
type: 'promptpay',
amount,
currency: 'THB'
});

console.log(`QR コード URL: ${source.scannable_code.image.download_uri}`);

// ソースでチャージを作成
const charge = await omise.charges.create({
amount,
currency: 'THB',
source: source.id,
return_uri: 'https://example.com/payment/callback'
});

return { source, charge };
}

インターネットバンキング

async function createInternetBankingCharge(amount, bankCode = 'scb') {
const source = await omise.sources.create({
type: `internet_banking_${bankCode}`,
amount,
currency: 'THB'
});

const charge = await omise.charges.create({
amount,
currency: 'THB',
source: source.id,
return_uri: 'https://example.com/payment/callback'
});

// リダイレクト用の authorize_uri を返す
return charge.authorize_uri;
}

分割払い

async function createInstallmentCharge(amount, bank, term) {
const source = await omise.sources.create({
type: `installment_${bank}`,
amount,
currency: 'THB',
installment_term: term
});

const charge = await omise.charges.create({
amount,
currency: 'THB',
source: source.id,
return_uri: 'https://example.com/payment/callback'
});

return charge;
}

// 使用方法
const charge = await createInstallmentCharge(100000, 'kbank', 6);

エラーハンドリング

const { OmiseError } = require('omise');

async function createChargeWithErrorHandling(params) {
try {
const charge = await omise.charges.create(params);
return charge;
} catch (error) {
if (error instanceof OmiseError) {
console.error('Omise エラー:', error.message);
console.error('ステータスコード:', error.statusCode);
console.error('エラーコード:', error.code);

// 特定のエラーを処理
switch (error.code) {
case 'authentication_failure':
throw new Error('無効な API キー');
case 'invalid_card':
throw new Error('カードが拒否されました');
case 'insufficient_fund':
throw new Error('残高不足');
default:
throw error;
}
}

// ネットワークまたはその他のエラー
throw error;
}
}

TypeScript エラーハンドリング

import Omise, { OmiseError } from 'omise';

async function handleChargeError(error: unknown): Promise<never> {
if (error instanceof OmiseError) {
const errorMessages: Record<string, string> = {
insufficient_fund: 'カードの残高不足',
stolen_or_lost_card: 'カードは盗難または紛失として報告されています',
invalid_security_code: '無効な CVV コード',
payment_cancelled: '支払いがキャンセルされました'
};

const message = errorMessages[error.code] || error.message;
throw new Error(message);
}

throw error;
}

Express 統合

コントローラーの例

// controllers/paymentController.js
const omise = require('../config/omise');
const Order = require('../models/Order');
const Payment = require('../models/Payment');

exports.createPayment = async (req, res) => {
try {
const { orderId } = req.params;
const { omiseToken } = req.body;

const order = await Order.findById(orderId);
if (!order) {
return res.status(404).json({ error: '注文が見つかりません' });
}

const charge = await omise.charges.create({
amount: Math.round(order.total * 100),
currency: 'THB',
card: omiseToken,
description: `Order #${order.id}`,
metadata: {
order_id: order.id,
customer_email: order.email
},
return_uri: `${req.protocol}://${req.get('host')}/payment/callback`
});

// 支払いレコードを保存
const payment = await Payment.create({
orderId: order.id,
chargeId: charge.id,
amount: order.total,
status: charge.status,
paid: charge.paid
});

if (charge.paid) {
order.paymentStatus = 'paid';
await order.save();
return res.json({ success: true, charge });
} else if (charge.authorize_uri) {
return res.json({ redirect: charge.authorize_uri });
} else {
return res.status(400).json({ error: charge.failure_message });
}

} catch (error) {
console.error('支払いエラー:', error);
res.status(500).json({ error: '支払いが失敗しました' });
}
};

exports.paymentCallback = async (req, res) => {
try {
const { id: chargeId } = req.query;

const charge = await omise.charges.retrieve(chargeId);
const payment = await Payment.findOne({ chargeId: charge.id });

if (!payment) {
return res.status(404).send('支払いが見つかりません');
}

payment.status = charge.status;
payment.paid = charge.paid;
await payment.save();

if (charge.paid) {
const order = await Order.findById(payment.orderId);
order.paymentStatus = 'paid';
await order.save();
res.redirect(`/orders/${order.id}?success=true`);
} else {
res.redirect(`/payment/${payment.orderId}?error=${charge.failure_message}`);
}

} catch (error) {
console.error('コールバックエラー:', error);
res.status(500).send('支払い検証が失敗しました');
}
};

ルート

// routes/payment.js
const express = require('express');
const router = express.Router();
const paymentController = require('../controllers/paymentController');

router.post('/payment/:orderId', paymentController.createPayment);
router.get('/payment/callback', paymentController.paymentCallback);

module.exports = router;

エラーハンドリング用ミドルウェア

// middleware/errorHandler.js
const { OmiseError } = require('omise');

function errorHandler(err, req, res, next) {
if (err instanceof OmiseError) {
console.error('Omise エラー:', {
message: err.message,
code: err.code,
statusCode: err.statusCode
});

return res.status(err.statusCode || 500).json({
error: err.message,
code: err.code
});
}

console.error('予期しないエラー:', err);
res.status(500).json({ error: '内部サーバーエラー' });
}

module.exports = errorHandler;

NestJS 統合

モジュール設定

// omise/omise.module.ts
import { Module, Global } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { OmiseService } from './omise.service';

@Global()
@Module({
imports: [ConfigModule],
providers: [OmiseService],
exports: [OmiseService],
})
export class OmiseModule {}

サービス

// omise/omise.service.ts
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import Omise from 'omise';

@Injectable()
export class OmiseService {
private omise: ReturnType<typeof Omise>;

constructor(private configService: ConfigService) {
this.omise = Omise({
secretKey: this.configService.get<string>('OMISE_SECRET_KEY')!,
publicKey: this.configService.get<string>('OMISE_PUBLIC_KEY')!,
omiseVersion: '2019-05-29'
});
}

async createCharge(params: Omise.Charges.CreatePayload): Promise<Omise.Charges.ICharge> {
return this.omise.charges.create(params);
}

async retrieveCharge(chargeId: string): Promise<Omise.Charges.ICharge> {
return this.omise.charges.retrieve(chargeId);
}

async createCustomer(params: Omise.Customers.CreatePayload): Promise<Omise.Customers.ICustomer> {
return this.omise.customers.create(params);
}

async refundCharge(chargeId: string, amount?: number): Promise<Omise.Refunds.IRefund> {
return this.omise.charges.refund(chargeId, amount ? { amount } : undefined);
}
}

コントローラー

// payment/payment.controller.ts
import { Controller, Post, Get, Body, Param, Query, HttpException, HttpStatus } from '@nestjs/common';
import { OmiseService } from '../omise/omise.service';
import { PaymentService } from './payment.service';

@Controller('payment')
export class PaymentController {
constructor(
private omiseService: OmiseService,
private paymentService: PaymentService
) {}

@Post(':orderId')
async createPayment(
@Param('orderId') orderId: string,
@Body('omiseToken') omiseToken: string
) {
try {
const order = await this.paymentService.findOrder(orderId);

const charge = await this.omiseService.createCharge({
amount: Math.round(order.total * 100),
currency: 'THB',
card: omiseToken,
description: `Order #${order.id}`,
metadata: {
order_id: order.id,
customer_email: order.email
},
return_uri: `${process.env.APP_URL}/payment/callback`
});

await this.paymentService.savePayment({
orderId: order.id,
chargeId: charge.id,
amount: order.total,
status: charge.status,
paid: charge.paid
});

if (charge.paid) {
await this.paymentService.markOrderPaid(order.id);
return { success: true, charge };
} else if (charge.authorize_uri) {
return { redirect: charge.authorize_uri };
} else {
throw new HttpException(charge.failure_message, HttpStatus.BAD_REQUEST);
}

} catch (error) {
throw new HttpException('支払いが失敗しました', HttpStatus.INTERNAL_SERVER_ERROR);
}
}

@Get('callback')
async paymentCallback(@Query('id') chargeId: string) {
const charge = await this.omiseService.retrieveCharge(chargeId);
await this.paymentService.updatePaymentStatus(charge.id, charge.status, charge.paid);

if (charge.paid) {
return { success: true, message: '支払いが成功しました' };
} else {
throw new HttpException(charge.failure_message, HttpStatus.BAD_REQUEST);
}
}
}

ベストプラクティス

1. 環境変数を使用

require('dotenv').config();

const omise = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY,
publicKey: process.env.OMISE_PUBLIC_KEY
});

if (!process.env.OMISE_SECRET_KEY) {
throw new Error('OMISE_SECRET_KEY が設定されていません');
}

2. べき等性を実装

async function createIdempotentCharge(params, orderId) {
// 注文IDに基づく決定論的なべき等キーを使用
// これにより、同じ注文は常に同じキーを取得します
const idempotencyKey = `order-${orderId}`;

return omise.charges.create(params, {
headers: {
'Idempotency-Key': idempotencyKey
}
});
}

3. 再試行ロジックを使用

async function createChargeWithRetry(params, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await omise.charges.create(params);
} catch (error) {
if (attempt === maxRetries - 1) throw error;

const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}

4. 最小限のデータを保存

class Payment {
constructor(chargeId) {
this.chargeId = chargeId;
this._charge = null;
}

async getCharge() {
if (!this._charge) {
this._charge = await omise.charges.retrieve(this.chargeId);
}
return this._charge;
}

async refreshCharge() {
this._charge = null;
return this.getCharge();
}
}

5. ロギングを実装

const winston = require('winston');

const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
]
});

async function createChargeWithLogging(params) {
logger.info('チャージを作成中', { amount: params.amount, currency: params.currency });

try {
const charge = await omise.charges.create(params);
logger.info('チャージ作成', { chargeId: charge.id, paid: charge.paid });
return charge;
} catch (error) {
logger.error('チャージ失敗', { error: error.message, code: error.code });
throw error;
}
}

6. 入力を検証

const Joi = require('joi');

const chargeSchema = Joi.object({
amount: Joi.number().min(2000).required(),
currency: Joi.string().valid('THB', 'USD', 'SGD', 'JPY').required(),
token: Joi.string().required()
});

async function createValidatedCharge(params) {
const { error, value } = chargeSchema.validate(params);

if (error) {
throw new Error(`検証エラー: ${error.message}`);
}

return omise.charges.create({
amount: value.amount,
currency: value.currency,
card: value.token
});
}

テスト

Jest の例

// __tests__/payment.test.js
const omise = require('../config/omise');

jest.mock('../config/omise');

describe('支払いサービス', () => {
beforeEach(() => {
jest.clearAllMocks();
});

test('チャージを正常に作成する', async () => {
const mockCharge = {
id: 'chrg_test_123',
amount: 100000,
currency: 'THB',
paid: true,
status: 'successful'
};

omise.charges.create.mockResolvedValue(mockCharge);

const result = await omise.charges.create({
amount: 100000,
currency: 'THB',
card: 'tokn_test_123'
});

expect(result.id).toBe('chrg_test_123');
expect(result.paid).toBe(true);
});

test('チャージエラーを処理する', async () => {
const mockError = new Error('insufficient_fund');
mockError.code = 'insufficient_fund';

omise.charges.create.mockRejectedValue(mockError);

await expect(
omise.charges.create({ amount: 100000, currency: 'THB', card: 'tokn_test_123' })
).rejects.toThrow('insufficient_fund');
});
});

Supertest での統合テスト

// __tests__/payment.integration.test.js
const request = require('supertest');
const app = require('../app');
const omise = require('../config/omise');

jest.mock('../config/omise');

describe('支払い API', () => {
test('POST /payment/:orderId は支払いを作成する', async () => {
const mockCharge = {
id: 'chrg_test_123',
paid: true,
status: 'successful'
};

omise.charges.create.mockResolvedValue(mockCharge);

const response = await request(app)
.post('/payment/order_123')
.send({ omiseToken: 'tokn_test_123' });

expect(response.status).toBe(200);
expect(response.body.success).toBe(true);
expect(response.body.charge.id).toBe('chrg_test_123');
});
});

トラブルシューティング

SSL 証明書エラー

const https = require('https');

const omise = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY,
agent: new https.Agent({
rejectUnauthorized: false // 開発環境のみ!
})
});

接続タイムアウト

const omise = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY,
timeout: 60000 // 60 秒
});

デバッグモード

const omise = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY,
debug: true // リクエスト/レスポンスの詳細をログに記録
});

ウェブフック署名検証

const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');

return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}

// Express ミドルウェア
function webhookVerification(req, res, next) {
const payload = JSON.stringify(req.body);
const signature = req.headers['omise-signature'];

if (!verifyWebhookSignature(payload, signature, process.env.OMISE_WEBHOOK_SECRET)) {
return res.status(401).json({ error: '無効な署名' });
}

next();
}

よくある質問

Express でウェブフックを処理する方法は?

const express = require('express');
const router = express.Router();

router.post('/webhooks/omise', express.json(), (req, res) => {
const event = req.body;

switch (event.key) {
case 'charge.complete':
handleChargeComplete(event.data);
break;
case 'refund.create':
handleRefundCreate(event.data);
break;
}

res.json({ status: 'ok' });
});

async function handleChargeComplete(chargeData) {
const charge = await omise.charges.retrieve(chargeData.id);
// 支払いステータスを更新
}

実際のチャージなしで支払いをテストする方法は?

// テスト API キーを使用
const omise = require('omise')({
secretKey: 'skey_test_123456789'
});

// テストトークンを使用
const charge = await omise.charges.create({
amount: 100000,
currency: 'THB',
card: 'tokn_test_5086xl7ddjbases4sq3i' // テストトークン
});

console.log('テストモード:', !charge.livemode);

通貨変換を処理する方法は?

class Money {
constructor(amountBaht) {
this.amountSatang = Math.round(amountBaht * 100);
}

getSatang() {
return this.amountSatang;
}

getBaht() {
return this.amountSatang / 100;
}

static fromSatang(amountSatang) {
const instance = new Money(0);
instance.amountSatang = amountSatang;
return instance;
}
}

// 使用方法
const money = new Money(1000.00);
const charge = await omise.charges.create({
amount: money.getSatang(),
currency: 'THB',
card: 'tokn_test_123'
});

指数バックオフで再試行ロジックを実装する方法は?

async function retry(fn, maxRetries = 3, baseDelay = 1000) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
if (attempt === maxRetries - 1) throw error;

const delay = baseDelay * Math.pow(2, attempt);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}

// 使用方法
const charge = await retry(() =>
omise.charges.create({
amount: 100000,
currency: 'THB',
card: 'tokn_test_123'
})
);

部分払い戻しを処理する方法は?

async function refundCharge(chargeId, refundAmount = null) {
const charge = await omise.charges.retrieve(chargeId);

const refundable = charge.amount - charge.refunded;

if (refundAmount && refundAmount > refundable) {
throw new Error('返金額が返金可能額を超えています');
}

return omise.charges.refund(chargeId, {
amount: refundAmount
});
}

顧客の複数のカードを保存する方法は?

async function addCardToCustomer(customerId, token) {
return omise.customers.update(customerId, { card: token });
}

async function listCustomerCards(customerId) {
const customer = await omise.customers.retrieve(customerId);
return customer.cards.data;
}

async function chargeSpecificCard(customerId, cardId, amount) {
return omise.charges.create({
amount,
currency: 'THB',
customer: customerId,
card: cardId
});
}

サブスクリプション請求を実装する方法は?

const cron = require('node-cron');

class SubscriptionManager {
constructor(customerId, planAmount) {
this.customerId = customerId;
this.planAmount = planAmount;
}

async chargeMonthly() {
const charge = await omise.charges.create({
amount: this.planAmount,
currency: 'THB',
customer: this.customerId,
description: `サブスクリプション ${new Date().toLocaleDateString('ja-JP', { month: 'long', year: 'numeric' })}`
});

return charge;
}

handleFailedPayment(charge) {
// 通知を送信
// サブスクリプションステータスを更新
}
}

// 毎月のチャージをスケジュール
cron.schedule('0 0 1 * *', async () => {
const subscriptions = await getActiveSubscriptions();

for (const subscription of subscriptions) {
const manager = new SubscriptionManager(
subscription.customerId,
subscription.planAmount
);

try {
await manager.chargeMonthly();
} catch (error) {
manager.handleFailedPayment(error);
}
}
});

関連リソース

次のステップ

サポート

Node.js ライブラリで問題が発生した場合:

  1. GitHub Issues を確認してください
  2. API ドキュメント を確認してください
  3. support@omise.co に以下の情報をご連絡ください:
    • Node.js バージョン
    • omise-node ライブラリバージョン
    • エラーメッセージとスタックトレース
    • 再現手順