Client 側での即時確認処理

概要

Mobage JS SDKのアイテム購入のフローでは、 コインによるアイテム決済 にて先にモバコインが引き落とされ、アイテムの受注処理 はその後に行われます。このため、モバコインが引き落とされた直後にブラウザがクラッシュしたり、Clientからのアイテム付与リクエストが失敗すると、コインは引き落とされたのにアイテムがまだ付与されていないという状態になります。

これを防ぐための方法として、Client 側で購入処理の確認をし、改めてアイテム付与をできるだけ早く行うための枠組みが、 Client 側での即時確認処理 です。
アイテム購入フローの途中でブラウザが落ちてしまった場合、別の画面に遷移してしまった場合などで、改めてアプリケーションに戻って来た際に、即座に未処理のアイテム付与が行われていないものを確認して再度アイテム付与を行う機能を開発していきます。
 

Client 側での即時確認処理と Client 側での非同期確認処理は競合しますので、同時に使用しないようにしてください。
Mobage JS SDK 3.3.1 より使用可能な API を使用します。

 

作成するファイル一覧

このチュートリアルで作成するファイルは下記になります。

ファイル名

概要

config.php

各種設定値をまとめます

immediate_confirmation.php

Client側での画面の UI を実装しています

immediate_confirmation.js

Client側での確認処理を行います

confirmation.php

Clientからの通知によりトランザクションの状態を確認し、場合によってアイテム付与をします

bank_debit_get.php

Bank Debit API をつかって決済トランザクションを確認します

 

なお本文中で定義するテーブル定義はこのチュートリアルの為のサンプルなので、参考程度に留めて下さい。

 

チュートリアルをはじめる前に

このチュートリアルは、以下のチュートリアルを終わらせている前提で進めます。
以下のチュートリアルでファイル作成していない場合は、先にそちらを完成させましょう。

サンプルコードのダウンロード

Github からサンプルコードを clone できます。

開発のステップ

Client 側での即時確認処理を実現するために、大きく以下の4ステップで進めます。

  1. Client にて 未処理の Transaction を確認する (シーケンス図500-505)
  2. Game Server で Bank Debit API を用いて 決済 Transaction を確認する (シーケンス図506-509)
  3. Game Server でアイテム付与/ Order データの更新などを実施する (シーケンス図510-514) ※
  4. Game Server から Client へのレスポンス (シーケンス図515-518)
※このチュートリアルでは、アイテム付与管理を行うテーブルを Order DB 、Order DB 上のトランザクションを表すデータを Order データ として解説を進めます。

 

なお、これらのステップに対応した Client 側での非同期確認処理のシーケンス図は下記になります。

 

Client にて 未処理の Transaction を確認する

アイテム購入処理を始める際、ユーザーが mobage.ui.open メソッドにて payment サービスを呼び出すと、下記のような画面が表示されつつ Client の localStorage に Transaction データ が保存されます。
 

Transaction データは下記のように Client の localStorage 内で、 payment_backlogの一要素として保存されます。

この localStorage に保存された Transaction データは、アイテム購入の処理が下記のような理由で中断されても、残っていることがあります。(localStorageなので消えていることもあります。)

  • 購入フローの途中で間違えてブラウザを閉じてしまった
  • 購入フローの途中で通信状態が悪化して処理できなかった

localStorage に 未処理の Transaction データが残った状態で、ユーザーがアプリケーションに戻って来た場合、未処理の Transaction を確認して Game Server に確認リクエストを送信するプログラムを作成します。
  

Client の localStorage に残っている 未処理の Transaction を確認する

mobage.bank.getPaymentAllTransactionIds() メソッドで、localStorage に残っている未処理の Transaction データを直接確認できます。
mobage.bank.getPaymentAllTransactionIds() メソッドの呼び出しは、Mobage Connect へログイン、かつゲームをインストールしている状態で実施します。
ここでは下記のように、ユーザーがアプリケーションに戻って来た際に未処理の Transaction を確認するように実装します。

mobage-jssdk-sample-payment/client_immediate/immediate_confirmation.js

 

未処理の Transaction が残っていたら、Game Server に確認リクエストを送信する

mobage.bank.getPaymentAllTransactionIds() メソッドにより、localStorage 内に未処理の Transaction データが残っていることが確認できると、戻り値として配列の形式で複数の TransactionId が入ります。以下のように Game Server に TransactionId を送ります。

mobage-jssdk-sample-payment/client_immediate/immediate_confirmation.js

TOC

Game Server で Bank Debit API を用いて 決済 Transaction を確認する

Client の localStorage に残っていた未処理の Transaction を Game Server で受け取り、モバコインが既に引き落とされているか Bank Debit API を使って確認するプログラムを作成します。

 

リクエストパラメタから TransactionId を抽出する

Client から送られたリクエストに含まれる TransactionId を抽出して処理します。

mobage-jssdk-sample-payment/client_immediate/confirmation.php

セッションからユーザーのAccess Token を取得する

このチュートリアルではMobage Connect へのログインチュートリアルにて、Game Server のセッションに Access Token を保存しました。Bank Debit API の呼び出しには Access Token が必要となるので、セッションから Access Token を取得します。

mobage-jssdk-sample-payment/client_immediate/confirmation.php

 

TransactionId と Access Token を利用して Bank Debit API を呼び出す

Client の localStorage に残っていた未処理の Transaction が、既にPlatformにてモバコイン引き落としが行われた Transaction であるか確認するため、Bank Debit API を利用します。Bank Debit API の呼び出しを行うにあたり、OAuth 2.0 Bearer Token を利用します。
まず、OAuth 2.0 の Bearer Token として、先ほど取得した Access Token を利用して、Bank Debit API を呼び出す準備をします。

mobage-jssdk-sample-payment/bank_api_connectors/bank_debit_get.php

 
次に、curl を使って Bank Debit API を呼び出します。 Bank Debit API からのレスポンスから、決済 Transaction を取得します。

mobage-jssdk-sample-login/bank_api_connectors/bank_debit_get.php

 
 

Bank Debit API のレスポンスから Transaction の state を取得する

Bank Debit API から受け取ったレスポンスにより、該当 Transaction がモバコイン引き落とし済みか確認します。
モバコイン引き落とし済みかどうかは、state 値の状態を見ることで確認できるため、state 値を抽出します。

mobage-jssdk-sample-payment/client_immediate/confirmation.php

TOC

Game Server でアイテム付与/ Order データの更新などを実施する

Client の localStorage に残っていた未処理の Transaction が、「モバコイン引き落とされているがアイテム付与されていない」という状態であるか確認するためには、「モバコインの決済状態」と「アイテムの付与状態」の2つを確認する必要があります。これらを確認して、必要な場合にアイテムを付与するプログラムを作成します。
 

「モバコインの決済状態」を確認する

Bank Debit API から受け取ったレスポンス(決済トランザクション)内の state 値を確認することで、モバコインが引き落とされているか判断します。
 
この決済トランザクションの state 値は以下のように分けられます。

state

状態

処理途中か処理完了か

authorized

まだコインを引き落としていない

処理途中

error

エラーによりコインを引き落とさない

処理完了

canceled

コインの引き落としはキャンセル済み

処理完了

closed

コインを引き落とし済み

処理完了

 

「アイテムの付与状態」を確認する

Game Server ではアイテム付与状態の管理も行っているので、「アイテム付与状態管理テーブル」を確認します。
ここでは、アイテム付与状態の管理を行うテーブルを Order DB として下記のように定義しています。

なお、この Order DB では、下記のように order_state という値でアイテム付与の状態を管理しています。

order_state

状態

処理途中か処理完了か

authorized

アイテム未付与

処理途中

error

エラーによりアイテム付与しない

処理完了

canceled

アイテム付与処理はキャンセル済み

処理完了

closed

アイテム付与済み

処理完了

上記に定義した Order DB は、あくまでこのチュートリアル用のサンプルであり、一例です。実際にゲームに実装する際には、ゲームの要件に従ったテーブルを定義してください。

 
決済トランザクションと、この Order DB を合わせて確認することで、「モバコインは引き落とされているがアイテム付与されていない」という状態のユーザーにできるだけ早くアイテムを付与します。 
 

Order データを排他制御する

「アイテムの付与状態」を確認する上で忘れずに対応したいのが、「アイテムの付与状態」を確認して「アイテム付与される」まで、他のプロセスによって邪魔されない(アイテムを付与されない)ことを担保することです。
ここでは、処理が始まってアイテム付与が終わるまで他のプロセスによって邪魔されないように、Order データを排他制御する手法を採用します。
排他制御を取り入れることで、同じようなタイミングで複数プロセスからリクエストがあった際に、アイテムの間違った重複付与を防ぐことができます。
また、他プロセスに直前に Order データを更新されていることも考慮して、排他制御で取得した最新の Order データの確認も行います。
すでにアイテムが付与されている場合は、order_stateclosed になっています。この場合、Platformにアイテム付与成功のレスポンス(200 OK)を返します。
このチュートリアルではMySQLのストレージエンジンInnoDBを利用して、行レベルでの排他制御を行い、最新の Order データを確認します。

mobage-jssdk-sample-payment/client_immediate/confirmation.php

 

「モバコインの決済状態」と「アイテムの付与状態」の比較と対応

「モバコインの決済状態」を表す決済トランザクションの state 値と、「アイテムの付与状態」を表す Order データの order_state 値を比較し、それぞれの状況に応じてアイテム付与などの対応を行います。
 

決済トランザクション と Order データの state 値が一致する

決済トランザクションの state 値 と、Order データの state 値が一致するパターンは、以下のようになります。

決済トランザクションの state 値

Order 情報の order_state 値

説明

closed

closed

モバコイン消費済みで、アイテムも付与済み

canceled

canceled

モバコイン消費キャンセル/失効済みで、アイテム付与処理もキャンセル/失効済み

error

error

モバコイン消費がエラーとなり、アイテム付与処理もエラーと状態変更済み

authorized

authorized

モバコイン消費が未処理、アイテム付与も未処理

上記の全てのパターンが、Order データの変更も、アイテム付与も行う必要がないものなので、該当する決済トランザクションについて処理はしません。排他制御を開放して Client にレスポンスを返します。

 

決済トランザクションの state 値が 'canceled' もしくは 'error' である

決済トランザクションの state 値が 'canceled' もしくは 'error' で、Order データの order_state 値と一致しない場合は、モバコイン消費がキャンセル/失効済み、もしくはエラーで終了している状態なので、ゲーム側でのアイテム付与処理は不要となります。

決済トランザクションの state 値が 'closed' である

決済トランザクションの state 値が 'closed' で、Order データの order_state 値と一致しない場合は、「モバコインは引き落とされているがアイテム付与されていない」という状態なので、アイテム付与処理を実行します。
このチュートリアルでは、ユーザのアイテムを管理するテーブルにレコードを追加/更新することでアイテムを付与します。

以下がこのチュートリアルで定義しているユーザのアイテム管理テーブルです。

上記に定義したアイテム管理テーブルは、あくまでこのチュートリアル用のサンプルであり、一例です。実際にゲームに実装する際には、ゲームの要件に従ったテーブルを定義してください。

 
 
上記のテーブル定義に従ってユーザーへのアイテム付与処理を実行し、Order データも更新することで、該当トランザクションの処理を終了させます。また、Order データの排他制御も開放します。

mobage-jssdk-sample-payment/client_immediate/confirmation.php

Game Server から Client へのレスポンス

Clientからのリクエストに対して、以下の場合に 成功レスポンス を返します。

  • 既にアイテムを付与していた場合
  • ユーザーへのアイテム付与が成功した場合

また、以下の場合には 失敗レスポンス を返します。

  • Clientからのリクエストに異常があった場合
  • Game Server 側の内部処理で異常があった場合

Client への成功レスポンス

ユーザへのアイテム付与が完了している場合、成功レスポンスを返します。
成功レスポンスの http status code は 200 OK とします。

Client への失敗レスポンス

ゲームサーバの処理で異常があった場合など、Platform へ失敗レスポンスを返します。
失敗レスポンスの http status code は 4xx もしくは 5xx などの適切なレスポンスを返します。

TOC

Client にて 対象 Transaction を監視から除外する

Callback 関数を利用して Game Server からのレスポンスを受け取ります。 Game Server からのレスポンスは、アイテム付与処理が行われた場合やアイテム付与処理を行う必要がない場合に http status 200 OK となるように実装しました。Clientが http status 200 OK を受け取った場合、Game Server へのリクエスト再送処理が不要になったと判断できます。このような場合、mobage.bank.clearPaymentBacklog() メソッドを呼び出すことで、該当 Transaction が処理済みであることをJavaScript SDKに伝えます。
 

mobage.bank.clearPaymentBacklog()メソッドの呼び出し

以下のように mobage.bank.clearPaymentBacklog() メソッドを呼び出し、該当 Transaction が処理済みであることを JavaScript SDK に伝えます。

mobage-jssdk-sample-payment/client_immediate/immediate_confirmation.js

JavaScript SDK の mobage.bank.getPaymentAllTransactionIds() メソッドは、未処理の Transaction データが残る限り、 TransactionId を返します。ユーザーへのアイテム未付与状態を解消し、mobage.bank.clearPaymentBacklog() メソッドを利用して、処理が完了した localStorage 内の Transaction を全てを削除してください

Client 側での即時確認処理は、場合によって実行されないことがあります。( localStorage から Transaction データが意図せず消された場合など)
この確認処理が実施されなくてもユーザーに損失が出ないように、バッチを用いた確認処理 を併用するようにしてください。

TOC
 

動作確認

 
では、開発したプログラムを下記のように Game Server に配置します。

ファイル名

URL

config.php

http://localhost/mobage-jssdk-sample-payment/config.php

immediate_confirmation.php

http://localhost/mobage-jssdk-sample-payment/client_immediate/immediate_confirmation.php

immediate_confirmation.js

http://localhost/mobage-jssdk-sample-payment/client_immediate/immediate_confirmation.js

confirmation.php

http://localhost/mobage-jssdk-sample-payment/client_immediate/confirmation.php

bank_debit_get.php

http://localhost/mobage-jssdk-sample-payment/bank_api_connectors/bank_debit_get.php

なお、アイテムを購入するプログラムは、下記のチュートリアルで先に開発しておきます。

Client 側での即時確認処理の動作確認を行うため、アイテムを購入する処理が実装されたプログラムを一部編集します。
(上記チュートリアルで開発した purchase.js を編集します)
下記のように、「モバコインが引き落とされ、Game Server にアイテム付与リクエストを送る」処理をコメントアウトします。

また、アイテム購入を行う前の Game Server 側のテーブルを以下のように確認します。

これらのコマンド結果から、ユーザーが1つもアイテムを保持していないことと、Order DB にデータが1つも無いことを確認できます。

では、「Game Server へのアイテム付与リクエスト送信処理」のコメントアウトがされた状態で、アイテム購入を進めます。

「Purchase」のボタンを押下すると、以下の画面が表示されます。

この画面が表示された時点で、Game Server の Order DB には既にレコードが追加されているので確認します。
この時点ではまだアイテム付与されていないので、Order DB の order_state は authorized(アイテム未付与:決済処理途中)となっています。

次に、アイテム購入を行って下記の画面を表示させます。

アイテム購入を行うと、モバコインは引き落とされているのにアイテムが付与されていない状態になります。

Game Server を確認すると、下記の状態のままになっています。

この状態で、 Client 側の localStorage を確認する下記ページを表示します。

http://localhost/mobage-jssdk-sample-payment/client_immediate/immediate_confirmation.php
 

このページを開くと、Client 側の localStorage が確認され、未処理の Transaction について、 Client から Game Server にリクエストが送られます。
 
Game Server では、 Client から通知が来たら分かるようにログをはいておきます。

ログを監視していると、すぐに下記のような表示が出て、Client からの通知が来たことが分かります。

Client からの通知をきっかけに、アイテム付与が行われたか、Order DB が更新されたか確認します。

上記のように、アイテム付与も行われ、 Order DB も正常に更新されたことを確認できました。

開発したコード

このチュートリアルで開発したコードは Github から clone できます。

 

更新履歴

  • 2016/03/25
    • JS SDK 3.3.1 公開に伴い、新規作成

 

PREVIOUS

Client 側での非同期確認処理

NEXT

バッチ処理での確認