ユーザーアカウントリンク (1.0)

はじめに

このAPIを用いることで、PayPayのユーザー認可をQRコードを用いてシームレスに取得する事が可能です。

詳細なフローはここからダウンロードできます。

ユーザー認可フローのダウンロード

TLSの実装

PayPay Open Payment APIでは、セキュリティ対策としてTLS 1.2以上の使用が必須となっております。TLS1.0およびTLS1.1では接続できませんのでご注意ください。

加盟店を登録する

PayPay OPAの利用を開始するには、事前に定められたプロセスに従ってPayPay加盟店の登録を行なってください。 このプロセスは 情報収集、手動検証、契約確認、およびクレデンシャル情報の発行から構成されます。

PayPayの加盟店として登録された後、以下の項目が設定されます。

  • api key と apiKeySecret
  • webhookの通知先となるエンドポイント
  • クライアントIPのホワイトリスト

これらの設定を管理するには、マーチャントパネルを使用するか、弊社営業担当までご連絡ください。

ユーザーからの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を再度取得する必要があります。 ユーザ環境によって、リダイレクトが複数回発生する可能性があります。 こちらをご確認の上、適切な処理をお願いします。

App Invoke flow

シーケンス図

Merchant desktop site with PayPay scan

シーケンス図

Merchant desktop site with PayPay web login

シーケンス図

ユーザー認可の結果を受け取る

PayPayの認可ページで、ユーザーは加盟店の認可取得を承認または拒否する選択ができます。 そのユーザーの操作に応じて、認可の取得は成功または失敗する可能性があります。

アカウントリンクの状態を取得する3つの方法

アカウントリンクの結果を受け取るには、次の3つの方法があります。

  • リダイレクトURLに付加されたペイロード
  • webhook通知のペイロード
  • 「アカウントリンクQRコードのステータス取得」APIからのポーリング

最初の 2つは推奨される実装方法で、最後の 1つは任意です。 最初の 2つのオプションはリアクティブであるため、情報をただちに更新する可能性が高いです。 リダイレクトと Webhook がどちらも失敗した場合、ステータスを取得するフォールバック手段としてポーリングが提供されます。

3つの方法がすべて失敗した場合は、アカウントリンクのセッションが失敗し、回復できないことを意味します。 マーチャントの側で新しい試行を開始し、アカウントリンクが失敗したことをユーザーに通知する必要があります。

1. リダイレクトURLに付加されたペイロード

結果を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 マスクされた電話番号またはメール(例:*******5678abc*******@example.com
nonce string レスポンスを検証するために、APIリクエストパラメータのnonceが設定される。
userAuthorizationId string データベースに保持し、APIの呼び出しの際に使用するPayPayユーザー参照ID。最大長64文字。
referenceId string リクエスト内で同一の参照ID。

ユーザーがアカウントリンクを拒否した場合、profileIdentifieruserAuthorizationId はレスポンスのJWTには含まれないことに注意してください。

ユーザーが認可要求を承認または却下した後は、WebViewを以下のURLにリダイレクトします。

  https://<redirect url>?apiKey={apiKey}&responseToken={jwtToken}

認証画面の有効期限が切れた場合、以下のURLにリダイレクトします。

  https://<redirect url>

2. webhook通知のペイロード

Webhook section参照。

3. 「アカウントリンクQRコードのステータス取得」APIからのポーリング

Fetch Status of Account Link QR Code参照。

API認証

本ドキュメントに記載されているAPIは、HMAC方式での認証が必要です。 HMAC方式での認証の実装においては、認証オブジェクト生成に対してすべてのリクエストを考慮します。

認証オブジェクトに必要なパラメータ

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==

HMAC authヘッダーの生成ステップ

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 このコードは問題が発生したことを意味しますが、
トランザクションが発生したかどうか正確には
わかりません。
不明な支払いステータスとして処理する必要が
あります。

アカウントリンクQRコードの作成

status code message
201 SUCCESS 作成成功
400 EXPECTATION_FAILED 渡されたscopes、
またはコールバックURLが無効な場合。

アカウントリンクQRコードのステータス取得

Status Code Message
200 SUCCESS 成功
404 SESSION_NOT_FOUND 間違った URL を指定した場合、またはセッションが既に期限切れになっている場合、要求されたリソースは見つかりません。

タイムアウト

推奨タイムアウト値は各APIで指定されています。 APIのタイムアウト値は30秒以下であってはいけません。 タイムアウトが発生した場合、それは状態が不明なステータスとして扱ってください。

ユーザー

アカウントリンクQRコードの作成

アカウントリンクQRを作成し、ユーザーに表示します。

Timeout: 10s

Request Body schema: application/json

アカウントリンクQRを作成

scopes
required
Array of strings

ユーザー認可のスコープです。必要なスコープのみを指定してください。
SCOPEは、利用するAPIのAPIドキュメントの「ユーザー認可を取得する」に記載されているSCOPEを指定してください。
指定するSCOPEを判断できない場合は、弊社にお問い合わせしてください。

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情報。

Responses

Request samples

Content type
application/json
{
  • "scopes": [
    ],
  • "nonce": "string",
  • "redirectType": "APP_DEEP_LINK",
  • "redirectUrl": "string",
  • "referenceId": "string",
  • "phoneNumber": "string",
  • "deviceId": "string",
  • "userAgent": "string",
  • "kycData": {
    }
}

Response samples

Content type
application/json
{
  • "resultInfo": {
    },
  • "data": {
    }
}

アカウントリンクQRコードのステータス取得

アカウントリンクQRコードのステータスを取得します。 このエンドポイントはポーリングに使用することを目的としており、間隔は 2–3 秒にする必要があります。 ポーリングを開始する前に、ユーザーが連携プロセスを完了するまで30秒程度待ちます。

ポーリング自体はオプションの手段であり、必須ではありません。 詳細については、以下の「アカウントリンクの状態を取得する 3つの方法」セクションを参照してください。

タイムアウト: 10秒

query Parameters
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

/v1/qr/sessions によって作成された linkQRCodeURL から取得された URL。これは URL エンコードされている必要があります。

Responses

Response samples

Content type
application/json
{
  • "resultInfo": {
    },
  • "data": {
    }
}

Webhookの設定

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種別では必須 マスクされた電話番号またはメール(例:*******5678abc*******@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種別では必須 実行結果に対する原因

通知の種別ごとの例は以下の通りです。

customer.authroization.succeeded

この通知は、クライアントがユーザーの認可を正常に取得した場合に送信されます。

{
  "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
}

customer.authroization.failed

この通知は、クライアントがユーザーの認可の取得に失敗した場合に送信されます。

{
  "notification_type": "customer.authroization.failed",
  "notification_id": "evt_aXnbdeFt2Ke",
  "createdAt": "1349654313",
  "referenceId": "yyyy",
  "nonce": "12345",
  "result": "declined",
  "reason": "invalid scope"
}

result(結果)はdeclinedkyc_not_completedkyc_data_mismatch のいずれかになります。

  • declined : リクエストがユーザーによって拒否された場合
  • kyc_not_completed ユーザーがKYC (本人確認) を完了していない場合
  • kyc_data_mismatch ユーザーのKYCデータが一致しない場合

customer.authroization.revoked

この通知は、ユーザーがPayPayアプリから、認可を取り消した場合に送信されます。

{
  "notification_type": "customer.authroization.revoked",
  "notification_id": "evt_aXnbdeFt2Ke",
  "createdAt": "1349654313",
  "userAuthorizationId": "xxxxx",
  "referenceId": "yyyy"
}

customer.authroization.extended

この通知は、ユーザー認可の期限が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
}

customer.authroization.canceled

この通知は、ユーザーが退会した時に送信されます。

サンプル・イベント:

{
  "notification_type": "customer.authroization.canceled",
  "notification_id": "evt_aXnbdeFt2Ke",
  "createdAt": "1349654313",
  "userAuthorizationId": "xxxxx"
}

FAQ

最新の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の説明を変更しました。