Open10
PayPay 決済を Next.js で実験
Web決済に二種類ある
- スマートペイメント
- ウェブペイメント
必要なクレデンシャル
.env.local
PAYPAY_API_KEY=XXXXX
PAYPAY_SECRET=XXXXX
PAYPAY_MERCHANT_ID=1234567890
まずは PayPay で支払う画面の URL を生成する必要がある。
src/app/api/paypay/route.ts
import { Configure, QRCodeCreate } from '@paypayopa/paypayopa-sdk-node';
import { NextResponse } from 'next/server';
import { v4 as uuidv4 } from 'uuid';
import { z } from 'zod';
Configure({
clientId: process.env.PAYPAY_API_KEY || '',
clientSecret: process.env.PAYPAY_SECRET || '',
merchantId: process.env.PAYPAY_MERCHANT_ID || '',
productionMode: false,
})
const PayPaySuccessResponse = z.object({
STATUS: z.literal(201),
BODY: z.object({
data: z.object({
url: z.string(),
}),
}),
})
export async function POST() {
const merchantPaymentId = uuidv4();
const payload = {
merchantPaymentId,
amount: {
amount: 300,
currency: "JPY",
},
codeType: 'ORDER_QR',
orderDescription: 'Test Order',
isAuthorization: false,
redirectUrl: `http://localhost:3000/payment/paypay/${merchantPaymentId}`,
redirectType: 'WEB_LINK',
}
const res = await QRCodeCreate(payload)
if (res.STATUS === 201) {
const url = PayPaySuccessResponse.parse(res).BODY.data.url
return NextResponse.json({
url,
})
} else {
return NextResponse.error()
}
}
src/app/page.tsx
"use client";
import styles from "./page.module.css";
export default function Home() {
const handlePayPayPayment = async () => {
const res = await fetch("/api/paypay", {
method: "POST",
})
const json = await res.json()
window.location.href = json.url
}
return (
<div className={styles.page}>
<main className={styles.main}>
<h1>
PayPay 決済テスト
</h1>
<button onClick={handlePayPayPayment}>
支払う
</button>
</main>
</div>
);
}
支払うための QR コードが表示されたページに遷移する
スマホの PayPay を開発モードにして、テストアカウントでログインして支払う。
支払いが完了すると、redirectUrl
に設定した URL に遷移する。
開発モード:
ちなみに、制限時間以内に支払いがなされなかった場合も redirectUrl
に遷移する。
逆に、プラットフォームで上げた売上をユーザーに送りたい場合はどうしたらいいのか。
送金は、ユーザーの PayPay ID or 電話番号がわかれば可能。
ユーザーの PayPay ID はどうやって認証すればいいのか?
この辺を使うのかなあ
アカウントリンクの例。redirectUrl
はダッシュボードで設定したドメインである必要がある。
import { AccountLinkQRCodeCreate, Configure } from '@paypayopa/paypayopa-sdk-node';
import { NextResponse } from 'next/server';
import { v4 as uuidv4 } from 'uuid';
Configure({
clientId: process.env.PAYPAY_API_KEY || '',
clientSecret: process.env.PAYPAY_SECRET || '',
merchantId: process.env.PAYPAY_MERCHANT_ID || '',
productionMode: false,
})
export async function POST() {
const nonce = uuidv4();
const payload = {
redirectUrl: 'http://localhost:3000',
redirectType: 'WEB_LINK',
scopes: [
"direct_debit"
],
nonce,
}
const res = await AccountLinkQRCodeCreate(payload)
return NextResponse.json(res)
}
返却される URL にアクセスして PayPay ログインすると、redirectUrl
に飛ばされる。この際、responseToken
クエリパラメータにある JWT にアカウント情報が含まれて帰ってくる。
{
STATUS: 201,
BODY: {
resultInfo: { code: 'SUCCESS', message: 'Success', codeId: '08100001' },
data: {
linkQRCodeURL: 'https://stg-www.sandbox.paypay.ne.jp/app/opa/web/link?code=https%3A%2F%2Fqr-stg.sandbox.paypay.ne.jp%2F281801074UK0O9zI3ecYainF'
}
}
}
JWT のペイロード。userAuthorizationId
を使うとユーザーに送金可能っぽい。
{
"result": "succeeded",
"aud": "XXXXXXXX",
"iss": "paypay.ne.jp",
"profileIdentifier": "*******0164",
"exp": 1730340440,
"nonce": "d84f3aa9-205b-4607-9b9f-603db20b67db",
"userAuthorizationId": "87f534c2-bbdf-4da1-8300-19e418950642",
"referenceId": null
}