作成したAPEXアプリケーションは以下のように動作します。
今回の紹介する内容はPAY.JPによるカード決済を実施するために、Oracle APEX側に実装すべき最低限のコーディングになります。
Webブラウザのフロント側では、カード情報を入力するエレメントの生成および支払いAPIの呼び出しに必要なトークンの生成を実装します。
フロント側の処理はpayjp.js v2リファレンスを参照して実装します。
生成したトークンと金額を受け取って、PAY.JPの支払いAPI(Charge API)を呼び出します。このREST APIは以下のリファレンスを参照して実装します。
アプリケーション作成ウィザードを起動し、空のアプリケーションを作成します。名前はPAY.JP Chargesとします。PAY.JPによるカード決済は、すべてホーム・ページに実装します。
アプリケーションの作成をクリックします。
アプリケーション定義の置換文字列として、テスト公開鍵と支払いAPIのエンドポイントを設定します。
テスト公開鍵は置換文字列をPAYJP_PUBLIC_KEY、置換値としてpk_test_で始まるテスト公開鍵を設定します。
APIのエンドポイントは置換文字列としてPAYJP_ENDPOINT、置換値としてhttps://api.pay.jpを設定します。
ワークスペース・ユーティリティのWeb資格証明を開きます。
作成済みのWeb資格証明の一覧が表示されます。その画面で作成をクリックし、新たなWeb資格証明の作成を始めます。
PAY.JPが提供するREST APIに使用するWeb資格証明は、以下の情報で作成します。
PAY.JPのAPIは、テスト秘密鍵(または本番秘密鍵)をユーザー名としたBasic認証により保護されています。Oracle APEXのWeb資格認証には認証タイプとして基本認証(Basic認証)を選択できますが、この場合、秘匿して保持されるのはパスワードに限られユーザー名は誰でも参照できます。
PAY.JPのテスト秘密鍵(もちろん本番秘密鍵も)は秘匿が必須なので、基本認証の代わりに認証タイプとしてHTTPヘッダーを選択します。資格証明名はAuthorization、資格証明シークレットとして、文字列Basicで初めて空白で区切り、テスト秘密鍵の末尾に':'(コロン)をつけてBase64でエンコードした値を設定します。
Linuxなどのコマンドラインでは、以下のような処理によって資格証明シークレットを生成できます。
echo Basic `echo sk_test_xxxxxxxxxxxxxxxxxxxxxxx: | base64`
% echo Basic `echo sk_test_xxxxxxxxxxxxxxxxxxxxxxx: | base64`
Basic cGtxxXafea*****aeaqf***********k6Cg==
%
Web資格証明の名前はPAY.JP Test CRED、静的IDはPAYJP_TEST_CREDとして、Web資格証明を作成します。URLに対して有効はhttps://api.pay.jpを設定します。
Web資格証明はアプリケーションのエクスポートから除外されるため、秘密鍵が誤って流出することを防ぐことができます。
以上で作成をクリックします。
Web資格証明としてPAY.JP Test CRED(静的IDはPAYJP_TEST_CRED)が作成されました。
ホーム・ページにいくつかのコンポーネントを配置します。
最初に決済する金額を入力するページ・アイテムを作成します。
ページ・アイテムの識別の名前はP1_AMOUNT、タイプとして数値フィールドを選択します。ラベルはAmountとします。
カード情報の上下にあるページ・アイテムとボタンとの間隔が狭いので、少し広げます。テンプレート・オプションを開き、詳細のTop MarginとBottom MarginをLargeに変更します。
支払いを実行するボタンを作成します。
識別のボタン名はPAY、ラベルはPayとします。外観のホットをオンにします。
動作のアクションとして動的アクションで定義を選択します。詳細の静的IDにpay-buttonを設定します。以下の画面ショットでは動的アクションが作成されていますが、これは後で作成します。
支払いAPIのレスポンスをそのまま表示するページ・アイテムを作成します。
識別の名前はP1_RESPONSE、タイプとしてテキスト領域を選択します。ラベルはResponseとします。
ページへ配置するコンポーネントは作成できました。これより、支払い処理を実装します。
ページ・プロパティのJavaScriptのファイルURLとして以下を設定します。
https://js.pay.jp/v2/pay.js
ファンクションおよびグローバル変数の宣言として以下を記述します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
document.getElementById("pay-button").disabled = "disabled"; | |
const payjp = Payjp('&PAYJP_PUBLIC_KEY.'); | |
const elements = payjp.elements(); | |
const cardElement = elements.create('card', {style: {base: {color: 'black'}}}); | |
cardElement.mount('#card-element'); | |
cardElement.on('change', (event) => { | |
console.log(event); | |
if (event.complete === true) { | |
document.getElementById("pay-button").disabled = null; | |
} else { | |
document.getElementById("pay-button").disabled = "disabled"; | |
} | |
if (event.error !== null) { | |
apex.message.clearErrors(); | |
apex.message.showErrors( | |
{ | |
type: "error", | |
location: "inline", | |
pageItem: "card-element", | |
message: event.error.message, | |
unsafe: false | |
} | |
); | |
} else { | |
let elem = document.getElementById("card-element_error_placeholder"); | |
if (elem !== null) { | |
elem.remove(); | |
} | |
// apex.message.clearErrors(); | |
}; | |
}); |
ボタンPAYに動的アクションを作成します。
動的アクションの識別の名前はonClick Pay、タイミングのイベントはボタンのデフォルトであるクリックです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
payjp.createToken(cardElement).then( | |
(response) => { | |
if (response.error) { | |
apex.message.showErrors( | |
{ | |
type: "error", | |
location: "page", | |
message: "Page error has occurred!", | |
unsafe: false | |
} | |
); | |
} else { | |
apex.server.process( | |
"CHARGE", | |
{ | |
x01: response.id, | |
pageItems: [ "P1_AMOUNT" ], | |
}, | |
{ | |
success: (data) => { | |
$s("P1_RESPONSE", JSON.stringify(data)); | |
}, | |
error: (jqXHR, textStatus, errorThrown) => { | |
console.log(textStatus); | |
} | |
} | |
) | |
} | |
} | |
); |
最初にカード情報からトークンを生成し、そのトークンと金額を引数として、PAY.JPの支払いAPIを呼び出すAjaxコールバックを呼び出します。
PAY.JPの支払いAPIの呼び出しはAjaxコールバックより行います。
AjaxコールバックとしてCHARGEを作成し、以下のコードを記述します。支払いAPIの仕様に従ってパラメータを渡し、/v1/chagesを呼び出しています。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare | |
l_card varchar2(128); | |
l_response clob; | |
e_charges_failed exception; | |
begin | |
l_card := apex_application.g_x01; | |
apex_web_service.set_request_headers('Content-Type','application/x-www-form-urlencoded'); | |
l_response := apex_web_service.make_rest_request( | |
p_url => :PAYJP_ENDPOINT || '/v1/charges' | |
,p_http_method => 'POST' | |
,p_parm_name => apex_string.string_to_table('card:amount:currency') | |
,p_parm_value => apex_string.string_to_table(l_card || ':' || :P1_AMOUNT || ':jpy') | |
,p_credential_static_id => 'PAYJP_TEST_CRED' | |
); | |
if apex_web_service.g_status_code <> 200 then | |
apex_debug.info(l_response); | |
raise e_charges_failed; | |
end if; | |
htp.p(l_response); | |
end; |
以上でPAY.JPの支払いAPIを呼び出すサンプルは完成です。アプリケーションを実行すると、この記事の先頭のGIF動画のように動作します。
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完