2023年8月24日木曜日

StripeのPaymentIntentsを使ったカード決済をAPEXアプリケーションに実装する

Stripeによる決済の実装は、以前にノーコードについては紹介したことがあります。こちらの記事になります。今回はPaymentIntentsを使ってカード決済を実装してみます。

Stripeの以下のドキュメントの記述にそって、Oracle APEXに合わせた実装を行います。

支払いページを作成する

Payment Intentの作成には、以下のREST APIを呼び出します。

カード番号の入力フォームはPayment Elementとして説明されています。

作成したアプリケーションは以下のように動作します。


最後にREST APIを呼び出してPayment Intentを表示しています。実際に決済の成功や失敗を確認するにはWebhookを実装するのが一般的だと思いますが、本記事ではWebhookの作成は取り扱っていません。通常Webhookは、APEXのアプリケーションではなく、ORDSのRESTサービスとして実装します。

以下より実装について説明します。

アプリケーション作成ウィザードを起動し、空のアプリケーションを作成します。名前はStripeとします。

アプリケーションの作成をクリックします。


アプリケーション定義の置換文字列として、公開可能キーとAPIのエンドポイントを設定します。

パブリックキーは置換文字列をSTRIPE_PUBLISHABLE_KEY、置換値としてpk_test_で始まる(テスト用の)公開可能キーを設定します。

APIのエンドポイントは置換文字列としてSTRIPE_ENDPOINT、置換値としてhttps://api.stripe.comを設定します。


ワークスペース・ユーティリティのWeb資格証明を開きます。


Stripeが提供するREST APIに使用するWeb資格証明は、以下の情報より作成します。

StripeのAPIは、ベアラーとしてシークレットキーを渡すことで認証できます。認証タイプにHTTPヘッダーを選択し、資格証明名はAuthorization、資格証明シークレットとして、文字列Bearerで始めて空白で区切り、シークレットキーの値を設定します。

Bearer シークレットキー

Web資格証明の名前はStripe CRED、静的IDはSTRIPE_CREDとして、Web資格証明を作成します。URLに対して有効はhttps://api.stripe.comを設定します。

以上で作成をクリックします。


Web資格証明としてStripe CRED(静的IDはSTRIPE_CRED)が作成されました。


Stripeによるカード情報入力フォームを表示するページを作成します。

ページの作成をクリックします。


空白ページを選択します。


ページ番号を2(ページ・アイテム名に現れるため2とします)、名前をPay、ページ・モードとしてドロワーを選択します。

ページの作成をクリックします。


ページPayが作成されました。

ホーム・ページでは決済金額を入力し、確定ボタンを押します。確定ボタンを押すとStripeが提供するカード情報を入力するフォームを実装したドロワーが開き、そこで決済を実行します。決済を実行すると、ドロワーが閉じます。


ページ・デザイナでホーム・ページを開きます。

金額を入力するページ・アイテムP1_AMOUNTを作成します。

タイプは数値フィールド、ラベルはAmountとします。


決済金額を確定するボタンCONFIRMを作成します。

ラベルはConfirm、外観のホットをオン、テンプレート・オプションのWidthとしてStretchを選択します。動作のアクションはデフォルトのページの送信から変更しません。


作成したPayment Intent IDを保持するページ・アイテムP1_PAYMENT_INTENT_IDとClient Secretを保持するページ・アイテムP1_CLIENT_SECRETを作成します。双方ともタイプは非表示です。

Payment Intent IDはPayment Intentを表示する際に使用し、決済の確定では使用しません。APIリファレンスには、シークレットキーとPayment Intent IDを組み合わせてPayment Intentを取得する、または、公開可能キーとClient Secretを組み合わせてPayment Intentを取得する2通りの手順があるとのことです。Client Secretは決済の確定に使用します。

セッション・ステートのストレージとしてセッションごと(永続)を選択します。決済の確定はPL/SQLで実行します。その際にページ・アイテムに設定されたPayment Intent IDは、ページ遷移の後でも値を維持するようにします。


Payment Intentを表示するリージョンを作成します。

識別のタイトルはPayment Intent、タイプとして動的コンテンツを選択します。

ソースのCLOBを返すPL/SQLファンクション本体として以下を記述します。

ページ・アイテムP1_PAYMENT_INTENT_IDはセッション・ステートとして保持されているため、送信するページ・アイテムへの設定は不要です。


このリージョンをリフレッシュするボタンREFRESHを作成します。

ラベルはRefresh、動作のアクションとして動的アクションで定義を選択します。


ボタンREFRESHの動的アクションを作成します。

識別の名前はonClick REFRESH、タイミングのイベントはボタンのデフォルトであるクリックです。


TRUEアクションとしてリフレッシュを選択します。影響を受ける要素の選択タイプはリージョン、リージョンとしてPayment Intentを選択します。


このページを初期化するボタンCLEARを作成します。

ラベルはClear、動作のアクションはページの送信です。レイアウトの新規行の開始はオフにし、ボタンREFRESHの右隣に配置します。


プロセス・ビューを開き、ボタンを押した時に実行されるプロセスを作成します。

ボタンCONFIRMを押した時にPayment Intentを作成します。

プロセスの識別の名前はCreate Payment Intent、タイプとしてコードを実行を選択します。ソースのPL/SQLコードとして以下を記述します。Payment Intentを作成するための最低限の処理です。


サーバー側の条件のボタン押下時としてCONFIRMを設定します。


ページを初期化するプロセスを作成します。

識別の名前はClear Session State、タイプはセッション・ステートのクリア、設定のタイプとしてClear all Items on the Current Pageを選択します。

サーバー側の条件のボタン押下時としてCLEARを設定します。


ブランチを作成しプロセスの後に実行するように配置します。

識別の名前はOpen Drawer、動作のタイプとしてページまたはURL(リダイレクト)を選択します。

サーバー側の条件のボタン押下時としてCONFIRMを設定します。


ターゲットは、タイプがこのアプリケーションのページ、ページは2です。アイテムの設定として、ページ・アイテムP2_CLIENT_SECRETに&P1_CLIENT_SECRET.の値が渡るようにします。


以上で、ボタンをCONFIRMをクリックするとPayment Intentが作成され、そのClient Secretを(ページ・アイテムP2_CLIENT_SECRETへの)引数としてドロワーが開くようになります。

ページ・デザイナでページPayを開きます。

ページ・プロパティのJavaScriptのファイルURLとして、Stripeが提供しているJavaScriptライブラリを指定します。

https://js.stripe.com/v3/

ファンクションおよびグローバル変数の宣言に以下を記述します。

カード情報の入力フォームを生成しています。


クレジットカード情報を入力するフォームを生成するリージョンを作成します。

Content Bodyの直下にタイプが静的コンテンツのリージョンを作成します。

識別のタイトルはpayment-form、余計な装飾を省くため外観のテンプレートとしてBlank with Attributes (No Grid)を選択します。詳細の静的IDとしてpayment-formを設定します。このリージョンは実施的に以下のDIV要素を生成します。

<div id="payment-form">....</div>

Stripeのチュートリアルではidがpayment-formの要素はFORMです。Oracle APEXが生成したページにFORM要素がすでに含まれているためか、<form id="payment-form">では動作しません。そのため、代わりにDIV要素を作成しています。


リージョンpayment-formにClient Secretを保持するページ・アイテムを作成します。

識別の名前はP2_CLIENT_SECRET、タイプとして非表示を選択します。レイアウトのリージョンとしてpayment-formを選択します。セッション・ステートのストレージはリクエストごと(メモリーのみ)とします。


クレジット・カードの所有者を入力するページ・アイテムを作成します。

識別の名前はP2_HOLDER_NAME、タイプはテキスト・フィールド、ラベルはHolder Nameとします。レイアウトのリージョンとしてpayment-formを選択します。


リージョンpayment-formの子リージョンを作成します。

識別のタイトルはcard-element、タイプは静的コンテンツです。レイアウトの親リージョンとしてpayment-formを指定します。このリージョンも余計な装飾を省くため、外観のテンプレートとしてBlank with Attributes (No Grid)を選びます。詳細の静的IDとしてcard-elementを設定します。


上にあるカードの所有者を入力するページ・アイテムと下にあるボタンが、カード情報を入力するリージョンに近過ぎたため、テンプレート・オプションのTop MarginとBottom MarginをLargeに変更しています。


エラーを表示するリージョンを作成します。

識別のタイトルはcard-errors、タイプは静的コンテンツです。レイアウトの親リージョンとしてpayment-formを指定します。このリージョンも余計な装飾を省くため、外観のテンプレートとしてBlank with Attributes (No Grid)を選びます。詳細の静的IDとしてcard-errorsを設定します。


決済を確定するボタンPAYを作成します。

ラベルはPay、レイアウトのリージョンとしてpayment-form、外観のホットをオンにし、テンプレート・オプションのWidthにStretchを選択します。動作のアクションとして動的アクションで定義を選択します。


ボタンPAYに動的アクションを作成します。

識別の名前はonClick PAYとします。タイミングのイベントはボタンのデフォルトであるクリックです。


TRUEアクションとしてJavaScriptコードの実行を選択し、設定のコードに以下を記述します。

カード決済が確定するとドロワーを閉じます。


以上でStripeのPayment Intentを使ったの決済サービスの実装は完了です。アプリケーションを実行すると、この記事の先頭のGIF動画のように動作します。

Oracle APEXのアプリケーション作成の参考になれば幸いです。

完