継続課金

あなたのサブスクリプション製品またはサービスへの定期的な支払いをユーザーが許可することで、定期的な支払いを行うことができます。※法人のお客様のみご利用いただけます。

Integration

Overview

こちらはPayPay決済を導入する開発者向けドキュメントになります。こちらのPayment SDKを使うことで簡単に開発をできるように支援することを目的としています。こちらのPayment SDKを用いてビジネス要求を実現しつつPayPayのガイドラインに合わせた実装を行うことが可能になります。

継続課金を使用する場合

継続課金 は以下のような場合に採用することをお勧めしております

  • ビデオストリーミングサービス、ゲームサービスなどのサブスクリプション製品またはサービスを持っている
  • 短期間でサブスクリプションサービスの決済機能が必要である

支払いフローについて

次の図は、 継続課金 の統合フローを定義しています。

documentation-image

取引のステータスを確認するために、マーチャントは4〜5秒間隔でGet payment Details APIのポーリングを実装することをお勧めします。

でははじめていきましょう

実際の開発を開始する前に、
事前作業として以下の作業が完了しているか確認ください。

  • PayPay for developer でマーチャントアカウントを 登録する
  • developer dashboard より API key and secret を取得する
  • sandboxむけの API keySecret を使って開発する

継続課金を開発する

インストール

terminal Terminal
# If you love Python, you will love our pip installation package, 
  # simply run the following to ensure you have all the methods needed to make the integration
  $ pip install paypayopa
SDKsのリリースノートはこちらでご確認ください。

クライアントをビルドする

以下に定義するようにapikeyとsecretを追加してクライアントを構築します。 APIでは、認証方式としてHMAC採用していますが、SDKで認証を処理することが可能です。 認証について詳しく知りたい場合は こちら を参照ください 。 Production_modeは、サンドボックス/本番環境の宛先を設定します。デフォルトのfalse設定は、サンドボックス環境に接続します。 Ture設定は、本番環境に接続します。

terminal Terminal
import paypayopa
  ''' production_mode : Set the connection destination of the sandbox environment / production environment. 
 The default false setting connects to the sandbox environment. The True setting connects to the production environment. '''
  client = paypayopa.Client(auth=(API_KEY, API_SECRET), production_mode=False)
  client.set_assume_merchant("MERCHANT_ID")
SDKsのリリースノートはこちらでご確認ください。

ユーザー認可を取得する

ユーザー認可を取得するためにはJWT を作成して頂く必要がございます。

ClaimRequiredTypeDescription
scopesYesArray of stringItems Enum: 'direct_debit' 'cashback' 'get_balance' 'quick_pay' 'continuous_payments' 'merchant_topup' 'pending_payments' 'user_notification' 'user_topup' 'user_profile' 'preauth_capture_native' 'preauth_capture_transaction' 'push_notification' 'notification_center_ob' 'notification_center_ab' 'notification_center_tl' ユーザー認可のスコープ
nonceYesstringランダムに生成された文字列。
redirectTypeNostringDefault: 'WEB_LINK' Enum: 'APP_DEEP_LINK' 'WEB_LINK' 加盟店アプリまたはウェブページにリダイレクトするかどうかを決定するパラメーター。
redirectUrlYesstringクライアントから提供されたコールバックエンドポイント。WEB_LINKの場合はHTTPSである必要があり、またドメインは事前に許可されたコールバックドメイン内になければなりません。
referenceIdYesstringマーチャントシステムでユーザーを識別するためのID。 再照合の目的でPayPayデータベースに格納されます
phoneNumberNostringユーザーの電話番号
deviceIdNostringユーザーの携帯電話デバイスID。提供されている場合は、より快適なUXを提供するために、この携帯電話デバイスIDを使って、ユーザーの確認とSMSの確認を省略できます。
userAgentNostringWebブラウザのユーザーエージェント。 redirectTypeが「WEB_LINK」の場合、ユーザー認可取得後に起動するWEBブラウザを指定する事が可能です。

terminal Terminal
payload = {
  "scopes": [
    "continuous_payments"
  ],
  "nonce": "rtyuhghj7989",
  "redirectType": "WEB_LINK",
  "redirectUrl": "https://merchant.domain",
  "referenceId": "uioiugf789",
  "phoneNumber": "90999999999",
  "deviceId": "qwertyuiopoiuytre54567",
  "userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"
}
client.Account.create_qr_session(payload)
SDKsのリリースノートはこちらでご確認ください。

ユーザーが認証を付与すると、認可ページの戻りパラメーターもしくはWebhookにてJWTトークンの一部としてUserAuthorizationIDを返します

terminal Terminal
# Calling the method to get user authorization status
response = client.User.get_authorization_status("<userAuthorizationId>")
# Printing if the method call was SUCCESS
print(response['resultInfo']['code'])
SDKsのリリースノートはこちらでご確認ください。

ユーザーのリンクを解除する

クライアントからユーザーのリンクを解除するには, 以下のパラメーターを使用してリクエストしてください

FieldRequiredTypeDescription
userAuthorizationIdYesstring <= 64 characters ユーザー認可フローで返却されたPayPayユーザー認可ID

terminal Terminal
# Calling the method to unlink the user from the client
response = client.User.unlink_user_athorization("<userAuthorizationId>")
# Printing if the method call was SUCCESS
print(response['resultInfo']['code'])
SDKsのリリースノートはこちらでご確認ください。

Create a continuous payment

継続課金を実施する場合には、以下のパラメータを使用してリクエストしてください

FieldRequiredTypeDescription
merchantPaymentIdYesstring <= 64 characters加盟店から提供された一意の支払い取引ID
userAuthorizationIdYesstring <= 64 charactersユーザー認可フローで返却されたPayPayユーザー認可ID
amountYesinteger <= 11 characters支払金額
orderDescriptionNostring <= 255 characters 取引の説明

terminal Terminal
# Creating the payload for a payment authorization request, additional parameters can be added basis the API Documentation
request_payload = {
    "merchantPaymentId": "merchant_payment_id",
    "userAuthorizationId": "my_user_authorization_id",
    "orderDescription":"Mune's Favourite Cake",
    "amount": {
          "amount": 1,
          "currency": "JPY"
          }
    }

# Calling the method to create a continuous payment authorization
response = client.Payment.create_continuous_payment(request_payload)
# Printing if the method call was SUCCESS, this does not mean the payment was a success
print(response['resultInfo']['code'])
SDKsのリリースノートはこちらでご確認ください。

上記のコンソール出力でSUCCESSが出力され、ステータスが'AUTHORIZED'である場合、APIの実行は成功しています。
レスポンス項目について詳細に知りたい 場合には、 [APIドキュメントガイド]をご確認ください。

Get Payment Details

決済情報を参照をすることができます。以下のパラメーターを使用してリクエストしてください。

FieldRequiredTypeDescription
merchantPaymentIdYesstring <= 64 characters加盟店から提供された一意の支払い取引ID

terminal Terminal
# Calling the method to get payment details
response = client.Payment.get_payment_details("<merchantPaymentId>")
# Printing if the method call was SUCCESS, this does not mean the payment was a success
print(response['resultInfo']['code'])
# Printing if the transaction status for the code has COMPLETED/ AUTHORIZED
print(response['data']['status'])
SDKsのリリースノートはこちらでご確認ください。

SUCCESS が返却された場合APIは正しく実行されています。支払いが完了すると、response.data.statusのステータスが CREATED から COMPLETED に変わります。 支払いの事前認証の場合、response.data.statusのステータスは CREATED から AUTHORIZED に変わります
レスポンス項目について詳細に知りたい 場合には、[APIドキュメントガイド]をご確認ください。

Cancel a payment

決済をキャンセルしたい場合にこちらを利用ください。通常の決済フローでは基本的には、Cancel a paymentを使いませんが以下の場合に利用ください。

  • Get Payment Detailsを実行したが状態がわからない場合

注:Cancel a paymentは、支払いが行われた翌日の00:14:59まで使用できます。 00:15 AM以降の場合、Refund a paymentを呼び出して支払いを払い戻します。
処理を実施する場合には、以下のパラメーターを使用してリクエストしてください。

FieldRequiredTypeDescription
merchantPaymentIdYesstring <= 64 characters加盟店から提供された一意の支払い取引ID

terminal Terminal
# Calling the method to cancel a Payment
response = client.Payment.cancel_payment("<merchantPaymentId>")
# Printing if the method call was SUCCESS
print(response['resultInfo']['code'])
SDKsのリリースノートはこちらでご確認ください。

SUCCESS が返却された場合APIは正しく実行されています。
レスポンス項目について詳細に知りたい 場合には、 [APIドキュメントガイド]をご確認ください。

Refund payment

ユーザーがサブスクリプションを解約した場合など、返金する場合にRefund a paymentを使用ください。主要な項目を以下に記載しますので、以下のパラメーターを使用してリクエストしてください。

FieldRequiredTypeDescription
merchantRefundIdYesstring <= 64 characters加盟店から提供された一意の払い戻し取引ID
paymentIdYesstring <= 64 charactersPayPayが決済後に発番する取引ID
amountYesinteger <= 11 characters返金金額
reasonNostring <= 255 characters返金理由

terminal Terminal
# Creating the payload to refund a Payment, additional parameters can be added basis the API Documentation

payload = {
    "assumeMerchant": "assume_merchant",
    "merchantRefundId": "merchant_refund_id",
    "paymentId": "paypay_payment_id",
    "amount": {
        "amount": 1,
        "currency": "JPY"
    },
    "reason": "reason for refund"
}

# Calling the method to refund a Payment
response = client.Pending.refund_payment(payload)
# Printing if the method call was SUCCESS
print(response['resultInfo']['code'])
SDKsのリリースノートはこちらでご確認ください。

SUCCESS が返却された場合APIは正しく実行されています。
レスポンス項目について詳細に知りたい場合には、 [APIドキュメントガイド] を確認ください。

Fetch refund status and details

返金処理(`Refund a payment`)がタイムアウトをした場合には、このAPIを利用ください。処理を実施する場合には、以下のパラメーターを使用してリクエストしてください。

FieldRequiredTypeDescription
merchantRefundIdYesstring <= 64 characters加盟店から提供された一意の返品取引ID

terminal Terminal
# Calling the method to get Refund Details
response = client.Payment.refund_status("<merchantRefundId>")
# Printing if the method call was SUCCESS
print(response['resultInfo']['code'])
SDKsのリリースノートはこちらでご確認ください。

SUCCESS が返却された場合APIは正しく実行されています。
レスポンス項目について詳細に知りたい 場合には、 [APIドキュメントガイド]をご確認ください。

突合ファイル

PayPayでは取引明細ファイル(突合ファイル)を日次の処理で生成し、Webhookで通知します。

突合ファイル連携仕様

CategoryDescriptionNote
ファイル連携方法Webhook
ファイル名transaction_<merchant_id>_<from>_<to>.csv
ファイル作成単位加盟店(merchant_id)単位
実行サイクルDailyPayPay側の取引日時が作成対象日の 00:00:00 – 23:59:59 の範囲
通知時間毎日4:00 AM 以降
フォーマットCSV
ファイル保持期間2週間
Character Code(content)SHIFT-JIS
Character Code(filename)UTF-8
newline codeCRLF

ファイルレイアウト

KeyValue fromNote
決済番号paymentIdPayPayで採番された決済番号
加盟店IDmerchant_idPayPayで採番された加盟店識別子
屋号brandNamePayPayで管理しているブランド名
店舗IDstoreIdリクエスト時にセットされたstoreId
店舗名storeNamePayPayで管理している店舗名
端末番号/PosIDterminalIdリクエスト時にセットされたterminalId
取引ステータス "取引完了" , "取引失敗" , "返金完了" , "返金失敗"
取引日時acceptedAt
取引金額amount返金の場合はマイナス記号あり
レシート番号""当機能では設定不可
支払い方法"PayPay残高" , "PayPayカード"
マーチャント決済IDmerchantPaymentId加盟店で採番された決済番号

Webhooks

Webhookの設定

PayPayは、アカウントでイベントが発生したときにアプリケーションに通知するWebhookを送信します。 通知を受信するためには、POSTメソッドを使用してクライアントにデータを送信するWebhook URLを設定する必要があります。 すべての通知データには、どのイベントが発生したかを判断するためにクライアントサービスで使用できるnotification_typeフィールドがあります。 Webhook処理が正常に終了した場合、200 OK のHTTPステータスコードを返してください。 レスポンスボディは必須ではないですが、"OK"など、簡単な文字列を返していただくことを推奨します。

Webhookでの通知

Webhookで通知されたpathからファイルを取得してください。

terminal Terminal
{
  "notification_type":"file.created",
  "notification_id":"<UUID>",
  "fileType":"transaction_recon",
  "path":"https://<server_path>/<filename>?parameters",
  "requestedAt":"<epoch time>"
}
SDKsのリリースノートはこちらでご確認ください。

下のボタンをクリックすると、Webhookの構成を確認できます

Error Handling

PayPayは、HTTP応答ステータスコードとエラーコードを使用して、リクエストの成功または失敗を示します。以下に、詳細のエラーコードごとの実装を詳細に記載致します。

HTTP 2xx

200 すべて正常に動作しています。
201 リクエストされたリソース(コードなど)が作成されたことを表します。
202 リクエストを受け付けたことを意味し、後に処理されます。

HTTP 4xx

400 このステータスコードは、リクエスト時にセットされた情報を処理できないことによるエラーを示します。 以下のOPAエラーコードが返される可能性があります。

  • INVALID_PARAMS リクエスト時にセットされた情報に無効なデータが含まれています。例)サポートされていない通貨がセットされているなど。
  • UNACCEPTABLE_OP リクエストが処理できません。
  • LIMIT_EXCEEDED 支払い上限額を超えています。決済金額が事前承認された金額を超える場合、発生する可能性があります。 *1
  • USER_DEFINED_DAILY_LIMIT_EXCEEDED ユーザ設定の支払い上限額(24時間)を超えています。 *1
  • USER_DEFINED_MONTHLY_LIMIT_EXCEEDED ユーザ設定の支払い上限額(30日)を超えています。 *1
  • NO_SUFFICIENT_FUND 支払のための残高が不足しています。

401 このステータスコードは、認証エラーを示します。 以下のOPAエラーコードが返される可能性があります。

  • UNAUTHORIZED 有効なapi keyとsecretがセットされていません。
  • OP_OUT_OF_SCOPE 対象APIを呼び出す権限がありません。

404 このステータスコードは、リクエストされたリソースがシステムに存在しないことを示しています。
429 このステータスコードは、クライアントが一定期間内に送信したリクエストが多すぎたため、速度制限に達したことを示します。 リクエストの送信を遅くするか、上限引き上げをご要望の旨を弊社までご連絡ください。

*1 : 2021年9月1日より本番環境に追加される予定です

HTTP 5xx

500 この状態コードは、PayPay側で何か問題が発生したことを示します。 下記のOPAエラーコードが返却される可能性があります。

  • TRANSACTION_FAILED このコードは、PayPay側でトランザクションが失敗したことを意味します。 適切なバックオフ時間で、同様の新しいトランザクションの作成が可能です。
  • INTERNAL_SERVER_ERROR このコードは何かがうまくいかなかったことを意味します。 しかし、トランザクションが発生したかどうか正確にはわからないため、不明な支払ステータスとして扱う必要があります。

502,503,504不明な支払いステータスとして扱われます。

Timeout

推奨されるタイムアウト設定は、各APIで指定されています。 最も重要なのは、支払いタイムアウトAPIで、読み取りタイムアウト値を30秒以上で設定してください。タイムアウトが発生した場合、不明な支払いステータスとして扱ってください。

Handle unknown payment status

ステータスが不明な場合、下記のいずれかの方法で対処してください:

  • 取引のステータスを照会するため、照会APIを使用してください。 PayPayで取引が失敗になっている、または存在しない場合は、元取引と同様のリクエストを再度行なってください。
  • キャンセルAPIを使用してください。 キャンセルAPIが提供されている場合は、取引をキャンセルすることもできます。 キャンセルが承認された後、元取引と同様のリクエストを再度行なってください。

Response code list

Common response code

StatusCodeMessage
200SUCCESSSuccess
202REQUEST_ACCEPTEDRequest accepted
400INVALID_REQUEST_PARAMSInvalid request params
401OP_OUT_OF_SCOPEThe operation is not permitted
400MISSING_REQUEST_PARAMS
401UNAUTHORIZEDUnauthorized request
404OPA_CLIENT_NOT_FOUNDOPA Client not found
429RATE_LIMITToo many requests
500SERVICE_ERROR
500INTERNAL_SERVER_ERRORSomething went wrong on PayPay service side
503MAINTENANCE_MODESorry, we are down for scheduled maintenance

Create a continuous payment

StatusCodeMessage
400REQUEST_ORDER_NOT_FOUNDRequest order not found
400UNACCEPTABLE_OPThe requested operation is not able to be processed due to the current condition. E.g. the user is blacklisted by fraud check.
400LIMIT_EXCEEDEDThe payment amount exceeded upper limit. *1
400USER_DEFINED_DAILY_LIMIT_EXCEEDEDThe payment amount exceeded user 24 hours defined limit. *1
400USER_DEFINED_MONTHLY_LIMIT_EXCEEDEDThe payment amount exceeded user 30 days defined limit. *1

*1 : 2021年9月1日より本番環境に追加される予定です

Get payment details

StatusCodeMessage
400DYNAMIC_QR_PAYMENT_NOT_FOUNDDynamic QR payment not found
400DYNAMIC_QR_BAD_REQUESTDynamic QR bad request error

Cancel a Payment

StatusCodeMessage
400ORDER_NOT_REVERSIBLEOrder cannot be reversed
500INTERNAL_SERVER_ERRORRequest timed out

Refund a Payment

StatusCodeMessage
400INVALID_PARAMSInvalid parameters received
400UNACCEPTABLE_OPOrder cannot be refunded
400UNACCEPTABLE_OPMultiple refund not allowed
400INVALID_PARAMSInvalid refund amount
400CANCELED_USERCanceled user
404RESOURCE_NOT_FOUNDOrder not found
500TRANSACTION_FAILEDTransaction failed
500TRANSACTION_FAILEDTransaction failed
500TRANSACTION_FAILEDBalance exceeded
500INTERNAL_SERVER_ERRORRequest timed out

Fetch refund status and details

StatusCodeMessage
404NO_SUCH_REFUND_ORDERRefund not found
500INTERNAL_SERVER_ERRORRequest timed out

本番展開の準備が整っているかどうかは、弊社推奨の チェックリストでご確認ください。