前回の記事では、Cloud Functions を使用したレシート検証を行いましーた。
デプロイまでは行なったのですが、テストはしていません。
というのも、サーバーでのテストは、アプリ側の実装やアクセス権限など地味に作業があるので、記事を分けさせてもらいました。
やっと下山できるので、ぬるりと気張ってきましょう
開発環境(前提条件)
前記事からの引用みたいなもんですが、今回も一応記載。
・macOS BigSur
・Homebrew
・Xcode12.3
・Swift5
・Node.js
・課金実装や Firebase 連携は済んでいるものとします
・対象プロジェクトの Firebase 料金プランを Blaze に変更しているものとします
関数へのアクセスを制限する
verifyReceipt 関数のアクセス制限をGoogle Cloud Platformで設定します。
誰でもアクセスできちゃうと金銭的にもセキュリティ的にもよくないので。
新しいロールを作成する
ロールというのは、メンバーに割り当てることができる権限のグループのことです。要はアクセス権です。
アクセス権を細かく設定することで、他のリソースへのアクセスを防ぐことができます。
関数ごとに割り当てることができ、Functions や Authentication などのサービスごとにデフォルトで複数作成されていますが、ここではカスタムします。
1)ヘッダーからプロジェクトを選択(なければ新しいプロジェクトを追加)
2)ヘッダーから「ナビゲーションメニュー」を選択
3)「IAM と管理」→「ロール」を選択
4)ページ上部にある「+ロールを作成」を選択(以下の画面になります)
5)「タイトル」「ID」「ロールのリリース段階」を入力
6)「+権限を追加」を選択して「cloudfunctions.functions.call」を追加
最後に「作成」を押して完了することで、ひとまずロールの作成は以上となります。
今回作成したロールは、Cloud Functions の call 以外のアクセス権は持っていないことになるので、create や delete などの操作も出来ませんが、権限は最小限にすることが推奨されているので、そこを意識しました。
Cloud Functions のアクセス権について知りたい方は公式ドキュメントを一読くださいませ。
関数にロールを設定する
Cloud Functions にデプロイした関数(ここでは verifyReceipt)が表示されてると思いますので、以下の手順で確認してください。
1)「ダッシュボード」を選択
2)「リソース」の「 Cloud Functions 」を選択
3)デプロイした関数を選択(以下の画面になります)
5)「権限」を選択
6)そのすぐ下の「+追加」を選択して、メンバーを追加します
7)新しいメンバーに「 allUsers 」を記入
8)「ロールを選択」→「カスタム」→ 先ほど作ったロールを選択
最後に「保存」を押して完了してください。アクセス制限は以上となります。
レシート検証をテスト
デプロイした verifyReceipt 関数を、アプリからアクセスしたいと思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// import Firebase は忘れずにお願いしまっす Auth.auth().currentUser?.getIDToken(completion: { (token, error) in // ★1 guard let token = token else { return } let data: [String: Any] = ["Method": "POST", "Authorization": "Bearer \(token)", "Content-Type": "application/json", "product_id": "product_id_1", "receipt-data": "eyJzaWduYXR1cmUiID0gIkFoaHEw..."] // ★2 let functions = Functions.functions(region: "us-central1") functions.httpsCallable("verifyReceipt").call(data) { result, error in if let error = error { print("error: " + error.localizedDescription + " \(error)") } else { print(result?.data) } } }) |
★1:verifyReceipt 関数で認証を行うので、ID トークンを取得します(このシリーズの記事では匿名認証を使用)
★2:レシートを Base64 エンコードしたデータに置き換えてください。
SNS 認証や Google 認証などを使っている場合は、自動認証してくれるので ID トークンは不要です。
さらに自動認証は課金にカウントされないのでオススメですが、アカウントでの認証を必要としない仕様では使えないので、Cloud Functions 側で認証する必要があります。
このときは課金にカウントされますが仕方ねーです (´·ω·`)
少し脱線しましたが、上記のコードを実行すると、レシート情報が返ってくると思いますので、お試しください。
Cloud Firestore で課金情報を保持する
データベースを作成する
Cloud Firestore というモバイル、ウェブ、サーバー開発に対応した柔軟かつスケーラブルなデータベースがあります。
ユーザーのアイテム情報や課金履歴を保存するために、この Cloud Firestore を使用してデータベースを作成しましょう
ブラウザから Firabase にログインして対象プロジェクトを選択し、左側にあるサイドメニューから Cloud Firestore を選択して、テストモードでデータベースを作成します。
画像のように、テストモードで開始 → ロケーションの設定 を行います。
東京のロケーションは asia-northeast1 となっています。
大阪も選べるし、アメリカとか外国も選択できるので、アプリのユーザー数が多い場所に合わせて選択してください。
これだけでデータベースの箱ができます。
課金情報を書き込む
Firestore に書き込む方法は2つあり、「Cloud Functions からの書き込み」と「アプリ側からの書き込み」になります。
今回のような課金情報を保持したい場合は以下のようになりますね。
・Cloud Functions でレシート検証〜データベースへの書き込み行う
・Cloud Functions でレシート検証、その結果を元にアプリ側でデータベースへの書き込みを行う
今回は後者の方法をやっていきたいと思います。
1 2 3 4 5 6 7 8 |
let user = Firestore.firestore().collection("users").document(uid) // ★1 user.setData(["item": 1]) // ★2 let purchases = user.collection("purchases") // ★3 let purchase: [String: Any] = ["date": date, "productId": "product_id_1"] purchases.addDocument(data: purchase, completion: { error in // ★4 print(error?.localizedDescription) }) |
★1:users というコレクションを作成し、uid をユニーク ID としたドキュメント(ユーザー)を作成
★2:作ったドキュメント(ユーザー)の直下にアイテム数を設定
★3:課金履歴を持つために、ドキュメント(ユーザー)の直下にコレクションを作成
★4:日付と ProductID をひとまとめにしたデータを作成して追加する
上記のようなコードで追加できます。
データベースのイメージとしては、以下のようなデータ構成になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
users | +- uid //自動生成することも出来ます。ここでは匿名認証で作成した ID を設定 | | | +- item: 1 | | | +- purchases | | | +- XsdjFilmwEkuaux //自動生成される文字列 | | | | | +- date: 2021:01:01 12:00:00 | | | | | +- productId: product_id_1 | | | +- qkTmaXJwlvqpNav | | | +- date: 2021:01:02: 12:00:00 | | | +- productId: product_id_2 | +- uid | | | +- item: 0 | | |
こういう感じで保存されるよってのを分かりやすくするためのデータ構成にしているので、課金履歴もテキトーに作ってます。
仕様に合わせて変更してください。
以上で課金のレシート確認からユーザーごとの課金情報保管までが完了しました!
さいごに
絶対忘れるやーつなので、他のアプリがあったらこれ見ながら作成します。笑
データベースやレシート確認は課金の種類でも異なるので、アプリごとの仕様を考慮して、適当に構成してください!
コメント