Closed6

SDK ではなく REST API で PayPal 決済・認証をする

9sako69sako6

下記公式ドキュメントで使用されている PayPal の SDK は便利だが、購入ボタンが特定のデザインに固定される。完全にカスタマイズされたボタンで PayPal 決済をする方法を探る。

https://qiita.com/PPJP/items/db5c57991c2c3fe80ac7

前提

  • Web アプリケーションで商品を購入できるようにしたい
  • 購入ボタンはオリジナルのものを作りたい
  • 金額は予めわかっている
  • ユーザーが承認したら即座に決済を完了し、元の商品ページに戻りたい
9sako69sako6

Create Order

PayPal REST API で Create Order し、レスポンスで返ってくる決済承認用 URL にユーザーをリダイレクトすればよさそう。

To create an order:

  1. In your Postman workspace, navigate to your fork of the PayPal collection.
  2. Select Orders > Create Order > Send. On a successful call, the API returns a 201 order created response code.
  3. Find the approve link in the response.
  4. Open the approve link in a browser.
  5. Log in with your Developer Dashboard sandbox personal account credentials.

https://developer.paypal.com/api/rest/postman/

Create Order のエンドポイントを叩く際に、リダイレクトから戻ったときの URL やキャンセル時に戻る URL、PayPal-Request-Idリクエストヘッダーなど必要なものはもろもろリクエストに含めておく。

https://developer.paypal.com/docs/api/orders/v2/#orders_create

承認されたら即座に決済を完了させたいが、Capture はどうやってやればいいんだろう。
ユーザーがブラウザで承認した後じゃないといけない。

return_url のクエリパラメータにいろいろ情報を詰めておき、商品ページに戻ってきた時に改めて Capture するのが一つの案。

9sako69sako6

Create Order 時の return_url には元の商品ページを指定するイメージでいたが、承認後に行いたい処理を実装した API の URL を指定することでも Capture ができそう。

アプリケーション用の API を用意し、承認後に行いたい処理を特定のエンドポイントに実装する。
このエンドポイントの中で PayPal API の Capture を叩き、成功したら元の商品ページにリダイレクトするレスポンスを返す。

PayPal の Webhook を使う手もありそう。
しかし、購入が完了していたら商品ページで即座に状況を反映したいので、遅延が発生しないように上記の案がよさそう。

9sako69sako6

エラーハンドリング

https://qiita.com/PPJP/items/db5c57991c2c3fe80ac7#テストについて

PayPalアカウントのカード与信エラーの発生方法:
カードの請求先住所(カードを登録する際に入力)の番地(Line1)に「CCREJECT-REFUSED」といれると、カード与信エラーが常に発生するようになります。このカードを決済時に利用することで、上記の「カード与信エラーが起きた場合のリカバリー」のテストができます。

と書いてあるが、上記記事でリンクされたドキュメントが 404 なのでもう使えないのか...?
リクエストの値をいじってエラーにする方法は下記にあるが、E2E でテストしたいのでアカウント側の設定でやりたいなあ。
https://developer.paypal.com/tools/sandbox/negative-testing/

これでできそう!
https://developer.paypal.com/api/rest/sandbox/card-testing/#link-creditcardgeneratorfortesting

sandbox アカウントでログインして、カード作成時に住所にエラートリガー文字列を入れておくとエラーにできた。(ドキュメントのようにカード名や First Name を設定する欄は見当たらない。)

不正なカードを使って決済しようとすると、capture に失敗して下記のようなエラーメッセージが返ってきた。

{
  "name": "UNPROCESSABLE_ENTITY",
  "details": [
    {
      "issue": "INSTRUMENT_DECLINED",
      "description": "The instrument presented  was either declined by the processor or bank, or it can't be used for this payment."
    }
  ],
  "message": "The requested action could not be performed, semantically incorrect, or failed business validation.",
  "debug_id": "e416fbb215a2f",
  "links": [
    {
      "href": "https://developer.paypal.com/docs/api/orders/v2/#error-INSTRUMENT_DECLINED",
      "rel": "information_link",
      "method": "GET"
    },
    {
      "href": "https://www.sandbox.paypal.com/checkoutnow?token=9LC452798Y049805P",
      "rel": "redirect",
      "method": "GET"
    }
  ]
}
9sako69sako6

ユーザーが PayPal を使って Web サービス上のコンテンツを購入する実装は上記の流れでできる。

9sako69sako6

ユーザーの PayPal アカウントに送金するには

逆に、ユーザーが Web サービス上で立てた売上げをサービス側から送金したいときにどうするか。
PayPal に登録されているメールアドレスか携帯電話番号を使う。

PayPalアカウントを使用して資金を受け取るには、PayPalアカウントに登録されている確認済みのメールアドレス、または携帯電話番号に支払いを行うよう、支払い元に依頼してください。

メールアドレスを使うとして、どうやってサービス側から取得するか。下記のドキュメントに書いてある。

https://developer.paypal.com/docs/log-in-with-paypal/integrate/

個人情報を Web サービス上で管理するのは嫌なので、認証に使っている Firebase Authentication を利用できないか試してみる。PayPal は OpenID Connect 準拠のようなので自前で provider を作れば出来そう。

https://www.paypalobjects.com/.well-known/openid-configuration

https://firebase.google.com/docs/auth/web/openid-connect?hl=ja

と思ったが、PayPal sandbox のディスカバリードキュメントがないのでこの方法は無理だ。(live 環境しか使ってないならできるけど)

このスクラップは6ヶ月前にクローズされました