PayPay Open Payment APIでは、セキュリティ対策としてTLS 1.2以上の使用が必須となっております。TLS1.0およびTLS1.1では接続できませんのでご注意ください。
PayPay OPAの利用を開始するには、事前に定められたプロセスに従ってPayPay加盟店の登録を行なってください。 このプロセスは 情報収集、手動検証、契約確認、およびクレデンシャル情報の発行から構成されます。
PayPayの加盟店として登録された後、以下の項目が設定されます。
これらの設定を管理するには、マーチャントパネルを使用するか、弊社営業担当までご連絡ください。
ユーザーからのPayPayアプリ、PayPayWeb画面への日本国外からのアクセスは制限されています。詳細については個別にご相談ください。
PayPayユーザーのウォレットから決済を回収できるようにするには、ユーザーの認可を明示的に取得する必要があります。
加盟店は、ユーザー認証を取得するたびに、「アカウントリンクQRコードの作成」APIにリクエストを行い、ユーザーが同意するPayPay許可画面のURLを生成する必要があります。
特別なケースとして、お客様が認証プロセスにおいてKYCの設定を義務付けることを選択した場合、ユーザーは認証画面においてKYCデータの照合など、いくつかの追加ステップを経る必要があります。KYCデータの照合に失敗した場合、ユーザーはPayPayでKYCを完了するか、加盟店のページに戻るかの選択肢が表示されます。
認可が成功すると、ユーザー認可IDがユーザーごとに発行されます。 このIDをバックエンドに保存し、それを内部ユーザーに関連付ける必要があります。 このユーザー認可IDはクライアント側に保存しないようにしてください。 このIDはOPAへのリクエストで使用され、決済、キャッシュバック及びTopUpのリクエストでユーザーを識別します。
すべてのユーザー認可には有効期間が設けられています。決済、残高付与や再認可を行う度に自動で延長されます。
これは、オンボーディングプロセス中に定義されたユーザー認可有効期間です。
ユーザー認可IDの有効期限は、カスタマーイベントwebhookのexpiry
、又は、Get user authorization statusのレスポンスデータのexpireAt
で確認ができます。
また、PayPayユーザーは、加盟店に通知することなく、PayPayサービスから認可を取り消すこともできます。
どちらの場合も、ユーザー認可IDを再度取得する必要があります。
ユーザ環境によって、リダイレクトが複数回発生する可能性があります。
こちらをご確認の上、適切な処理をお願いします。
PayPayの認可ページで、ユーザーは加盟店の認可取得を承認または拒否する選択ができます。 そのユーザーの操作に応じて、認可の取得は成功または失敗する可能性があります。
アカウントリンクの結果を受け取るには、次の3つの方法があります。
最初の 2つは推奨される実装方法で、最後の 1つは任意です。 最初の 2つのオプションはリアクティブであるため、情報をただちに更新する可能性が高いです。 リダイレクトと Webhook がどちらも失敗した場合、ステータスを取得するフォールバック手段としてポーリングが提供されます。
3つの方法がすべて失敗した場合は、アカウントリンクのセッションが失敗し、回復できないことを意味します。 マーチャントの側で新しい試行を開始し、アカウントリンクが失敗したことをユーザーに通知する必要があります。
結果をJWTトークンにエンコードして、それをCreate Account Link QR Code API(/v1/qr/sessions) に指定されているリダイレクトURLに渡します。
リダイレクトURLに渡す特定のパラメータは以下のとおりです。
apiKey
は、登録プロセス中に発行されたapi keyです。responseToken
は、apiKeyに対応するapiKeySecretのBase64デコード値で署名されたJWTトークンです。 {
"typ": "JWT",
"alg": "HS256",
}
.
{
"aud" : "<merchant organization id>",
"iss" : "paypay.ne.jp",
"exp" : 1638198000,
"result": "succeeded",
"profileIdentifier": "*******5678",
"nonce" : "<the same nonce in the request>",
"userAuthorizationId" : "<PayPay user reference id>",
"referenceId": "<merchant user reference id>"
}
.
signature
claim | 種類 | 説明 |
---|---|---|
iss | string | 発行者はPayPayであり、"paypay.ne.jp"が設定される。 |
aud | string | 想定利用者は加盟店であり、加盟店のクライアントIDが設定される。 |
exp | number | responseTokenの有効期限。エポックタイムスタンプ(秒単位)で設定。 |
result | string | succeeded , declined |
profileIdentifier | string | マスクされた電話番号またはメール(例:*******5678 、abc*******@example.com ) |
nonce | string | レスポンスを検証するために、APIリクエストパラメータのnonceが設定される。 |
userAuthorizationId | string | データベースに保持し、APIの呼び出しの際に使用するPayPayユーザー参照ID。最大長64文字。 |
referenceId | string | リクエスト内で同一の参照ID。 |
ユーザーがアカウントリンクを拒否した場合、profileIdentifier
と userAuthorizationId
はレスポンスのJWTには含まれないことに注意してください。
ユーザーが認可要求を承認または却下した後は、WebViewを以下のURLにリダイレクトします。
https://<redirect url>?apiKey={apiKey}&responseToken={jwtToken}
認証画面の有効期限が切れた場合、以下のURLにリダイレクトします。
https://<redirect url>
Value | Description | Example |
---|---|---|
API Key | PayPayから発行されたAPI Key | APIKeyGenerated |
API Key secret | PayPayから発行されたAPI Key secret | APIKeySecretGenerated |
Request URI | リクエストURL path | /v2/codes |
Request method | HTTPメソッド | POST |
Epoch | 現在のエポックタイムスタンプ(秒単位), Note : サーバー時刻との差が2分未満である必要があります。 | 1579843452 |
Nonce | ランダムに生成された文字列。Note : 任意の文字列、length 8を推奨。 | acd028 |
Request body | リクエストで渡されるbody。 | {"sampleRequestBodyKey1":"sampleRequestBodyValue1","sampleRequestBodyKey2":"sampleRequestBodyValue2"} |
Request content type | リクエストヘッダーで渡されるコンテンツタイプ。 | application/json;charset=UTF-8; |
hash (MD5(Request body, Request content type)) | リクエストの本文とコンテンツタイプのハッシュ。以下に記載されているStep1で生成されます。 | 1j0FnY4flNp5CtIKa7x9MQ== |
これらから生成されるサンプルHMAC Authヘッダーは以下の通りです。
hmac OPA-Auth:APIKeyGenerated:NW1jKIMnzR7tEhMWtcJcaef+nFVBt7jjAGcVuxHhchc=:acd028:1579843452:1j0FnY4flNp5CtIKa7x9MQ==
Step 1: MD5アルゴリズムを使用してbodyとcontent-typeをハッシュ化する
サンプルコード
private String requestBody;
private String contentType;
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(contentType.getBytes(StandardCharsets.UTF_8));
md.update(requestBody.getBytes(StandardCharsets.UTF_8));
String hash = new String(
Base64.getEncoder().encode(md.digest()),
StandardCharsets.UTF_8);
Note : HTTP GETメソッドの場合など、リクエストの本文がない場合、MD5を生成する必要はありません。代わりに、hashには"empty"がセットされます。
Step 2: HMAC-SHA256でハッシュ化される文字列を生成します。
リクエストの署名には、以下のパラメータが必要です。
private String requestUrl; //Only the request URI Example: "/v2/codes/payments/dynamic-qr-test-00002"
private String httpMethod;
private String nonce; //Random string
private String epoch;
private String contentType;
private String hash; //Output of step 1
private static final String DELIMITER = "\n";
byte[] hmacData = new StringBuilder()
.append(requestUrl)
.append(DELIMITER)
.append(httpMethod)
.append(DELIMITER)
.append(nonce)
.append(DELIMITER)
.append(epoch)
.append(DELIMITER)
.append(contentType)
.append(DELIMITER)
.append(hash != null ? hash : "")
.toString()
.getBytes(StandardCharsets.UTF_8);
Note : HTTP GETメソッドの場合など、リクエストの本文がない場合、content-typeおよびhashには"empty"がセットされます。
Step 3 : Step2で生成された値と、Key secretを使用してHMACオブジェクトを生成します。
public final String toBase64HmacString() {
private String apiKeySecret;
private byte[] dataToSign; //Output from step 2
try {
SecretKeySpec signingKey = new SecretKeySpec(apiKeySecret.getBytes(StandardCharsets.UTF_8),
"HmacSHA256");
Mac sha256HMAC = Mac.getInstance("HmacSHA256");
sha256HMAC.init(signingKey);
byte[] rawHmac = sha256HMAC.doFinal(dataToSign);
return java.util.Base64.getEncoder().encodeToString(rawHmac);
} catch (GeneralSecurityException e) {
LOGGER.error("Unexpected error while creating hash: " + e.getMessage());
throw new IllegalArgumentException(e);
}
}
Step 4 : ヘッダーオブジェクトを生成します。
String authHeader = "hmac OPA-Auth:" + api-key +
":" + macData + ":" + nonce + ":" + epoch + ":" + hash;
Note: macDataはStep3で生成された値を使用してください。また、nonceとepochは、Step2で使用した値を渡す必要があります。
HTTP GETメソッドの場合などリクエストの本文がない場合、hash値は"empty"となるため、ヘッダーオブジェクトは下記の通りとなります。
String authHeader = "hmac OPA-Auth:" + api-key +
":" + macData + ":" + nonce + ":" + epoch + ":empty";
authHeaderの値を、HttpHeader.AUTHORIZATIONにセットして渡してください。 PayPay側で渡ってきたデータをデコードし、SHA256( "key"、requestParams)を再作成します。 再作成したmacDataとヘッダーで渡ってきた値が一致しているかを検証します。
PayPay OPAはhttpレスポンスステータスコードとOPAエラーコードを使用してリクエストの成功または失敗を示します。 これらの情報を使用して、どのようなエラー対応をするかを判断できます。 PayPay OPAは以下のhttpレスポンスステータスコードを返します。
status | code | message |
---|---|---|
400 | INVALID_REQUEST_PARAMS | リクエストによって提供された情報に 無効なデータが含まれています。 例: サポートされていない通貨 |
401 | UNAUTHORIZED | 有効なapi keyとsecretが提供されていません。 |
429 | RATE_LIMIT | リクエスト制限数超過。 |
500 | INTERNAL_SERVER_ERROR | このコードは問題が発生したことを意味しますが、 トランザクションが発生したかどうか正確には わかりません。 不明な支払いステータスとして処理する必要が あります。 |
status | code | message |
---|---|---|
201 | SUCCESS | 作成成功 |
400 | EXPECTATION_FAILED | 渡されたscopes、 またはコールバックURLが無効な場合。 |
Status | Code | Message |
---|---|---|
200 | SUCCESS | 成功 |
404 | SESSION_NOT_FOUND | 間違った URL を指定した場合、またはセッションが既に期限切れになっている場合、要求されたリソースは見つかりません。 |
アカウントリンクQRを作成し、ユーザーに表示します。
Timeout: 10s
アカウントリンクQRを作成
scopes required | Array of strings ユーザー認可のスコープです。必要なスコープのみを指定してください。 |
nonce required | string <= 255 characters ランダムに生成された文字列。 |
redirectType | string Default: "WEB_LINK" Enum: "APP_DEEP_LINK" "WEB_LINK" 加盟店アプリまたはウェブページにリダイレクトするかどうかを決定するパラメーター。 |
redirectUrl required | string <= 255 characters クライアントから提供されたコールバックエンドポイント。WEB_LINKの場合はHTTPSである必要があり、またドメインは事前に許可されたコールバックドメイン内になければなりません。 |
referenceId | string <= 255 characters 加盟店システムでユーザーを識別するためのID。 再照合の目的でPayPayデータベースに格納されます。 |
phoneNumber | string ユーザーの電話番号。ブラウザにてログイン画面を開いた場合、電話番号の初期値として設定されます。 |
deviceId | string <= 255 characters このパラメータは廃止となりました。 |
userAgent | string <= 255 characters Webブラウザのユーザーエージェント。 redirectTypeが「WEB_LINK」の場合、ユーザー認可取得後に起動するWEBブラウザを指定する事が可能です。 |
object (KYCData) アカウントリンク時に確認するKYC情報。 |
{- "scopes": [
- "direct_debit",
- "get_balance"
], - "nonce": "string",
- "redirectType": "APP_DEEP_LINK",
- "redirectUrl": "string",
- "referenceId": "string",
- "phoneNumber": "string",
- "deviceId": "string",
- "userAgent": "string",
- "kycData": {
- "firstNameKana": "string",
- "lastNameKana": "string",
- "dateOfBirth": "string"
}
}
{- "resultInfo": {
- "code": "string",
- "message": "string",
- "codeId": "string"
}, - "data": {
- "linkQRCodeURL": "string"
}
}
アカウントリンクQRコードのステータスを取得します。 このエンドポイントはポーリングに使用することを目的としており、間隔は 2–3 秒にする必要があります。 ポーリングを開始する前に、ユーザーが連携プロセスを完了するまで30秒程度待ちます。
ポーリング自体はオプションの手段であり、必須ではありません。 詳細については、以下の「アカウントリンクの状態を取得する 3つの方法」セクションを参照してください。
タイムアウト: 10秒
linkQRCodeURL required | string <urlencoded> Example: linkQRCodeURL=https://www.paypay-corp.co.jp/app/opa/web/link?code=https%3A%2F%2Fqr-stg.paypay-corp.co.jp%2F2818010757vFsOLzaglGjvtE
|
{- "resultInfo": {
- "code": "string",
- "message": "string",
- "codeId": "string"
}, - "data": {
- "status": "ACCEPTED",
- "referenceId": "string",
- "nonce": "string",
- "scopes": [
- "string"
], - "userAuthorizationId": "string",
- "profileIdentifier": "string",
- "expiry": 0
}
}
PayPayは、アカウントでイベントが発生したときにアプリケーションに通知するWebhookを送信します。
通知を受信するためには、POSTメソッドを使用してクライアントにデータを送信するWebhook URLを設定する必要があります。
すべての通知データには、どのイベントが発生したかを判断するためにクライアントサービスで使用できるnotification_type
フィールドがあります。
Webhook処理が正常に終了した場合、200 OK
のHTTPステータスコードを返してください。
レスポンスボディは必須ではないですが、"OK"など、簡単な文字列を返していただくことを推奨します。
セキュリティ上の問題から、通知受信において、クライアントによるPayPay IPアドレスのホワイトリスト登録を強く推奨します。
現在Webhookに送信されている通知について、以下もご一読ください。
ユーザー状態の変化に関連するイベントです。 authroization
の部分は文字通りです。
項目 | 型 | 必ず含まれているか | 説明 |
---|---|---|---|
notification_type | string | yes | 通知の種別。取りうる値は次の通り: customer.authroization.succeeded , customer.authroization.failed , customer.authroization.revoked , customer.authroization.extended , customer.authroization.canceled |
notification_id | string | yes | 通知ID |
createdAt | number | yes | 通知が作成された時刻。エポックタイムスタンプ(秒単位) |
referenceId | string | no | 加盟店システムでユーザーを識別するためのID |
nonce | string | customer.authroization.succeeded , customer.authroization.failed 種別では必須 |
レスポンスを検証するために必要なクライアント側のリクエスト内の同一のnonce |
scopes | string | customer.authroization.succeeded , customer.authroization.extended 種別では必須 |
ユーザー認可のスコープ |
userAuthorizationId | string | customer.authroization.succeeded , customer.authroization.revoked , customer.authroization.canceled , customer.authroization.extended 種別では必須 |
APIの呼び出しの際に使用するPayPayユーザー参照ID。最大長64文字 |
profileIdentifier | string | customer.authroization.succeeded 種別では必須 |
マスクされた電話番号またはメール(例:*******5678 、abc*******@example.com ) |
expiry | number | customer.authroization.extended , customer.authroization.succeeded 種別では必須 |
userAuthorizationIdの有効期限。エポックタイムスタンプ(秒単位) |
result | string | customer.authroization.failed 種別では必須 |
実行結果。取りうる値は次の通り: declined , kyc_not_completed , kyc_data_mismatch |
reason | string | customer.authroization.failed 種別では必須 |
実行結果に対する原因 |
通知の種別ごとの例は以下の通りです。
この通知は、クライアントがユーザーの認可を正常に取得した場合に送信されます。
{
"notification_type": "customer.authroization.succeeded",
"notification_id": "evt_aXnbdeFt2Ke",
"createdAt": "1349654313",
"referenceId": "yyyy",
"nonce": "12345",
"scopes": "direct_debit",
"userAuthorizationId": "xxxxx",
"profileIdentifier": "*******5678",
"expiry": 1669734000 // the authorization id expiration epoch timestamp in seconds
}
この通知は、クライアントがユーザーの認可の取得に失敗した場合に送信されます。
{
"notification_type": "customer.authroization.failed",
"notification_id": "evt_aXnbdeFt2Ke",
"createdAt": "1349654313",
"referenceId": "yyyy",
"nonce": "12345",
"result": "declined",
"reason": "invalid scope"
}
result
(結果)はdeclined
、kyc_not_completed
、kyc_data_mismatch
のいずれかになります。
declined
: リクエストがユーザーによって拒否された場合kyc_not_completed
ユーザーがKYC (本人確認) を完了していない場合kyc_data_mismatch
ユーザーのKYCデータが一致しない場合この通知は、ユーザーがPayPayアプリから、認可を取り消した場合に送信されます。
{
"notification_type": "customer.authroization.revoked",
"notification_id": "evt_aXnbdeFt2Ke",
"createdAt": "1349654313",
"userAuthorizationId": "xxxxx",
"referenceId": "yyyy"
}
この通知は、ユーザー認可の期限がPayPayによって延長された場合に送信されます。
支払いの実施/認可の取得をした場合にユーザー認可の期限を延長します。 これにより、ユーザー操作による認可の取得を減らすことで、ユーザーへの負担を減らせます。
{
"notification_type": "customer.authroization.extended",
"notification_id": "evt_aXnbdeFt2Ke",
"createdAt": "1349654313",
"scopes": "direcrt_debit",
"userAuthorizationId": "xxxxx",
"expiry": 1669734000 // the authorization id expiration epoch timestamp in seconds
}
この通知は、ユーザーが退会した時に送信されます。
サンプル・イベント:
{
"notification_type": "customer.authroization.canceled",
"notification_id": "evt_aXnbdeFt2Ke",
"createdAt": "1349654313",
"userAuthorizationId": "xxxxx"
}
最新のFAQについてはこちらをご参照ください。
ドキュメント更新日 | リリース日 | 種別 | セクション | 変更箇所 |
---|---|---|---|---|
2022.12.21 | Released | Feature | ユーザー認可の結果を受け取る | 認証画面の有効期限が切れた場合のリダイレクトを追加しました。 |
2023.01.19 | Released | Feature | アカウントリンクQRコードの作成 | deviceIdは廃止であることを追加しました。 |
2023.01.31 | Released | Feature | アカウントリンクQRコードの作成 | KYC情報の説明を追加しました。 |
2023.03.24 | Released | Documentation Fix | 認証オブジェクトに必要なパラメータ | Request URIの説明を修正しました。 |
2023.03.28 | Released | Feature | ユーザー認可の結果を受け取る | nonceの説明を変更しました。 JWTトークンの署名説明を変更しました。 リンク先を修正したました。 |
2023.03.28 | Released | Feature | アカウントリンクQRコードの作成 | scopesの説明を変更しました。 |
2023.03.28 | Released | Feature | レスポンスコード一覧 | EXPECTATION_FAILEDのmessageを変更しました。 |
2023.04.28 | 2023.05.25 | Feature | アカウントリンクQRコードの作成 | referenceIdを任意に変更しました。 |
2023.09.11 | Released | Feature | ユーザー認可の結果を受け取る | JWTトークンの署名説明を変更しました。 expの説明を変更しました。 |