PayPalの定期支払APIについて


# ペイパルでサブスクしたい！

そんな人も多い，サブスク時代なのではないのでしょうか？ 爆

ちょっと調べたらペイパルに定期支払APIあるじゃん！
ペイパル定期支払実装簡単そう！

さあドキュメントを読もう!
https://developer.paypal.com/docs/subscriptions/

．
．
．

ドキュメント読んでも理解に時間がかかったので，自分の読解力のなさに絶望．
ドキュメントの構造や，管理画面が`Stripe`と比べるとちょっとクセがあるかなぁと感じました．

ドキュメント内の気になった内部リンク踏んでいくと，いつの間にか定期支払以外のAPIの方に行って混乱したりするので，paypalのドキュメントは順番通りに読み進めることをオススメします．

公式のqiitaもありますが，
https://qiita.com/PPJP/items/1668c546a2c09f840819
基本的にはドキュメントを読んでね．というリンクなので，

噛み砕いた自分の理解を，少しでも誰かの役に立てればと思っています．
APIも随時更新される可能性あるので，あくまでも参考にお願いします．



## 前提


- **ペイパルの（ビジネス）アカウント**

が必要になります．ここから自分のアカウントの状態がわかりますが，
https://developer.paypal.com/developer/accountStatus/

***ライブモード***まで使うにはビジネスアカウントにしておく必要があります．
ここではアカウント作成の流れは省略します．



## 簡単に説明

簡単にやることの順番を説明すると，これだけです．

**1. トークン作成**
**2. プロダクツID作成**
**3. プランID作成**
**4. 作成したのプランIDをjavascriptに追加**





## 実践

ターミナル使います！
トークン作成からプランID作成までは`curl`でAPIを呼び出し，そのレスポンスから必要な情報を取得できます．



### 1.トークン作成


まず，自分のクライアントIDが必要になります．　
（加筆:Client Secret も必要ですのでメモしておきましょう）
ここからクライアントIDをコピーしておき，メモしておきましょう．

https://developer.paypal.com/developer/applications/

<img width="1292" alt="screenshot.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567202/6ad73993-a7b9-8843-2b0a-3988a24b7293.png">


以下のcurlコマンドのクライアントIDを自分のIDに修正し，
(加筆：Client Secret も合わせて修正してください）

ターミナルを開いて，コマンドを送信します．

~~~shell:コマンド
curl -v https://api.sandbox.paypal.com/v1/oauth2/token \
   -H "Accept: application/json" \
   -H "Accept-Language: en_US" \
   -u "(Client ID):(Client Secret)" \
   -d "grant_type=client_credentials"
~~~


~~~json:レスポンス
{
	"scope": "https://uri.paypal.com/services/invoicing https://uri.paypal.com/services/disputes/read-buyer https://uri.paypal.com/services/payments/realtimepayment https://uri.paypal.com/services/disputes/update-seller https://uri.paypal.com/services/payments/payment/authcapture openid https://uri.paypal.com/services/disputes/read-seller https://uri.paypal.com/services/payments/refund https://api.paypal.com/v1/vault/credit-card https://api.paypal.com/v1/payments/.* https://uri.paypal.com/payments/payouts https://api.paypal.com/v1/vault/credit-card/.* https://uri.paypal.com/services/subscriptions https://uri.paypal.com/services/applications/webhooks",
	"access_token": "アクセストークンがここにあります",
	"token_type": "Bearer",
	"app_id": "APP-XXXXXXXXXXXXXX",
	"expires_in": 31306,
	"nonce": "2020-XXXXXXXXXXXXXXXXXXXXXXXX"
}
~~~

ここの`access_token`の入ったレスポンスが返ってきたら成功です．
これで**アクセストークン**が取得できました．
これも次以降のコマンドで使用するのでメモしておきましょう．



　
　



### 2.プロダクツID作成

先程取得した**アクセストークン**を
`Authorization: Bearer `
のあとにコピペし，**name**以下の項目もそれぞれ自分の使用するサービスに合わせて適に入力し，コマンドを送信します．


`Authorization: Bearer アクセストークン`
です．
`Authorization: アクセストークン`
と間違えないようにしましょう．
 
 


~~~shell:コマンド
curl -v -X POST https://api.sandbox.paypal.com/v1/catalogs/products \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer 先程取得したトークンをここに" \
-d '{
  "name": "サービスの名前をここに記入",
  "description": "説明をここに記入",
  "type": "SERVICE（適に変更してください）",
  "category": "SOFTWARE（適に変更してください）",
  "image_url": "https://（適に変更してください）.png",
  "home_url": "https://（適に変更してください）.com"
}'
~~~


~~~json:レスポンス
{
	"id": "PROD-XXXXXXXXXXXXXXXX",
	"name": "サービス名",
	"description": "サービス説明",
	"create_time": "2020-01-14T09:50:42Z",
	"links": [
		{
			"href": "https://api.sandbox.paypal.com/v1/catalogs/products/PROD-XXXXXXXXXXXXXXXXXX",
			"rel": "self",
			"method": "GET"
		},
		{
			"href": "https://api.sandbox.paypal.com/v1/catalogs/products/PROD-XXXXXXXXXXXXXXXXXX",
			"rel": "edit",
			"method": "PATCH"
		}
	]
}
~~~

`id`の箇所の`PROD-XXXXXXXXXXXXXXXX`がプロダクツIDとなります．
これも次に使用するのでメモしておきましょう．

　
　



### 3.プランID作成


先程と同じく，**アクセストークン**を
`Authorization: Bearer `
に入れるのと，，**name**以下の項目もそれぞれ自分の使用するサービスに合わせて適に入力し，コマンドを送信します．


`billing_cycles`以下の項目が料金プランの設定項目になりますが，
ここでは説明を省きます．



設定できる項目やその説明はドキュメントをどうぞ！
時間があったら別途説明を追加するかもです，，，
https://developer.paypal.com/docs/api/subscriptions/v1/


以下はサンプルの定期支払プランです．

~~~shell:コマンド
curl -v -k -X POST https://api.sandbox.paypal.com/v1/billing/plans \
  -H "Accept: application/json" \
  -H "Authorization: Bearer トークンをここに入力" \
  -H "Prefer: return=representation" \
  -H "Content-Type: application/json" \
  -d '{
      "product_id": "PROD-XXXXXXXXXXXXXXXX",
      "name": "Basic Plan（料金プランの名前）",
      "description": "料金プランの説明",
      "billing_cycles": [
        {
          "frequency": {
            "interval_unit": "MONTH",
            "interval_count": 1
          },
          "tenure_type": "TRIAL",
          "sequence": 1,
          "total_cycles": 1
        },
        {
          "frequency": {
            "interval_unit": "MONTH",
            "interval_count": 1
          },
          "tenure_type": "REGULAR",
          "sequence": 2,
          "total_cycles": 12,
          "pricing_scheme": {
            "fixed_price": {
              "value": "100",
              "currency_code": "USD"
            }
          }
        }
      ],
      "payment_preferences": {
        "auto_bill_outstanding": true,
        "setup_fee": {
          "value": "10",
          "currency_code": "USD"
        },
        "setup_fee_failure_action": "CONTINUE",
        "payment_failure_threshold": 3
      },
      "taxes": {
        "percentage": "10",
        "inclusive": false
      }
    }'
~~~



~~~json:レスポンス
{
	"id": "P-XXXXXXXXXXXXXXXXXXXXXXXXX",
	"product_id": "PROD-XXXXXXXXXXXXXXXXXXXXXXXXX",
	"name": "Basic Plan",
	"status": "ACTIVE",
	"description": "Basic plan",
	"billing_cycles": [
		{
			"frequency": {
				"interval_unit": "MONTH",
				"interval_count": 1
			},
			"tenure_type": "TRIAL",
			"sequence": 1,
			"total_cycles": 1
		},
		{
			"pricing_scheme": {
				"version": 1,
				"fixed_price": {
					"currency_code": "USD",
					"value": "100.0"
				},
				"create_time": "2020-01-XXXXXXXXXXXXXX",
				"update_time": "2020-01-XXXXXXXXXXXXXX"
			},
			"frequency": {
				"interval_unit": "MONTH",
				"interval_count": 1
			},
			"tenure_type": "REGULAR",
			"sequence": 2,
			"total_cycles": 12
		}
	],
	"payment_preferences": {
		"auto_bill_outstanding": true,
		"setup_fee": {
			"currency_code": "USD",
			"value": "10.0"
		},
		"setup_fee_failure_action": "CONTINUE",
		"payment_failure_threshold": 3
	},
	"taxes": {
		"percentage": "10.0",
		"inclusive": false
	},
	"quantity_supported": false,
	"create_time": "2020-01-XXXXXXXXXXXXXX",
	"update_time": "2020-01-XXXXXXXXXXXXXX",
	"links": [
		{
			"href": "https://api.sandbox.paypal.com/v1/billing/plans/P-XXXXXXXXXXXXXX",
			"rel": "self",
			"method": "GET"
		},
		{
			"href": "https://api.sandbox.paypal.com/v1/billing/plans/P-XXXXXXXXXXXXXX",
			"rel": "edit",
			"method": "PATCH"
		},
		{
			"href": "https://api.sandbox.paypal.com/v1/billing/plans/P-XXXXXXXXXXXXXX/deactivate",
			"rel": "self",
			"method": "POST"
		}
	]
}
~~~

`"id": "P-XXXXXXXXXXXXXXXXXXXXXXXXX"`
の部分がプランIDとなり，これをjavascriptの方に設定すればokです．


　
　

### 4.javascript組み込み


`CLIENT_ID`に自分のクライアントIDを入れ，htmlのhead内に以下を配置します．


~~~javascript:headに配置
<script src="https://www.paypal.com/sdk/js?client-id=CLIENT_ID&vault=true"></script>
~~~


***「ペイパルで支払い」***ボタンを挿入したい箇所に以下のdivを配置します．

~~~html:ボタン挿入
<div id="paypal-button-container"></div>
~~~


`createSubscription`部分以外は任意です．
こんな感じでクリックされたときのフォーム内容に応じて，プランを変更したり，決済完了後の動作を制御することができます．

~~~javascript:動作制御用javascript
<script type="javascript">

paypal.Buttons({

    //支払いボタンのスタイルの変更ができます
    style: {
    	layout: 'horizontal',
        color: 'blue',
        label: 'pay',
        tagline: 'true'
    },

    //ボタンがクリックされたときの処理を追加できます
    onClick: function() {

    },

    //プランIDをここで設定します
    createSubscription: function(data, actions) {
        return actions.subscription.create({
          'plan_id': 'P-XXXXXXXXXXXXXX'
        });
      },

    //ペイパルの決済画面から戻ってきたときの動作を制御できます
    onApprove: function(data, actions) {
        if(data.subscriptionID){
            console.log("○完了 : " + data.subscriptionID);
            //フォームの送信処理などを追加できます
        }
    }

  }).render('#paypal-button-container');


</script>
~~~


　　

##最後に

ここまでの説明は
https://developer.paypal.com/docs/subscriptions/integrate/

ここのドキュメントに書いていることとだいたい同じなのですが，

あれ?
curl？
管理画面からプラン作成とかするんじゃないの？

みたいな感じで思っていると，私のようにドキュメントをウロウロすることになるかと思います．

あと，

**1. トークン作成**
**2. プロダクツID作成**
**3. プランID作成**
**4. プランIDをjavascriptに追加**


これの流れが必要だということが分かっていれば，ドキュメントも読みやすくなるかと思います．


参考になれば幸いです．