Skip to main content

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.

RegionCurrencyMin AmountMax AmountSettlement
JapanJPYยฅ1ยฅ999,9991-3 days

How It Worksโ€‹

Customer Experience:

Option 1: ATM Payment

  1. Customer receives Pay-easy code
  2. Goes to any bank ATM
  3. Selects "Pay-easy" (ใƒšใ‚คใ‚ธใƒผ)
  4. EntersๅŽ็ดๆฉŸ้–ข็•ชๅท (billing organization code)
  5. Enters customer number and confirmation number
  6. Inserts cash or uses bank card
  7. Receives receipt

Option 2: Online Banking

  1. Customer logs into internet banking
  2. Selects "Pay-easy" payment
  3. Enters payment code information
  4. Confirms payment
  5. Receives confirmation

Typical completion time: 1-24 hours (depends on customer action)

Implementationโ€‹

Create Pay-easy Sourceโ€‹

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

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
if (amount < 1 || amount > 99999900) {
return res.status(400).json({
error: 'Amount must be between ยฅ1 and ยฅ999,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โ€‹

No Refunds

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
  • Higher limit (ยฅ999,999)
  • ATM or online
  • No refunds

Konbini:

  • Universal (anyone with cash)
  • Lower limit (ยฅ300,000)
  • 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.

Next Stepsโ€‹

  1. Create Pay-easy source
  2. Display payment code to customer
  3. Send email with payment instructions
  4. Set up webhook handler
  5. Handle payment expiration
  6. Test with Japanese customers
  7. Go live