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

PHPライブラリ (omise-php)

omise-php ライブラリは、優れたLaravelとSymfony統合、最新のPHP機能、および包括的なエラーハンドリングを備えた、PSR準拠のPHPインターフェースをOmise APIに提供します。

インストール

Composerの使用 (推奨)

composer require omise/omise-php

composer.json

{
"require": {
"omise/omise-php": "^2.15"
}
}

要件

  • PHP 7.2以上 (PHP 8.x を含む)
  • cURL 拡張機能
  • JSON 拡張機能
  • 依存関係管理用のComposer

クイックスタート

基本的な構成

<?php
require_once 'vendor/autoload.php';

// APIキーで構成
define('OMISE_SECRET_KEY', 'skey_test_123456789');
define('OMISE_PUBLIC_KEY', 'pkey_test_123456789');

// APIバージョンを設定
define('OMISE_API_VERSION', '2019-05-29');

Laravelの構成

構成ファイルを公開:

php artisan vendor:publish --provider="Omise\OmiseServiceProvider"

.env で構成:

# config/services.php
OMISE_SECRET_KEY=skey_test_123456789
OMISE_PUBLIC_KEY=pkey_test_123456789
OMISE_API_VERSION=2019-05-29

サービスを構成:

<?php
// config/services.php

return [
'omise' => [
'secret_key' => env('OMISE_SECRET_KEY'),
'public_key' => env('OMISE_PUBLIC_KEY'),
'api_version' => env('OMISE_API_VERSION', '2019-05-29'),
],
];

Symfonyの構成

# config/packages/omise.yaml
omise:
secret_key: '%env(OMISE_SECRET_KEY)%'
public_key: '%env(OMISE_PUBLIC_KEY)%'
api_version: '2019-05-29'

認証

ライブラリはすべてのAPI操作にシークレットキーを使用します:

<?php
require_once 'vendor/autoload.php';

// オプション 1: グローバル構成
define('OMISE_SECRET_KEY', getenv('OMISE_SECRET_KEY'));
define('OMISE_PUBLIC_KEY', getenv('OMISE_PUBLIC_KEY'));

// オプション 2: リクエストごとの構成
$charge = OmiseCharge::retrieve('chrg_test_123', 'skey_test_alternate');

一般的な操作

チャージの作成

トークンを使用

<?php
require_once 'vendor/autoload.php';

define('OMISE_SECRET_KEY', getenv('OMISE_SECRET_KEY'));

try {
$charge = OmiseCharge::create([
'amount' => 100000, // 1,000.00 THB (最小通貨単位)
'currency' => 'THB',
'card' => 'tokn_test_123',
'description' => 'Order #1234',
'metadata' => [
'order_id' => '1234',
'customer_name' => 'John Doe'
]
]);

if ($charge['paid']) {
echo "チャージ成功: " . $charge['id'];
} else {
echo "チャージ失敗: " . $charge['failure_message'];
}
} catch (Exception $e) {
echo "エラー: " . $e->getMessage();
}

型宣言を使用 (PHP 7.4+)

<?php
declare(strict_types=1);

class PaymentService
{
public function createCharge(
int $amount,
string $currency,
string $token,
array $metadata = []
): array {
return OmiseCharge::create([
'amount' => $amount,
'currency' => $currency,
'card' => $token,
'metadata' => $metadata
]);
}
}

// 使用方法
$service = new PaymentService();
$charge = $service->createCharge(
100000,
'THB',
'tokn_test_123',
['order_id' => '1234']
);

顧客を使用

<?php
// 既存の顧客のチャージを作成
$charge = OmiseCharge::create([
'amount' => 50000,
'currency' => 'THB',
'customer' => 'cust_test_123',
'description' => 'サブスクリプション支払い'
]);

3Dセキュアで

<?php
// 3Dセキュアが必要な可能性のあるチャージを作成
$charge = OmiseCharge::create([
'amount' => 100000,
'currency' => 'THB',
'card' => 'tokn_test_123',
'return_uri' => 'https://example.com/payment/callback'
]);

if ($charge['authorized']) {
if (isset($charge['authorize_uri'])) {
// 3Dセキュアのためauthorize_uriに顧客をリダイレクト
header('Location: ' . $charge['authorize_uri']);
exit;
} else {
// 3Dセキュアなしでチャージ完了
processSuccessfulPayment($charge);
}
}

チャージの取得

<?php
// IDでチャージを取得
$charge = OmiseCharge::retrieve('chrg_test_123');

echo "金額: " . $charge['amount'] . PHP_EOL;
echo "通貨: " . $charge['currency'] . PHP_EOL;
echo "ステータス: " . $charge['status'] . PHP_EOL;
echo "支払済み: " . ($charge['paid'] ? 'はい' : 'いいえ') . PHP_EOL;

チャージのリスト表示

<?php
// ページネーション付きですべてのチャージをリスト表示
$charges = OmiseCharge::retrieve([
'limit' => 20,
'offset' => 0,
'order' => 'reverse_chronological'
]);

foreach ($charges['data'] as $charge) {
echo $charge['id'] . ": " . $charge['amount'] . " " . $charge['currency'] . PHP_EOL;
}

// フィルタ付きでチャージをリスト表示
$weekAgo = (new DateTime('-7 days'))->format('Y-m-d');
$today = (new DateTime())->format('Y-m-d');

$recentCharges = OmiseCharge::retrieve([
'from' => $weekAgo,
'to' => $today
]);

顧客の作成

<?php
// カードなしで顧客を作成
$customer = OmiseCustomer::create([
'email' => 'customer@example.com',
'description' => 'John Doe',
'metadata' => [
'user_id' => '12345',
'account_type' => 'premium'
]
]);

echo "顧客作成: " . $customer['id'];

顧客へのカード保存

<?php
// カードトークンで顧客を更新
$customer = OmiseCustomer::retrieve('cust_test_123');
$customer = OmiseCustomer::update('cust_test_123', [
'card' => 'tokn_test_456'
]);

echo "カード保存: " . $customer['default_card'];

// または1ステップでカード付きの顧客を作成
$customer = OmiseCustomer::create([
'email' => 'customer@example.com',
'description' => 'John Doe',
'card' => 'tokn_test_123'
]);

顧客カードのリスト表示

<?php
$customer = OmiseCustomer::retrieve('cust_test_123');

foreach ($customer['cards']['data'] as $card) {
echo $card['brand'] . " 末尾番号 " . $card['last_digits'] . PHP_EOL;
echo "有効期限: " . $card['expiration_month'] . "/" . $card['expiration_year'] . PHP_EOL;
}

払い戻しの作成

<?php
// 全額返金
$refund = OmiseRefund::create('chrg_test_123', [
'amount' => null // 全額返金の場合はnull
]);

// 部分払い戻し
$refund = OmiseRefund::create('chrg_test_123', [
'amount' => 25000, // 250.00 THB
'metadata' => [
'reason' => 'customer_request',
'ticket_id' => 'TICKET-123'
]
]);

echo "払い戻し " . $refund['id'] . ": " . $refund['amount'] . " " . $refund['currency'];

転送の作成

<?php
// 銀行口座への転送を作成
$transfer = OmiseTransfer::create([
'amount' => 500000, // 5,000.00 THB
'recipient' => 'recp_test_123',
'metadata' => [
'payout_id' => 'PAYOUT-456'
]
]);

echo "転送 " . $transfer['id'] . ": " . $transfer['amount'];

代替決済方法

ソースの作成

<?php
// PromptPay QR
$source = OmiseSource::create([
'type' => 'promptpay',
'amount' => 100000,
'currency' => 'THB'
]);

// 顧客にQRコードを表示
echo "QRコードURL: " . $source['scannable_code']['image']['download_uri'];

// ソース付きでチャージを作成
$charge = OmiseCharge::create([
'amount' => 100000,
'currency' => 'THB',
'source' => $source['id'],
'return_uri' => 'https://example.com/payment/callback'
]);

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

<?php
// インターネットバンキング
$source = OmiseSource::create([
'type' => 'internet_banking_scb',
'amount' => 100000,
'currency' => 'THB'
]);

$charge = OmiseCharge::create([
'amount' => 100000,
'currency' => 'THB',
'source' => $source['id'],
'return_uri' => 'https://example.com/payment/callback'
]);

// 顧客をauthorize_uriにリダイレクト
header('Location: ' . $charge['authorize_uri']);
exit;

モバイルバンキング

<?php
// モバイルバンキング (SCB Easy)
$source = OmiseSource::create([
'type' => 'mobile_banking_scb',
'amount' => 100000,
'currency' => 'THB'
]);

$charge = OmiseCharge::create([
'amount' => 100000,
'currency' => 'THB',
'source' => $source['id'],
'return_uri' => 'https://example.com/payment/callback'
]);

インストール

<?php
// 分割払い
$source = OmiseSource::create([
'type' => 'installment_kbank',
'amount' => 100000,
'currency' => 'THB',
'installment_term' => 6 // 6ヶ月
]);

$charge = OmiseCharge::create([
'amount' => 100000,
'currency' => 'THB',
'source' => $source['id'],
'return_uri' => 'https://example.com/payment/callback'
]);

エラーハンドリング

ライブラリは異なるエラータイプに対して例外をスローします:

<?php
require_once 'vendor/autoload.php';

try {
$charge = OmiseCharge::create([
'amount' => 100000,
'currency' => 'THB',
'card' => 'tokn_test_123'
]);
} catch (OmiseException $e) {
// エラー詳細を取得
echo "エラー: " . $e->getMessage() . PHP_EOL;
echo "HTTPステータス: " . $e->getHttpStatus() . PHP_EOL;
echo "エラーコード: " . $e->getOmiseCode() . PHP_EOL;

// 特定のエラーを処理
if ($e->getOmiseCode() === 'authentication_failure') {
echo "無効なAPIキー";
} elseif ($e->getOmiseCode() === 'invalid_card') {
echo "カードが拒否されました";
}
}

特定のカードエラーの処理

<?php
function handleCardError(OmiseException $e): string
{
$errorMessages = [
'insufficient_fund' => 'カードの残高不足',
'stolen_or_lost_card' => 'カードが盗難または紛失として報告されています',
'invalid_security_code' => '無効なCVVコード',
'payment_cancelled' => '支払いがキャンセルされました'
];

return $errorMessages[$e->getOmiseCode()] ?? "カードエラー: " . $e->getMessage();
}

try {
$charge = OmiseCharge::create([
'amount' => 100000,
'currency' => 'THB',
'card' => $token
]);
} catch (OmiseException $e) {
$errorMessage = handleCardError($e);
// ユーザーにエラーを表示
}

Laravel統合

コントローラーの例

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use App\Models\Order;
use App\Models\Payment;

class PaymentController extends Controller
{
public function __construct()
{
define('OMISE_SECRET_KEY', config('services.omise.secret_key'));
define('OMISE_PUBLIC_KEY', config('services.omise.public_key'));
}

public function create(Request $request, $orderId)
{
$order = Order::findOrFail($orderId);

$request->validate([
'omise_token' => 'required|string',
]);

try {
$charge = \OmiseCharge::create([
'amount' => (int)($order->total * 100),
'currency' => 'THB',
'card' => $request->omise_token,
'description' => "Order #{$order->id}",
'metadata' => [
'order_id' => $order->id,
'customer_email' => $order->email
],
'return_uri' => route('payment.callback')
]);

// 支払いレコードを保存
Payment::create([
'order_id' => $order->id,
'charge_id' => $charge['id'],
'amount' => $order->total,
'status' => $charge['status'],
'paid' => $charge['paid']
]);

if ($charge['paid']) {
$order->update(['payment_status' => 'paid']);
return redirect()->route('orders.show', $order)
->with('success', '支払いが成功しました!');
} elseif (isset($charge['authorize_uri'])) {
// 3Dセキュアが必要
return redirect($charge['authorize_uri']);
} else {
return back()->with('error', $charge['failure_message']);
}

} catch (\OmiseException $e) {
Log::error('Omiseエラー: ' . $e->getMessage());
return back()->with('error', '支払いに失敗しました。もう一度お試しください。');
}
}

public function callback(Request $request)
{
$chargeId = $request->query('id');

try {
$charge = \OmiseCharge::retrieve($chargeId);
$payment = Payment::where('charge_id', $charge['id'])->firstOrFail();

$payment->update([
'status' => $charge['status'],
'paid' => $charge['paid']
]);

if ($charge['paid']) {
$payment->order->update(['payment_status' => 'paid']);
return redirect()->route('orders.show', $payment->order)
->with('success', '支払いが成功しました!');
} else {
return redirect()->route('payment.form', $payment->order)
->with('error', $charge['failure_message']);
}

} catch (\Exception $e) {
return redirect()->route('home')
->with('error', '支払い検証に失敗しました。');
}
}
}

モデル統合

<?php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Payment extends Model
{
protected $fillable = [
'order_id', 'charge_id', 'amount', 'currency', 'status',
'paid', 'failure_code', 'failure_message', 'refund_id', 'refund_amount'
];

protected $casts = [
'amount' => 'decimal:2',
'refund_amount' => 'decimal:2',
'paid' => 'boolean'
];

public function __construct()
{
parent::__construct();
define('OMISE_SECRET_KEY', config('services.omise.secret_key'));
}

public function order()
{
return $this->belongsTo(Order::class);
}

public function charge(string $token): array
{
$charge = \OmiseCharge::create([
'amount' => (int)($this->amount * 100),
'currency' => $this->currency,
'card' => $token,
'description' => "Order #{$this->order->id}",
'metadata' => $this->getChargeMetadata()
]);

$this->update([
'charge_id' => $charge['id'],
'status' => $charge['status'],
'paid' => $charge['paid']
]);

return $charge;
}

public function refund(?float $refundAmount = null): array
{
if (!$this->charge_id) {
throw new \Exception('charge_idなしで支払いを返金できません');
}

$refund = \OmiseRefund::create($this->charge_id, [
'amount' => $refundAmount ? (int)($refundAmount * 100) : null
]);

$this->update([
'refund_id' => $refund['id'],
'refund_amount' => $refund['amount'] / 100,
'status' => 'refunded'
]);

return $refund;
}

public function refreshStatus(): void
{
if (!$this->charge_id) {
return;
}

$charge = \OmiseCharge::retrieve($this->charge_id);

$this->update([
'status' => $charge['status'],
'paid' => $charge['paid'],
'failure_code' => $charge['failure_code'] ?? null,
'failure_message' => $charge['failure_message'] ?? null
]);
}

protected function getChargeMetadata(): array
{
return [
'order_id' => $this->order->id,
'customer_email' => $this->order->email,
'customer_name' => $this->order->customer_name
];
}
}

非同期処理用のキュージョブ

<?php
namespace App\Jobs;

use App\Models\Payment;
use App\Mail\PaymentConfirmed;
use App\Mail\PaymentFailed;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Log;

class ProcessChargeJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

public $tries = 3;
public $backoff = [60, 120, 240];

protected $paymentId;
protected $token;

public function __construct(int $paymentId, string $token)
{
$this->paymentId = $paymentId;
$this->token = $token;

define('OMISE_SECRET_KEY', config('services.omise.secret_key'));
}

public function handle()
{
$payment = Payment::findOrFail($this->paymentId);

try {
$charge = $payment->charge($this->token);

if ($charge['paid']) {
Mail::to($payment->order->email)
->send(new PaymentConfirmed($payment));
} else {
Mail::to($payment->order->email)
->send(new PaymentFailed($payment, $charge['failure_message']));
}

} catch (\OmiseException $e) {
$payment->update([
'status' => 'failed',
'failure_message' => $e->getMessage()
]);

Mail::to($payment->order->email)
->send(new PaymentFailed($payment, $e->getMessage()));

Log::error('チャージ処理失敗', [
'payment_id' => $this->paymentId,
'error' => $e->getMessage()
]);
}
}
}

サービスプロバイダー

<?php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class OmiseServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton('omise', function ($app) {
return new \OmiseClient(
config('services.omise.secret_key'),
config('services.omise.public_key')
);
});
}

public function boot()
{
if ($this->app->runningInConsole()) {
$this->publishes([
__DIR__.'/../config/omise.php' => config_path('omise.php'),
], 'config');
}
}
}

ベストプラクティス

1. キーに環境変数を使用

<?php
// APIキーをハードコードしない
// 悪い例
define('OMISE_SECRET_KEY', 'skey_test_123456789');

// 良い例
define('OMISE_SECRET_KEY', getenv('OMISE_SECRET_KEY'));

// より良い例 (Laravel)
define('OMISE_SECRET_KEY', config('services.omise.secret_key'));

// キーが存在することを検証
if (empty(OMISE_SECRET_KEY)) {
throw new \RuntimeException('OMISE_SECRET_KEYが設定されていません');
}

2. べき等性の処理

<?php
class PaymentService
{
public function createIdempotentCharge(
int $amount,
string $currency,
string $token,
string $orderId
): array {
$idempotencyKey = sprintf('order-%s-%s', $orderId, time());

// べき等性キーをキャッシュ/データベースに保存
\Cache::put("charge:idempotency:{$orderId}", $idempotencyKey, 3600);

return OmiseCharge::create([
'amount' => $amount,
'currency' => $currency,
'card' => $token
], $idempotencyKey);
}
}

3. 型宣言を使用 (PHP 7.4+)

<?php
declare(strict_types=1);

class ChargeService
{
private string $secretKey;

public function __construct(string $secretKey)
{
$this->secretKey = $secretKey;
define('OMISE_SECRET_KEY', $secretKey);
}

public function createCharge(
int $amount,
string $currency,
string $token,
array $metadata = []
): array {
return OmiseCharge::create([
'amount' => $amount,
'currency' => $currency,
'card' => $token,
'metadata' => $metadata
]);
}
}

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

<?php
class Payment
{
private string $chargeId;
private ?array $chargeCache = null;

public function getCharge(): array
{
if ($this->chargeCache === null) {
$this->chargeCache = \OmiseCharge::retrieve($this->chargeId);
}
return $this->chargeCache;
}

public function refreshCharge(): array
{
$this->chargeCache = null;
return $this->getCharge();
}
}

5. API呼び出し前の検証

<?php
class ChargeValidator
{
public function validate(int $amount, string $currency): void
{
if ($amount < 2000) {
throw new \InvalidArgumentException('金額は最低20 THBである必要があります');
}

$allowedCurrencies = ['THB', 'USD', 'SGD', 'JPY'];
if (!in_array($currency, $allowedCurrencies)) {
throw new \InvalidArgumentException("通貨 {$currency} はサポートされていません");
}
}
}

// 使用方法
$validator = new ChargeValidator();
$validator->validate(100000, 'THB');
$charge = OmiseCharge::create([...]);

6. ロギングの実装

<?php
use Psr\Log\LoggerInterface;

class PaymentService
{
private LoggerInterface $logger;

public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}

public function createCharge(array $params): array
{
$this->logger->info('チャージ作成中', [
'amount' => $params['amount'],
'currency' => $params['currency']
]);

try {
$charge = OmiseCharge::create($params);

$this->logger->info('チャージ作成完了', [
'charge_id' => $charge['id'],
'paid' => $charge['paid']
]);

return $charge;

} catch (\OmiseException $e) {
$this->logger->error('チャージ失敗', [
'error' => $e->getMessage(),
'code' => $e->getOmiseCode()
]);

throw $e;
}
}
}

テスト

PHPUnitの例

<?php
namespace Tests\Unit;

use PHPUnit\Framework\TestCase;
use Mockery;

class PaymentServiceTest extends TestCase
{
protected function tearDown(): void
{
Mockery::close();
}

public function testCreateCharge()
{
// OmiseChargeをモック
$chargeMock = Mockery::mock('alias:OmiseCharge');
$chargeMock->shouldReceive('create')
->once()
->with([
'amount' => 100000,
'currency' => 'THB',
'card' => 'tokn_test_123'
])
->andReturn([
'id' => 'chrg_test_123',
'amount' => 100000,
'currency' => 'THB',
'paid' => true,
'status' => 'successful'
]);

$service = new \App\Services\PaymentService();
$charge = $service->createCharge(100000, 'THB', 'tokn_test_123');

$this->assertEquals('chrg_test_123', $charge['id']);
$this->assertTrue($charge['paid']);
}

public function testCreateChargeWithError()
{
$this->expectException(\OmiseException::class);

$chargeMock = Mockery::mock('alias:OmiseCharge');
$chargeMock->shouldReceive('create')
->once()
->andThrow(new \OmiseException('insufficient_fund'));

$service = new \App\Services\PaymentService();
$service->createCharge(100000, 'THB', 'tokn_test_123');
}
}

Laravel機能テスト

<?php
namespace Tests\Feature;

use Tests\TestCase;
use App\Models\Order;
use App\Models\Payment;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Mockery;

class PaymentControllerTest extends TestCase
{
use RefreshDatabase;

protected function setUp(): void
{
parent::setUp();
config(['services.omise.secret_key' => 'skey_test_123']);
}

public function testCreatePayment()
{
$order = Order::factory()->create(['total' => 1000.00]);

$chargeMock = Mockery::mock('alias:OmiseCharge');
$chargeMock->shouldReceive('create')
->once()
->andReturn([
'id' => 'chrg_test_123',
'paid' => true,
'status' => 'successful'
]);

$response = $this->post("/payment/{$order->id}", [
'omise_token' => 'tokn_test_123'
]);

$response->assertRedirect(route('orders.show', $order));
$this->assertDatabaseHas('payments', [
'order_id' => $order->id,
'charge_id' => 'chrg_test_123',
'paid' => true
]);
}
}

トラブルシューティング

SSL証明書エラー

<?php
// CA bundleを更新 (本番環境では非推奨)
define('OMISE_CA_BUNDLE_PATH', '/path/to/cacert.pem');

// またはSSL検証を無効化 (テスト用のみ!)
// 本番環境では推奨されません

接続タイムアウト

<?php
// カスタムタイムアウトを設定
define('OMISE_API_TIMEOUT', 60); // 秒

デバッグモード

<?php
// デバッグモードを有効化
define('OMISE_DEBUG', true);

// リクエスト/レスポンスの詳細が出力されます

ウェブフック署名検証

<?php
function verifyWebhookSignature(string $payload, string $signature, string $secret): bool
{
$expectedSignature = hash_hmac('sha256', $payload, $secret);
return hash_equals($signature, $expectedSignature);
}

// 使用方法
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_OMISE_SIGNATURE'] ?? '';

if (!verifyWebhookSignature($payload, $signature, getenv('OMISE_WEBHOOK_SECRET'))) {
http_response_code(401);
exit('無効な署名');
}

$event = json_decode($payload, true);
// イベントを処理

よくある質問

LaravelでウェブフックをどのようにHandleしますか?

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

class WebhookController extends Controller
{
public function omise(Request $request)
{
// 署名を検証
$payload = $request->getContent();
$signature = $request->header('Omise-Signature');

if (!$this->verifySignature($payload, $signature)) {
return response()->json(['error' => '無効な署名'], 401);
}

$event = $request->json()->all();

switch ($event['key']) {
case 'charge.complete':
$this->handleChargeComplete($event['data']);
break;
case 'refund.create':
$this->handleRefundCreate($event['data']);
break;
}

return response()->json(['status' => 'ok']);
}

protected function verifySignature(string $payload, string $signature): bool
{
$expected = hash_hmac('sha256', $payload, config('services.omise.webhook_secret'));
return hash_equals($signature, $expected);
}

protected function handleChargeComplete(array $chargeData): void
{
$charge = \OmiseCharge::retrieve($chargeData['id']);
$payment = Payment::where('charge_id', $charge['id'])->first();

if ($payment) {
$payment->update([
'status' => $charge['status'],
'paid' => $charge['paid']
]);
}
}
}

実際のチャージなしで支払いをテストするにはどうすればよいですか?

<?php
// テストAPIキーを使用
define('OMISE_SECRET_KEY', 'skey_test_123456789');

// テストカードトークンを使用
// 成功: tokn_test_5086xl7ddjbases4sq3i
// 拒否: tokn_test_no1

$charge = OmiseCharge::create([
'amount' => 100000,
'currency' => 'THB',
'card' => 'tokn_test_5086xl7ddjbases4sq3i'
]);

// テストモードを確認
var_dump($charge['livemode'] === false);

通貨変換をどのように処理しますか?

<?php
class Money
{
private int $amountSatang;

public function __construct(float $amountBaht)
{
$this->amountSatang = (int)($amountBaht * 100);
}

public function getSatang(): int
{
return $this->amountSatang;
}

public function getBaht(): float
{
return $this->amountSatang / 100;
}

public static function fromSatang(int $amountSatang): self
{
$instance = new self(0);
$instance->amountSatang = $amountSatang;
return $instance;
}
}

// 使用方法
$money = new Money(1000.00); // 1000.00 THB
$charge = OmiseCharge::create([
'amount' => $money->getSatang(), // 100000サタン
'currency' => 'THB',
'card' => 'tokn_test_123'
]);

リトライロジックをどのように実装しますか?

<?php
function createChargeWithRetry(array $params, int $maxRetries = 3): array
{
$attempt = 0;

while ($attempt < $maxRetries) {
try {
return OmiseCharge::create($params);
} catch (\OmiseException $e) {
$attempt++;

if ($attempt >= $maxRetries) {
throw $e;
}

// 指数バックオフ
sleep(2 ** $attempt);
}
}
}

部分返金をどのように処理しますか?

<?php
function refundCharge(string $chargeId, ?float $refundAmount = null): array
{
// 現在のチャージを取得
$charge = \OmiseCharge::retrieve($chargeId);

// 返金可能金額を計算
$refundable = $charge['amount'] - $charge['refunded'];

if ($refundAmount !== null) {
$refundAmountSatang = (int)($refundAmount * 100);
if ($refundAmountSatang > $refundable) {
throw new \Exception("返金金額が返金可能金額を超えています");
}
} else {
$refundAmountSatang = null; // 全額返金
}

return \OmiseRefund::create($chargeId, [
'amount' => $refundAmountSatang
]);
}

顧客に複数のカードを保存するにはどうすればよいですか?

<?php
function addCardToCustomer(string $customerId, string $token): array
{
return \OmiseCustomer::update($customerId, [
'card' => $token
]);
}

function listCustomerCards(string $customerId): array
{
$customer = \OmiseCustomer::retrieve($customerId);
return $customer['cards']['data'];
}

function chargeSpecificCard(string $customerId, string $cardId, int $amount): array
{
return \OmiseCharge::create([
'amount' => $amount,
'currency' => 'THB',
'customer' => $customerId,
'card' => $cardId
]);
}

サブスクリプション請求をどのように実装しますか?

<?php
class SubscriptionManager
{
private string $customerId;
private int $planAmount;

public function __construct(string $customerId, int $planAmount)
{
$this->customerId = $customerId;
$this->planAmount = $planAmount;
}

public function chargeMonthly(): array
{
return \OmiseCharge::create([
'amount' => $this->planAmount,
'currency' => 'THB',
'customer' => $this->customerId,
'description' => 'Subscription ' . date('F Y')
]);
}

public function handleFailedPayment(array $charge): void
{
// 通知を送信
// サブスクリプションステータスを更新
// 猶予期間後に再試行
}
}

// Laravelコマンド
namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Models\Subscription;

class ChargeSubscriptions extends Command
{
protected $signature = 'subscriptions:charge';

public function handle()
{
$subscriptions = Subscription::where('status', 'active')->get();

foreach ($subscriptions as $subscription) {
$manager = new SubscriptionManager(
$subscription->customer_id,
$subscription->plan_amount
);

try {
$charge = $manager->chargeMonthly();
$subscription->update(['last_charge_date' => now()]);
} catch (\OmiseException $e) {
$manager->handleFailedPayment($charge);
}
}
}
}

関連リソース

次のステップ

サポート

PHPライブラリで問題が発生した場合:

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