LGTMoonにPayPalで課金機能を実装
2021/04/30 - 05/01 ハッカソン
やること候補
Flutter
やること思いつかなかった
Nuxt.js で PWA(Progressive Web Apps)
PayPal 決済
PayPay
はじめに
会社で課金系の部署に配属された
課金色々勉強してきた(主に、携帯の通信量とまとめて支払い的なやつ)
docomo SPモード決済
ソフトバンクまとめて支払い
auかんたん決済
PayPal 勉強したい → やる
昔作った LGTMoon というアプリ
LGTMoon に月額課金 or 都度課金をつける
月額課金: LGTMoon上にアカウントとかログインとかを実装する必要がる
都度課金にする → 300円はらったら30日広告が消える、みたいなのを実装する
300円払ったらシリアルコードみたいなのを発行
シリアルコードを入力すると、ブラウザのCookieとかに広告無し情報をセット
PayPal
課金方法がいろいろある
日本語の情報結構古いので海外版のドキュメント見たほうが良さそう
メールで決済
これは、PayPal の Web ページで請求書を発行して、相手に送るってやつ
Web サービスには使うやつじゃない
かんたん決済ボタン
多分一番楽なやつ
これで普通に月額課金もできそう
「購読する」ってのがある
API決済
アプリから決済したいとか、決済画面のデザインを凝った感じにしたい場合はこれを使う
定期支払
これは単に、「かんたん決済ボタン」と「API決済」で、定期支払もできますよ、という話だった
ペイパル+クレジット決済
ペイパルのアカウントがなくてもクレジットカードで決済できますよというやつ
いわゆる普通の、クレカの決済代行会社みたいなシステム
月額3000円かかる
従量課金
客から事前承認をもらっておいてで、購入ボタンを押すときに承認を挟まない(PayPalのページに飛ばすことなく承認できる)
頻繁に課金が発生したり、月ごとに料金が変わるのものに使う(たぶん)
アプリ内課金
手数料
40円 + 支払いの4%くらいらしい
かんたん決済ボタン
とりあえずかんたん決済ボタンから作ってみる
アカウント作成
ビジネスアカウント(売る方のアカウント)と、個人アカウント(買う方のアカウント)がある
ビジネスアカウントの作成方法
https://gyazo.com/37bf45d7304cd39a4b06084c99e7c0d8
「商品またはサービスのキーワード」がむずい(自由入力ではない)
https://gyazo.com/0e2568758bc258911c4f00081ae39f1d
どういう支払い方法をしたいですか?
Webでの支払い、とか、定期購読、とか選ぶと、なんかいい感じに設定手順が出てくる
サンドボックスアカウントの作成
ここでサンドボックス用のアカウントが作れる
サンドボックス = 支払いが実際には発生しない動作確認用
サンドボックス用のビジネスアカウントと個人アカウントが作成できる
ビジネスアカウントで clientId と secret を発行して、個人アカウントで購入して動作確認する
https://gyazo.com/e36fac0a72a686d5544fa38c15957449
スマート決済ボタン
とりあえずスマートチェックアウトってやつを選択してボタンを作る。
そんなに細かいカスタマイズはできない
https://gyazo.com/bcf1324f01e8ba2ea3248cfce16184cd
本当は Nuxt.js とか使ってページ作りたいけど、とりあえず、 Scala Play のテンプレートで試してみることに
https://gyazo.com/0c076a343d5c14505f870566660a938b
動作確認
Sandbox アカウントで決済できる
https://gyazo.com/8133edfde9baa808b0deee8fea570993
支払いが完了した時に処理をする
PayPal が自動生成した HTML に onApprove というメソッドがあり、これを変更すればなんやかんやできるはず
code:sh
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
alert('Transaction completed by ' + details.payer.name.given_name + '!');
});
},
ただ、単にここの処理を変更するだけだと、手動でAPI叩いたりとかできちゃうので、サーバーサイドで注文が正しいかどうかはチェックする必要があるはず。
ちなみに、支払い完了時に飛んでくる情報
console.log(details)
これ、業務で PayPal 使ってた時にも思ったけど、PayPal は、支払い者の名前とか住所とか電話番号をカジュアルに飛ばしてくるので、大丈夫なの?って思ったりする。
https://gyazo.com/12fdd766def391cddcc6407de9797f49
ちなみに、簡単決済ボタンについてのドキュメントはこれ
Customize the PayPal JS
onApprove で受け取った orderId をサーバーサイドに渡す
サーバーサイドで PayPal API を叩いて検証。問題なければ Cookie を発行する。
サーバーサイドから叩く PayPal API
レスポンス
確認すること
status が COMPLETED である
payee の マーチャントID を確認する
マーチャント ってのは商品を提供してお金を貰う人のこと
メールアドレスを確認するのでもいい
価格を確認する
なんか確認しろって PayPal のドキュメントに書いてあった気がする
create_time を確認する
何故か金額は string になっている
code:json
{
"id": "2N072191W44509916",
"intent": "CAPTURE",
"status": "COMPLETED",
"purchase_units": [
{
"reference_id": "default",
"amount": {
"currency_code": "JPY",
"value": "330",
"breakdown": {
"item_total": {
"currency_code": "JPY",
"value": "300"
},
"shipping": {
"currency_code": "JPY",
"value": "0"
},
"tax_total": {
"currency_code": "JPY",
"value": "30"
}
}
},
"payee": {
"email_address": "sb-yejr66074697@business.example.com",
"merchant_id": "32A2M4EKKMP3A"
},
"description": "LGTMoonに寄付",
"shipping": {
"name": {
"full_name": "Doe John"
},
"address": {
"address_line_1": "Nishi 4-chome",
"admin_area_2": "Shibuya-ku",
"admin_area_1": "Tokyo",
"postal_code": "150-0002",
"country_code": "JP"
}
},
"payments": {
"captures": [
{
"id": "77628240HP8610325",
"status": "COMPLETED",
"amount": {
"currency_code": "JPY",
"value": "330"
},
"final_capture": true,
"seller_protection": {
"status": "ELIGIBLE",
"dispute_categories": [
"ITEM_NOT_RECEIVED",
"UNAUTHORIZED_TRANSACTION"
]
},
"seller_receivable_breakdown": {
"gross_amount": {
"currency_code": "JPY",
"value": "330"
},
"paypal_fee": {
"currency_code": "JPY",
"value": "52"
},
"net_amount": {
"currency_code": "JPY",
"value": "278"
}
},
"links": [
{
"rel": "self",
"method": "GET"
},
{
"rel": "refund",
"method": "POST"
},
{
"rel": "up",
"method": "GET"
}
],
"create_time": "2021-04-30T06:56:44Z",
"update_time": "2021-04-30T06:56:44Z"
}
]
}
}
],
"payer": {
"name": {
"given_name": "John",
"surname": "Doe"
},
"email_address": "sb-bbiri6076567@personal.example.com",
"payer_id": "7LAU9Q6YQBXZ2",
"address": {
"country_code": "JP"
}
},
"create_time": "2021-04-30T06:56:23Z",
"update_time": "2021-04-30T06:56:44Z",
"links": [
{
"rel": "self",
"method": "GET"
}
]
}
Capture とは
お金のやりとりは オーソリ(Authorize)→売上確定(Capture)という流れで行う
「オーソリ」はクレカの利用額の確保だけ行う。「売上確定」は実際に請求が走る。
在庫の概念がある商品は オーソリ→在庫確保→売上確定 の流れで行う
今回の僕の実装は、在庫の概念が無いので、オーソリと売上確定は同時に行う
このボタンの実装でどれだけ細かいことができるのかは謎
table:売上の詳細について
gross_amount 支払い者が支払った金額
paypal_fee PayPal に支払う手数料。今回は52円 = 40円 + (300円の約4% = 12円)
net_amount gross_amount - paypal_fee → 我々に入るお金
マーケットプレイス決済の場合は platform_fees もマイナスされる
platform_fees 多分、マーケットプレイス用決済のプラットフォームの取り分だと思う
(プラットフォームと出品者が居て、みたいなやつ)
Scala の time について
Date and Time API 復習 - Qiita