Pay-easy
Accept payments via Pay-easy, Japan's standardized payment service allowing customers to pay through ATMs or online banking at any participating bank.
Overviewโ
Pay-easy is a Japanese payment service that enables customers to pay bills and make purchases through ATMs or internet banking. It's widely trusted and used by over 50 million Japanese consumers for utility bills, taxes, and online shopping.
Key Features:
- โ Multi-bank - Works with all major Japanese banks
- โ 50M+ users - Wide adoption across Japan
- โ ATM or online - Flexible payment channels
- โ Trusted - Backed by major Japanese banks
- โ 24/7 availability - Pay anytime
- โ ๏ธ No refunds - Refunds not supported via API
Supported Banksโ
Pay-easy works with virtually all Japanese banks including:
Major Banks:
- Mizuho Bank (ใฟใใป้่ก)
- MUFG Bank (ไธ่ฑUFJ้่ก)
- Sumitomo Mitsui Banking Corporation (ไธไบไฝๅ้่ก)
- Japan Post Bank (ใใใกใ้่ก)
- Resona Bank (ใใใช้่ก)
And 1,000+ other banks, credit unions, and online banks.
| Region | Currency | Min Amount | Max Amount | API Version |
|---|---|---|---|---|
| Japan | JPY | ยฅ200 | ยฅ49,999 | 2017-11-02 |
How It Worksโ
Customer Experience:
Option 1: ATM Payment
- Customer receives Pay-easy code
- Goes to any bank ATM
- Selects "Pay-easy" (ใใคใธใผ)
- Entersๅ็ดๆฉ้ข็ชๅท (billing organization code)
- Enters customer number and confirmation number
- Inserts cash or uses bank card
- Receives receipt
Option 2: Online Banking
- Customer logs into internet banking
- Selects "Pay-easy" payment
- Enters payment code information
- Confirms payment
- Receives confirmation
Typical completion time: 1-24 hours (depends on customer action)
Implementationโ
Create Pay-easy Sourceโ
- Node.js
- PHP
- Python
const omise = require('omise')({
secretKey: 'skey_test_YOUR_SECRET_KEY'
});
// Create Pay-easy source
const source = await omise.sources.create({
type: 'pay_easy',
amount: 100000, // ยฅ100,000
currency: 'JPY'
});
// Payment code details
console.log('Payment Code:', source.references.payment_code);
console.log('Expires at:', source.references.expires_at);
// Create charge
const charge = await omise.charges.create({
amount: 100000,
currency: 'JPY',
source: source.id,
metadata: {
order_id: 'ORD-12345'
}
});
// Display payment instructions to customer
<?php
$source = OmiseSource::create(array(
'type' => 'pay_easy',
'amount' => 100000,
'currency' => 'JPY'
));
$paymentCode = $source['references']['payment_code'];
$expiresAt = $source['references']['expires_at'];
$charge = OmiseCharge::create(array(
'amount' => 100000,
'currency' => 'JPY',
'source' => $source['id']
));
?>
import omise
omise.api_secret = 'skey_test_YOUR_SECRET_KEY'
source = omise.Source.create(
type='pay_easy',
amount=100000,
currency='JPY'
)
payment_code = source.references['payment_code']
expires_at = source.references['expires_at']
charge = omise.Charge.create(
amount=100000,
currency='JPY',
source=source.id
)
Display Payment Instructionsโ
<div class="pay-easy-instructions">
<h2>ใๆฏๆใๆนๆณ (Pay-easy Payment)</h2>
<div class="payment-code">
<h3>ใๆฏๆใๆ
ๅ ฑ</h3>
<table>
<tr>
<th>ๅ็ดๆฉ้ข็ชๅท</th>
<td>{{ billing_code }}</td>
</tr>
<tr>
<th>ใๅฎขๆง็ชๅท</th>
<td>{{ customer_number }}</td>
</tr>
<tr>
<th>็ขบ่ช็ชๅท</th>
<td>{{ confirmation_number }}</td>
</tr>
<tr>
<th>ใๆฏๆใ้้ก</th>
<td>ยฅ{{ amount }}</td>
</tr>
<tr>
<th>ใๆฏๆใๆ้</th>
<td>{{ expiry_date }}</td>
</tr>
</table>
</div>
<div class="payment-methods">
<div class="method">
<h4>ATMใงใฎใๆฏๆใ</h4>
<ol>
<li>ใ่ฟใใฎ้่กATMใธ</li>
<li>ใ็จ้ใปๆ้ๆ่พผใใพใใฏใใใคใธใผใใ้ธๆ</li>
<li>ไธ่จใฎ็ชๅทใๅ
ฅๅ</li>
<li>ๅ
ๅฎนใ็ขบ่ชใใฆๆฏๆใ</li>
<li>ใฌใทใผใใๅใๅใ</li>
</ol>
</div>
<div class="method">
<h4>ใใใใใณใญใณใฐใงใฎใๆฏๆใ</h4>
<ol>
<li>ใๅฉ็จใฎ้่กใฎใใใใใณใญใณใฐใซใญใฐใคใณ</li>
<li>ใ็จ้ใปๆ้ๆ่พผใใพใใฏใใใคใธใผใใ้ธๆ</li>
<li>ไธ่จใฎ็ชๅทใๅ
ฅๅ</li>
<li>ๅ
ๅฎนใ็ขบ่ชใใฆๆฏๆใ</li>
<li>็ขบ่ชใกใผใซใๅไฟก</li>
</ol>
</div>
</div>
<div class="supported-banks">
<h4>ใๅฉ็จๅฏ่ฝใช้่ๆฉ้ข</h4>
<p>ๅ
จๅฝใฎใใคใธใผๅฏพๅฟ้่ๆฉ้ข๏ผ้ฝๅธ้่กใๅฐๆน้่กใไฟก็จ้ๅบซใใใใกใ้่กใชใฉ๏ผ</p>
</div>
</div>
<style>
.payment-code {
background: #f5f5f5;
padding: 20px;
border-radius: 8px;
margin: 20px 0;
}
.payment-code table {
width: 100%;
border-collapse: collapse;
}
.payment-code th {
text-align: left;
padding: 10px;
font-weight: bold;
width: 40%;
}
.payment-code td {
padding: 10px;
font-size: 18px;
font-family: monospace;
}
</style>
Handle Webhook Confirmationโ
app.post('/webhooks/omise', async (req, res) => {
const event = req.body;
if (event.key === 'charge.complete') {
const charge = event.data;
if (charge.source.type === 'pay_easy') {
if (charge.status === 'successful') {
// Customer paid - now ship order
await shipOrder(charge.metadata.order_id);
await sendConfirmation(charge.metadata.customer_email);
} else if (charge.status === 'expired') {
// Payment expired - cancel order
await cancelOrder(charge.metadata.order_id);
}
}
}
res.sendStatus(200);
});
Complete Implementationโ
const express = require('express');
const omise = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY
});
const app = express();
app.use(express.json());
// Create Pay-easy payment
app.post('/checkout/pay-easy', async (req, res) => {
try {
const { amount, order_id, customer_email } = req.body;
// Validate amount (ยฅ200 - ยฅ49,999)
if (amount < 200 || amount > 49999) {
return res.status(400).json({
error: 'Amount must be between ยฅ200 and ยฅ49,999'
});
}
// Create source
const source = await omise.sources.create({
type: 'pay_easy',
amount: amount,
currency: 'JPY'
});
// Create charge
const charge = await omise.charges.create({
amount: amount,
currency: 'JPY',
source: source.id,
metadata: {
order_id: order_id,
customer_email: customer_email
}
});
// Send payment instructions email
await sendPayEasyInstructions(customer_email, {
payment_code: source.references.payment_code,
amount: amount,
expires_at: source.references.expires_at
});
// Return payment details
res.json({
payment_code: source.references.payment_code,
expires_at: source.references.expires_at,
charge_id: charge.id
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000);
Important: No Refund Supportโ
Pay-easy payments cannot be refunded via the Omise API. If you need to refund a customer, you must process it manually via bank transfer.
Alternative: Use Online Banking which supports refunds.
Payment Expirationโ
Pay-easy payments typically expire after 3-7 days:
// Check if payment expired
if (charge.status === 'expired') {
await cancelOrder(order_id);
await sendExpirationNotice(customer_email);
}
// Set reminder before expiration
const expiryDate = new Date(source.references.expires_at);
const reminderDate = new Date(expiryDate.getTime() - 24 * 60 * 60 * 1000);
scheduleEmail(reminderDate, customer_email, {
subject: 'ใๆฏๆใๆ้ใฎใ็ฅใใ',
body: 'ๆๆฅใใๆฏๆใๆ้ใงใใใๅฟใใชใใๆฏๆใใใ ใใใ'
});
Best Practicesโ
1. Clear Payment Instructionsโ
Provide detailed, localized instructions in Japanese:
const instructions = {
atm: [
'ใ่ฟใใฎ้่กATMใธใ่ถใใใ ใใ',
'ใ็จ้ใปๆ้ๆ่พผใใพใใฏใใใคใธใผใใ้ธๆ',
'ๅ็ดๆฉ้ข็ชๅทใใๅฎขๆง็ชๅทใ็ขบ่ช็ชๅทใๅ
ฅๅ',
'ๅ
ๅฎนใ็ขบ่ชใใฆๆฏๆใ',
'ใฌใทใผใใๅใๅใฃใฆใใ ใใ'
],
online: [
'ใๅฉ็จใฎ้่กใฎใใใใใณใญใณใฐใซใญใฐใคใณ',
'ใ็จ้ใปๆ้ๆ่พผใใพใใฏใใใคใธใผใใ้ธๆ',
'็ชๅทใๅ
ฅๅใใฆๆฏๆใ'
]
};
2. Email Confirmationโ
Send immediate email with payment details:
await sendEmail(customer.email, {
subject: 'ใๆณจๆ็ขบ่ช - Pay-easyใงใฎใๆฏๆใ',
body: `
ใๆณจๆใใใใจใใใใใพใใ
ใๆฏๆใๆนๆณ: Pay-easy
ๅ็ดๆฉ้ข็ชๅท: ${billing_code}
ใๅฎขๆง็ชๅท: ${customer_number}
็ขบ่ช็ชๅท: ${confirmation_number}
ใๆฏๆใ้้ก: ยฅ${amount}
ใๆฏๆใๆ้: ${expiry_date}
่ฉณใใใๆฏๆใๆนๆณใฏใใกใ: ${instructions_url}
`
});
3. Payment Remindersโ
Send reminders before expiration:
// 2 days before expiration
scheduleReminder(expiryDate - 2days, {
message: 'ใๆฏๆใๆ้ใ่ฟใฅใใฆใใพใใใๅฟใใชใใๆฏๆใใใ ใใใ'
});
// 1 day before expiration
scheduleReminder(expiryDate - 1day, {
message: 'ๆๆฅใใๆฏๆใๆ้ใงใใ'
});
4. Show Supported Banksโ
<div class="supported-banks">
<h4>ใๅฉ็จๅฏ่ฝใช้่ๆฉ้ข</h4>
<div class="bank-logos">
<img src="/banks/mizuho.svg" alt="ใฟใใป้่ก">
<img src="/banks/mufg.svg" alt="ไธ่ฑUFJ้่ก">
<img src="/banks/smbc.svg" alt="ไธไบไฝๅ้่ก">
<img src="/banks/japan-post.svg" alt="ใใใกใ้่ก">
</div>
<p><small>ใใฎไป1,000ไปฅไธใฎ้่ๆฉ้ข</small></p>
</div>
Testingโ
Test Amount: ยฅ100,000 (10000000 smallest unit) Expected: Payment code generation in test mode
FAQโ
What is Pay-easy?
Pay-easy (ใใคใธใผ) is Japan's standardized multi-bank payment service allowing customers to pay through ATMs or online banking at any participating bank. It's widely used for bills, taxes, and online shopping.
How long do customers have to pay?
Typically 3-7 days from order creation. The exact expiration is set when creating the source and should be clearly communicated to customers.
Can I refund Pay-easy payments?
No, Pay-easy payments cannot be refunded via the Omise API. You must handle refunds manually via bank transfer if needed.
Is Pay-easy better than Konbini?
Pay-easy:
- Bank customers
- Limit: ยฅ200 - ยฅ49,999
- ATM or online
- No refunds
Konbini:
- Universal (anyone with cash)
- Limit: ยฅ200 - ยฅ49,999
- In-store only
- No refunds
Choose based on your target audience.
Do I need Japanese language support?
Yes, absolutely essential. Pay-easy customers are Japanese and expect instructions in Japanese.
Related Resourcesโ
- Japan Payments Overview - All Japan methods
- Konbini - Convenience store alternative
- Online Banking - With refund support
- Testing - Test your integration
Next Stepsโ
- Create Pay-easy source
- Display payment code to customer
- Send email with payment instructions
- Set up webhook handler
- Handle payment expiration
- Test with Japanese customers
- Go live