この記事は、Stripe Apps を25日間紹介し続ける Advent Calendar 2022 19日目の記事です。
「Stripeと、外部のSaaSを連携する」
StripeのApp Marketplaceを見ると、MailchimpやIntercom・DocuSignなど、さまざまなサービスと連携するアプリが公開されています。
Stripeが持つ決済やサブスクリプション・顧客の「情報」やプランの変更や請求書の期限超過などの「イベント」を、外部のサービスと連携させることで、よりワークフローを効率的にすることができます。
Stripeとの連携には、OAuthを利用する
Stripe Apps上で外部のサービスにアクセスする場合、OAuthによる認証を推奨しています。
OAuthを利用する場合、Proof Key for Code Exchange(PKCE)フローに対応する必要がありますので、事前にご確認ください。
Google Cloud APIとStripe Appsを連携させる方法
ここからは、連携の例としてGoogle Cloud APIとの連携方法を紹介します。
Google CloudおよびStripeダッシュボードのスクリーンショットは、2022/12時点のものです。
記事作成後、それぞれのサービスがUI・デザインを変更している場合もありますので、ご了承ください。
Step0: Google Cloudで、Gmail APIを有効化する
今回はGmail APIを利用します。
Google CloudのAPIライブラリから、Gmailを検索して有効化しましょう。
[gmail]で検索し、[Gmail API]を見つけたら、[有効にする]ボタンをクリックします。
Google Cloud管理画面の[有効なAPIとサービス]に[Gmail API]が表示されていればOKです。
Step1: Google Cloudで、OAuth同意画面を作成する
OAuthで認証するための設定をGoogle Cloud側で行います。
Google Cloudの管理画面から、[APIとサービス > OAuth同意画面]へ移動します。
[外部]を選び、[作成]をクリックしましょう。
公開アプリの場合は、サポートサイトやプライバシーポリシーのURLなどを整備する必要があります。
作成に成功すると、設定画面が開きます。
テストユーザーを追加しよう
テストモードで認証をパスさせるために、事前にテストで利用するアカウントを登録します。
[テストユーザー]にて、[+ ADD USERS]をクリックしましょう。
メールアドレスを100件まで登録できます。テストに利用したいGoogleアカウントのメールアドレスを追加しましょう。
Step2: OAuthの接続情報を発行・取得する
同意画面の用意ができましたので、接続情報を取得します。
Google Cloud管理画面の[接続情報]から[認証情報を作成]を選択し、[OAuthクライアントID]を選びましょう。
[アプリケーションの種類]を訊かれますので、[ウェブアプリケーション]を選びましょう。
Stripe DashboardのURLを登録する
OAuthでの認証が完了した後に遷移するページなどを登録します。
[承認済みのJavaScript]生成元にはhttps://dashboard.stripe.com
を登録します。
また、[承認済みのリダイレクトURI]には、https://dashboard.stripe.com/test/apps-oauth/{Stripe AppsのID}
を登録しましょう。
[作成]をクリックすると、OAuthクライアントが追加されます。
[JSONをダウンロード]をクリックすると、次のようなJSONがDLできます。
{
"web": {
"client_id": "xxxxxx.apps.googleusercontent.com",
"project_id": "numeric-citron-123456789",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_secret": "GOCSPX-xxxxxxxxxxx",
"redirect_uris": [
"https://dashboard.stripe.com/test/apps-oauth/com.example.first-stripe-app"
],
"javascript_origins": [
"https://dashboard.stripe.com"
]
}
}
Stripe AppsからOAuthの認証画面に遷移する
Google側の設定が終わりましたので、Stripe AppsからGoogleに接続を進めます。
まずはGoogleアカウントでログインするためのUIを用意しましょう。
src/views/App.tsx
を次のように変更します。
import { SignInView } from "@stripe/ui-extension-sdk/ui"
import { useEffect, useState } from 'react'
import { ExtensionContextValue } from "@stripe/ui-extension-sdk/context"
import { createOAuthState } from "@stripe/ui-extension-sdk/utils"
// ダウンロードしたクライアントID
const GOOGLE_API_CLIENT_ID = "xxxxxxx.apps.googleusercontent.com"
const App = ({ environment }: ExtensionContextValue) => {
const { mode } = environment
const redirectUrl = [
"https://dashboard.stripe.com",
mode === "live" ? null : "test",
"apps-oauth",
"{Stripe AppsのID}"
].filter(Boolean).join("/")
const [authURL, setAuthURL] = useState("")
useEffect(() => {
createOAuthState()
.then(({state, challenge}) => {
const url = new URL("https://accounts.google.com/o/oauth2/auth")
const params = new URLSearchParams({
response_type: "code",
client_id: GOOGLE_API_CLIENT_ID,
redirect_uri: redirectUrl,
state,
code_challenge: challenge,
scope: "https://www.googleapis.com/auth/gmail.readonly",
code_challenge_method: "S256"
})
setAuthURL(`${url}?${params}`)
})
}, [redirectUrl])
return (
<SignInView
description="Googleにログインします。"
primaryAction={authURL ? {
label: "ログイン",
href: authURL
} : undefined}
/>
)
}
export default App
変更を保存すると、アプリのUIが次のように変わります。
[ログイン]をクリックすると、Googleの認証画面に移動します。
なお、テストモードのため、警告メッセージが表示されることがあります。
[続行]をクリックすることで、処理を継続できます。
権限の確認画面で、[続行]をクリックすると、Stripeダッシュボードにリダイレクトされます。
認証成功時の処理を追加する
認証画面への移動は実装できましたので、続いてトークンの取得や保存処理を追加しましょう。
Google APIへのアクセス権を設定する
アクセストークンなどを取得するために、Google APIを呼び出す必要があります。
Stripe CLIで、APIを許可リストに追加しましょう。
$ stripe apps grant url "https://oauth2.googleapis.com/token" "Integrate with Google"
関連記事
Google APIを呼び出して、アクセストークンを取得する
続いてGoogle APIからアクセストークンを取得しましょう。
src/views/App.tsx
を次のように変更します。
// ダウンロードしたクライアントID
const GOOGLE_API_CLIENT_ID = "xxxxxxx.apps.googleusercontent.com"
// ダウンロードしたクライアントシークレット
const GOOGLE_API_CLIENT_SECRET = "GOCSPXーxxxxx"
-const App = ({ environment }: ExtensionContextValue) => {
+const App = ({ environment, oauthContext }: ExtensionContextValue) => {
+ const { code, verifier } = oauthContext || {}
const { mode } = environment
const redirectUrl = [
"https://dashboard.stripe.com",
mode === "live" ? null : "test",
"apps-oauth",
"{Stripe AppsのID}"
].filter(Boolean).join("/")
+ useEffect(() => {
+ if (!code || !verifier) return
+ const tokenRequestURL = new URL("https://oauth2.googleapis.com/token")
+ const params = {
+ code,
+ grant_type: "authorization_code",
+ code_verifier: verifier,
+ client_id: GOOGLE_API_CLIENT_ID,
+ client_secret: GOOGLE_API_CLIENT_SECRET,
+ redirect_uri: redirectUrl
+ }
+ fetch(`${tokenRequestURL}?${new URLSearchParams(params)}`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/x-www-form-urlencoded"
+ },
+ }).then(response => {
+ if (response.ok) {
+ return response.json()
+ }
+ return response.json().then(error => {
+ throw new Error(`${error.error}: ${error.error_description}`)
+ })
+ }).then(data => {
+ console.log(data)
+ }).catch(console.log)
+ }, [code, verifier, redirectUrl])
この状態で、再度[ログインボタン]をクリックしてみましょう。
ダッシュボードにリダイレクトされた際、開発コンソールのログにアクセストークンなどが表示されています。
*画像のトークンはダミーです。
実際に発行されたトークンをブログやGitHubなどで公開しないようにご注意ください。
取得したアクセストークンを、Stripe Secret Store APIで保存する
取得したアクセストークンを利用できるようにするため、Secret Store APIを使って保存しましょう。
関連記事
まず、Stripe CLIでアクセス権限を設定します。
$ stripe apps grant permission "secret_write" "Store accesst token"
続いてsrc/views/App.tsx
を次のように変更します。
import { createOAuthState } from "@stripe/ui-extension-sdk/utils"
+import Stripe from 'stripe'
+import {createHttpClient, STRIPE_API_KEY} from '@stripe/ui-extension-sdk/http_client'
+const stripe = new Stripe(STRIPE_API_KEY, {
+ httpClient: createHttpClient(),
+ apiVersion: '2022-11-15',
+});
-const App = ({ environment, oauthContext }: ExtensionContextValue) => {
+const App = ({ environment, oauthContext, userContext }: ExtensionContextValue) => {
+ const userId = userContext.id
...
}).then(response => {
if (response.ok) {
return response.json()
}
response.text().then(text => {
throw new Error(text)
})
}).then(data => {
- console.log(data)
+ return stripe.apps.secrets.create({
+ scope: {
+ type: 'user',
+ user: userId,
+ },
+ name: "oauth_token",
+ payload: JSON.stringify(data)
+ })
}).catch(console.log)
- }, [code, verifier, redirectUrl])
+ }, [code, verifier, redirectUrl, userId])
これでブラウザをリロードしたり、別のデバイスやブラウザからStripeダッシュボードにログインした場合でも、Google APIにアクセスするためのトークンを利用できます。
Gmail APIを呼び出してみよう
最後に取得・保存したアクセストークンを利用して、Gmail APIを呼び出してみましょう。
Stripe CLIで、APIを許可リストに追加しましょう。
$ stripe apps grant url "https://www.googleapis.com/gmail" "Integrate with Google"
続いてGmail APIを呼び出すための処理を、src/views/App.tsx
に追加します。
}, [code, verifier, redirectUrl, userId])
+ useEffect(() => {
+ if (code && verifier) return
+ if (!userId) return
+ stripe.apps.secrets.find({
+ scope: {
+ type: "user",
+ user: userId,
+ },
+ name: "oauth_token",
+ expand: ["payload"]
+ }).then(({payload}) => {
+ if (!payload) return
+ const secrets = JSON.parse(payload)
+ if (!secrets.access_token) return
+ return fetch(`https://www.googleapis.com/gmail/v1/users/{連携させたGmailアドレス}/messages`, {
+ method: "GET",
+ headers: {
+ "Authorization": `${secrets.token_type} ${secrets.access_token}`
+ }
+ }).then(data => data.json())
+ }).then(console.log)
+ .catch(e => {
+ if (e.code === "resource_missing") {
+ return
+ }
+ console.log(`${e.code}: ${e.message}`)
+ })
+ }, [code, verifier, userId])
const [authURL, setAuthURL] = useState("")
接続に成功していれば、Gmailのメールスレッド情報が開発コンソールに表示されます。
本格的な開発に向けて
この記事では、連携させるところまでを紹介しました。
実際の開発では、次のような要件も発生します。
- アクセストークンの有効期限が切れた場合のトークンの更新と保存
- 連携済み or 未連携でアプリのUIを出し分ける
- 設定画面から、連携の解除や変更ができる機能
決済やサブスクリプションの運用業務を効率化させるための開発や機能提案の1つとして、ぜひ2023年はStripe Appsをご検討ください。
[Tips]一度認証したGoogleアカウントで、再度認証フローに入りたい場合
一度認証に成功し、アクセストークンを取得すると、アクセス権の確認などのページに遷移しなくなります。
認証フローをもう一度試したい場合は、Googleアカウントの[セキュリティ > アカウントにアクセスできるサードパーティアプリ]から登録したアプリを削除しましょう。
Documents
Stripe Appsひとりアドベントカレンダー 2022
今年ベータリリースされたばかりのStripe Appsは、まだ日本語の情報が多くありません。
そこでQiita Advent Calendar 2022にて、毎日Stripe Appsについての情報を投稿します。
ノーコードで利用する方法や、開発するためのTipsなども紹介予定ですので、ぜひ購読をお願いします。