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

TrueMoney Wallet

3000万人以上のアクティブユーザーを持つタイで最も人気のあるe-walletの1つからオンライン決済を受け付けます。顧客は電話番号を入力し、OTPで認証するためにリダイレクトされます。

QRコード決済をお探しですか?

オフラインQRコードベースの決済については、TrueMoney QRをご覧ください。このページではオンラインリダイレクトフローについて説明しています。

支払いフロー

TrueMoney Payment Flow

上記の画像は、ワンタイムパスワード(OTP)検証を使用した完全なredirect支払いフローを示しています。

概要

ユーザー統計

ユーザー数は概算であり、公開されている情報に基づいています。実際のアクティブユーザー数は異なる場合があります。

TrueMoney Walletは、3000万人以上のユーザーを持つタイの主要なモバイル決済ソリューションです。ウォレットにより、顧客はセキュリティ強化のためのOTP検証付きで携帯電話番号を使用して支払いを行うことができます。

主な機能:

  • 大規模なユーザーベース - タイで3000万人以上のアクティブユーザー
  • シンプルなフロー - 電話番号 + OTP認証
  • 迅速な決済 - 従来の銀行よりも高速
  • モバイルファースト - スマートフォンユーザーに最適化
  • 信頼できるブランド - Ascend Group(CPグループ)の一部

サポートされている地域

地域通貨最小金額最大金額1日の上限
タイTHB฿20.00฿100,000฿40,000 - ฿200,000*

*1日の上限は顧客のKYC検証レベルによって異なります

検証レベル別の取引制限

検証レベル取引ごと1日の上限月間上限
Basic(電話のみ)฿100,000฿40,000฿200,000
Plus(IDカード)฿100,000฿100,000฿500,000
Premium(銀行口座)฿100,000฿200,000無制限

仕組み

顧客体験:

  1. 顧客がチェックアウト時にTrueMoneyを選択
  2. 携帯電話番号を入力
  3. SMSでOTPを受信
  4. OTPを入力して承認
  5. 支払い金額を確認
  6. 加盟店サイトに戻る

実装

ステップ1: TrueMoney Sourceの作成

curl https://api.omise.co/sources \
-u skey_test_YOUR_SECRET_KEY: \
-d "type=truemoney" \
-d "amount=50000" \
-d "currency=THB" \
-d "phone_number=+66876543210"

レスポンス:

{
"object": "source",
"id": "src_test_5rt6s9vah5lkvi1rh9c",
"type": "truemoney",
"flow": "redirect",
"amount": 50000,
"currency": "THB",
"phone_number": "+66876543210"
}

ステップ2: Chargeの作成

curl https://api.omise.co/charges \
-u skey_test_YOUR_SECRET_KEY: \
-d "amount=50000" \
-d "currency=THB" \
-d "source=src_test_5rt6s9vah5lkvi1rh9c" \
-d "return_uri=https://yourdomain.com/payment/callback"

ステップ3: 顧客のredirect

app.post('/create-truemoney-payment', async (req, res) => {
// Create source
const source = await omise.sources.create({
type: 'truemoney',
amount: req.body.amount,
currency: 'THB',
phone_number: req.body.phone_number
});

// Create charge
const charge = await omise.charges.create({
amount: req.body.amount,
currency: 'THB',
source: source.id,
return_uri: 'https://yourdomain.com/payment/callback',
metadata: {
order_id: req.body.order_id
}
});

// Redirect customer
res.redirect(charge.authorize_uri);
});

ステップ4: returnの処理

app.get('/payment/callback', async (req, res) => {
const chargeId = req.query.charge_id;

// Retrieve charge status
const charge = await omise.charges.retrieve(chargeId);

if (charge.status === 'successful') {
// Payment successful
await processOrder(charge.metadata.order_id);
res.redirect('/payment-success');
} else if (charge.status === 'failed') {
// Payment failed
res.redirect('/payment-failed?reason=' + charge.failure_message);
} else {
// Still pending
res.redirect('/payment-pending');
}
});

ステップ5: webhookの処理

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

if (event.key === 'charge.complete' && event.data.source.type === 'truemoney') {
const charge = event.data;

if (charge.status === 'successful') {
processOrder(charge.metadata.order_id);
}
}

res.sendStatus(200);
});

完全な実装例

// Express.js server
const express = require('express');
const omise = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY
});

const app = express();
app.use(express.json());

// Checkout page
app.post('/checkout/truemoney', async (req, res) => {
try {
const { amount, phone_number, order_id } = req.body;

// Validate phone number format
if (!/^\+66\d{9}$/.test(phone_number)) {
return res.status(400).json({
error: 'Invalid phone number. Use format: +66876543210'
});
}

// Check amount limits
if (amount < 2000 || amount > 10000000) {
return res.status(400).json({
error: 'Amount must be between ฿20 and ฿100,000'
});
}

// Create source
const source = await omise.sources.create({
type: 'truemoney',
amount: amount,
currency: 'THB',
phone_number: phone_number
});

// Create charge
const charge = await omise.charges.create({
amount: amount,
currency: 'THB',
source: source.id,
return_uri: `${process.env.BASE_URL}/payment/callback`,
metadata: {
order_id: order_id,
customer_phone: phone_number
}
});

// Return authorization URL
res.json({
authorize_uri: charge.authorize_uri,
charge_id: charge.id
});

} catch (error) {
console.error('TrueMoney payment error:', error);
res.status(500).json({ error: error.message });
}
});

// Callback handler
app.get('/payment/callback', async (req, res) => {
try {
const chargeId = req.query.charge_id;
const charge = await omise.charges.retrieve(chargeId);

if (charge.status === 'successful') {
res.redirect(`/order-success?order=${charge.metadata.order_id}`);
} else {
res.redirect(`/payment-failed?charge=${chargeId}`);
}
} catch (error) {
res.redirect('/payment-error');
}
});

// Webhook handler
app.post('/webhooks/omise', (req, res) => {
const event = req.body;

if (event.key === 'charge.complete') {
const charge = event.data;

if (charge.source.type === 'truemoney') {
if (charge.status === 'successful') {
// Process order
updateOrderStatus(charge.metadata.order_id, 'paid');
sendConfirmation(charge.metadata.customer_phone);
} else {
// Handle failure
updateOrderStatus(charge.metadata.order_id, 'failed');
}
}
}

res.sendStatus(200);
});

app.listen(3000);

voidと返金のサポート

chargeのvoid

TrueMoneyはcharge作成から24時間以内のvoidをサポート:

// Void immediately (full or partial)
const refund = await omise.charges.refund('chrg_test_...', {
amount: 50000 // Full amount
});

if (refund.voided) {
console.log('Charge was voided (within 24 hours)');
}

返金

30日以内全額返金のみ:

// Full refund only
const refund = await omise.charges.refund('chrg_test_...', {
amount: 50000 // Must be full amount
});
部分返金なし

TrueMoney Walletは部分返金をサポートしていません。30日以内の全額返金のみが許可されています。

よくある問題とトラブルシューティング

問題: "無効な電話番号"

原因:

  • 間違った形式
  • 国コードが欠落
  • タイ以外の番号

解決策:

function validateThaiPhone(phone) {
// Accept formats: +66876543210, 0876543210
let normalized = phone.replace(/\s/g, '');

if (normalized.startsWith('0')) {
normalized = '+66' + normalized.substring(1);
}

if (!/^\+66\d{9}$/.test(normalized)) {
throw new Error('Invalid Thai phone number');
}

return normalized;
}

問題: 顧客が1日の上限を超過

エラー: 取引が拒否されました

解決策:

  • 顧客がTrueMoneyアカウントの検証をアップグレードする必要があります
  • 複数日にわたって支払いを分割
  • 代替決済方法を使用

問題: 支払いが長時間保留中

原因: 顧客がOTP検証を完了しませんでした

解決策:

  • 15〜20分のタイムアウトを設定
  • 顧客が新しいchargeで再試行できるようにする
  • 明確な指示を表示

問題: return URIが呼び出されない

原因: 顧客がブラウザを閉じました

解決策:

  • webhook処理を実装(より信頼性が高い)
  • 注文ステータス確認ページを提供
  • 顧客にSMS確認を送信

ベストプラクティス

1. 電話番号の検証

const phoneRegex = /^\+66[0-9]{9}$/;

if (!phoneRegex.test(phoneNumber)) {
return res.status(400).json({
error: 'Please enter a valid Thai phone number (e.g., +66876543210)'
});
}

2. 明確な指示を表示

<div class="truemoney-instructions">
<h3>TrueMoney Walletで支払う</h3>
<ol>
<li>TrueMoneyに登録されている電話番号を入力してください</li>
<li>SMSでOTPが送信されます</li>
<li>OTPを入力して支払いを承認してください</li>
<li>金額を確認してください</li>
</ol>
<p>TrueMoney Walletに十分な残高があることを確認してください。</p>
</div>

3. タイムアウトの処理

// Set reasonable timeout
setTimeout(() => {
if (!paymentConfirmed) {
showTimeoutMessage();
allowRetry();
}
}, 15 * 60 * 1000); // 15 minutes

4. webhookを使用

redirectコールバックのみに依存しないでください:

// Webhook is more reliable
app.post('/webhooks/omise', handleWebhook);

// Callback is backup
app.get('/payment/callback', handleCallback);

5. 顧客サポートを提供

metadata: {
order_id: orderId,
customer_phone: phoneNumber,
customer_email: email,
support_ticket: ticketId
}

FAQ

TrueMoney Walletとは何ですか?

TrueMoney Walletは、3000万人以上のユーザーを持つタイのモバイル決済アプリです。顧客はウォレットにお金をロードし、OTP認証付きの電話番号を使用して支払うことができます。

顧客は最初に登録する必要がありますか?

はい、顧客は既存のTrueMoney Walletアカウントを持っている必要があります。アプリをダウンロードして、タイの電話番号で登録できます。

取引手数料はいくらですか?

現在の料金については、Omiseダッシュボードを確認してください。e-wallet手数料は通常、クレジットカードよりも低くなっています。

決済にはどのくらいかかりますか?

決済は通常、クレジットカードよりも高速です。具体的なタイムラインについては、Omiseサポートに確認してください。

海外の顧客はTrueMoneyを使用できますか?

TrueMoneyは、タイの電話番号とタイの銀行口座を持つタイの顧客のみが利用できます。

顧客の残高が不足している場合はどうなりますか?

支払いは失敗します。顧客は以下の方法でTrueMoney Walletにチャージできます:

  • セブンイレブン店舗
  • 銀行振込
  • クレジット/デビットカード
  • TrueMoneyキオスク

その後、支払いを再試行してください。

テスト

テストモード

TrueMoney Walletは、テストAPIキーを使用してテストモードでテストできます。テストモードでは:

テスト認証情報:

  • 有効なタイの電話番号形式(+66XXXXXXXXX)を使用
  • テストchargeは実際に顧客アカウントから引き落とされません
  • すべてのテストデータはテストAPIキー(skey_test_xxx)を使用

テストフロー:

  1. テストAPIキーを使用してsourceとchargeを作成
  2. redirectのauthorize_uriを受け取ります
  3. テストモードでは、ダッシュボードでchargeを成功/失敗として手動でマーク
  4. ステータスの変更に基づいてwebhookがトリガーされます

ステータス変更のテスト:

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

// In test mode, use Omise Dashboard to:
// 1. Navigate to the charge
// 2. Use "Actions" menu to mark as successful or failed
// 3. Verify webhook handling

テストシナリオ:

  • 成功した支払い: 注文処理ワークフローを検証
  • 失敗した支払い: エラー処理と再試行ロジックをテスト
  • タイムアウト: 放棄された支払いシナリオをテスト
  • webhook配信: すべてのwebhookが適切に受信されることを確認

重要な注意事項:

  • テストモードのQR codeはredirectしますが、実際のTrueMoneyサーバーには接続しません
  • ダッシュボードを使用して支払い完了をシミュレート
  • 本番環境に移行する前に常にwebhook処理をテスト
  • 金額制限と検証ロジックを検証

包括的なテストガイドラインについては、テストドキュメントを参照してください。

関連リソース

次のステップ

  1. TrueMoney sourceの作成
  2. redirectフローの実装
  3. webhook処理の設定
  4. 支払いフローのテスト
  5. 本番環境へ