アプリ内課金(IAP)v2.0ウェブアプリの例
アプリ内課金(IAP)v2.0ウェブアプリの例
アプリ内課金(IAP)サンプルウェブアプリは以下からダウンロード可能です。
サンプルにアクセスするには、ローカルコンピューターでHTTPサーバーを起動します。Pythonがインストールされている場合は、Python HTTPサーバーを使用できます。
- ダウンロードファイルを解凍します。
- ターミナルウィンドウで、新しく解凍されたフォルダ(IAPv2-web-app-sample)に移動します。
python -m SimpleHTTPServer
と入力してPythonサーバーを起動します。
追加のサーバーオプションについては、Mozillaの記事を参照してください。
サンプルを実行するには、次の手順に従います。
- ブラウザでhttp://localhost:8000を開きます。
- ページの指示に従ってアプリを使用します。
サンプルの説明
サンプルのindex.htmlファイルには、次のコンテンツが含まれています。
- Amazon Servicesライブラリとテストライブラリを組み込むscriptタグ。Amazon ServicesライブラリにはIAP v2.0の機能があります。
buttonclicker.js
ファイルを組み込むscriptタグ。- 3つのボタンを表示するHTML。ボタンアクションには、ボタンクリッカーのJavaScriptファイルによってメソッドがバインドされます。
ボタンクリッカーのJavaScriptファイルの内容は次のとおりです。
// シンプルなモデルビューコントローラーのセットアップ。
// onPurchaseResponseはいつでも呼び出される可能性が
// ある点を考慮して処理を行います。
//
// APIの使用時には、レスポンスが発生するタイミングは予測できない
// ことを理解しておく必要があります。たとえば、レシートの配信前に
// ウェブアプリが終了されることがあります。この場合は、
// アプリが次に実行されると、APIの初期化時に
// レシートが配信されます。
// モデルデータ
var state = {
clicksLeft: 10,
activeButton: "",
hasRedButton: false,
hasGreenButton: false,
hasBlueButton: false,
lastPurchaseCheckTime: null
}
// モデルに基づいてビュー(HTML)を設定します
function refreshPageState() {
$("#clicksLeft").text(state.clicksLeft);
var button = $("#theButton");
var redButton = $("#redButton");
var greenButton = $("#greenButton");
var blueButton = $("#blueButton");
setClass(redButton, "locked", !state.hasRedButton);
setClass(greenButton, "locked", !state.hasGreenButton);
setClass(blueButton, "locked", !state.hasBlueButton);
setClass(redButton, "active", state.activeButton == "red");
setClass(greenButton, "active", state.activeButton == "green");
setClass(blueButton, "active", state.activeButton == "blue");
if (state.activeButton != "") {
button.css("background-color", state.activeButton);
} else {
button.css("background-color", "gray");
}
persistPageState();
}
// アプリの次回実行時に前回実行時と同じ状態が維持されるように、
// localStorageに状態を保存します。特に、
// getPurchaseUpdatesに渡されるlastPurchaseCheckTimeなどの
// IAPステータスを保存することが重要です。
function persistPageState() {
localStorage.setItem("state", JSON.stringify(state));
}
// localStorageから状態を復元します
function loadPageState() {
if ("state" in localStorage) {
// これが初めての実行である場合は、事前に設定した
// デフォルト値が使用されます。
state = JSON.parse(localStorage.getItem("state"));
}
}
function setClass(element, className, condition) {
if (condition) {
element.addClass(className);
} else {
element.removeClass(className);
}
}
// コントローラー
// 消費型アイテムを処理します
function buttonPressed() {
if (state.clicksLeft > 0) {
state.clicksLeft--;
} else {
buyClicks();
}
refreshPageState();
}
// 非消費型アイテムを処理します
function redButtonPressed() {
if (state.hasRedButton) {
state.activeButton = "red";
} else {
buyButton("sample.redbutton");
}
refreshPageState();
}
// 非消費型アイテムを処理します
function greenButtonPressed() {
if (state.hasGreenButton) {
state.activeButton = "green";
} else {
buyButton("sample.greenbutton");
}
refreshPageState();
}
// 定期購入型アイテムを処理します
function blueButtonPressed() {
if (state.hasBlueButton) {
state.activeButton = "blue";
} else {
// 特定の(期限付きの)定期購入型アイテムを購入する必要があります
buyButton("sample.bluebutton.subscription.1mo");
}
refreshPageState();
}
function buyClicks() {
if (window.AmazonIapV2 == null) {
alert("クリックの残数がなくなりました。Amazonアプリ内課金はAmazonアプリストアのアプリでのみ動作します。");
} else if (confirm("クリックを購入しますか?")) {
//window.AmazonIapV2.purchase('sample.clicks');
var requestOptions = {
sku: 'sample.clicks'
};
window.AmazonIapV2.purchase(
function(operationResponse) {
console.debug(operationResponse.requestId);
},
function(errorResponse) {
console.debug(errorResponse);
},
[requestOptions]
);
}
}
function buyButton(buttonName) {
if (window.AmazonIapV2 == null) {
alert("このボタンは購入できません。Amazonアプリ内課金はAmazonアプリストアのアプリでのみ動作します。");
} else {
//window.AmazonIapV2.purchase(buttonName);
var requestOptions = {
sku: buttonName
};
window.AmazonIapV2.purchase(
function(operationResponse) {
console.debug(operationResponse.requestId);
},
function(errorResponse) {
console.debug(errorResponse);
},
[requestOptions]
);
}
}
// コールバックから呼び出されるハンドラー関数
// purchaseItemではレシートを1つ含む購入レスポンスが発生します
function onPurchaseResponse(e) {
var response = e.response;
if (response.status === 'SUCCESSFUL') {
handleReceipt(response.purchaseReceipt);
} else if (response.status === 'ALREADY_PURCHASED') {
// 何らかの理由によりサーバーと同期されていません。最初から
// 更新します。
var requestOptions = {
reset: true
};
window.AmazonIapV2.getPurchaseUpdates(
function(operationResponse) {
// オペレーションレスポンスを処理します
var requestId = operationResponse.requestId;
console.debug(requestId);
},
function(errorResponse) {
// エラーレスポンスを処理します
console.debug(errorResponse);
},
[requestOptions]
);
} else if (response.status === 'FAILED') {
alert('購入リクエストが中断されました。後でもう一度お試しください。');
} else if (response.status === 'INVALID_SKU') {
alert('SKUが無効です。SKUの構成を確認してください。');
}
refreshPageState();
}
// getPurchaseUpdatesではレシートの配列が返されます
function onPurchaseUpdatesResponse(e) {
var response = e.response;
for (var i = 0; i < response.receipts.length; i++) {
handleReceipt(response.receipts[i]);
}
state.lastPurchaseCheckTime = response.offset;
refreshPageState();
if (response.hasMore) {
// アップデートが多すぎてこのレスポンスで送信されない
// ものがあった場合、確実に残りのアップデートを取得
// します。
var requestOptions = {
reset: false
};
window.AmazonIapV2.getPurchaseUpdates(
function(operationResponse) {
// オペレーションレスポンスを処理します
var requestId = operationResponse.requestId;
console.debug(requestId);
},
function(errorResponse) {
// エラーレスポンスを処理します
console.debug(errorResponse);
},
[requestOptions]
);
}
}
// どちらの場合もレシートの内容は同じように処理します
function handleReceipt(receipt) {
if (receipt.sku == "sample.redbutton") {
// 非消費型アイテム
state.hasRedButton = true;
} else if (receipt.sku == "sample.greenbutton") {
// 非消費型アイテム
state.hasGreenButton = true;
} else if (receipt.sku.substring(0, 30) == "sample.bluebutton.subscription") {
// 定期購入型アイテムでは親のIDが返されることがあるため、
// 親のIDと比較します
if (receipt.cancelDate == null) {
// 有効な期間中はcancelDateがnullになります
state.hasBlueButton = true;
}
} else if (receipt.sku == "sample.clicks") {
// 消費型アイテム
state.clicksLeft += 10;
}
//まだアイテム付与が完了していない場合は、レシートのアイテムを付与します。
//付与済みのアイテムをトラッキングできるようにreceiptIdを保存してから、
//receiptIdとFULFILLEDステータスを指定してnotifyFulfillment()を呼び出します。
//アイテムが以前のゲーム状態に対応するものであった場合や、ゲームでサポートされていない場合
//など、アイテム付与を完了できないときは、次の呼び出しを行います。
//
notifyFulfillment(receipt.receiptId);
}
/**
* @function notifyFulfillment
* @description NotifyFulfillmentは、購入アイテムの付与完了についてAmazonに通知します。
* @param {String} receiptId レシートID
*/
function notifyFulfillment(receiptId) {
//fulfillmentResultに指定できる値はFULFILLEDまたはUNAVAILABLEです
var requestOptions = {
'receiptId': receiptId,
'fulfillmentResult': 'FULFILLED'
};
window.AmazonIapV2.notifyFulfillment(
function(operationResponse) {
// オペレーションレスポンスを処理します
console.debug(operationResponse);
},
function(errorResponse) {
// エラーレスポンスを処理します
console.debug(errorResponse);
},
[requestOptions]
);
}
// セットアップ
function initialize() {
loadPageState();
amzn_wa.enableApiTester(amzn_wa_tester);
refreshPageState();
// ボタンクリックハンドラーをセットアップします
$("#theButton").click(function() { buttonPressed(); });
$("#redButton").click(function() { redButtonPressed(); });
$("#greenButton").click(function() { greenButtonPressed(); });
$("#blueButton").click(function() { blueButtonPressed(); });
document.addEventListener('amazonPlatformReady', function() {
// IAP APIを呼び出せるようにします
if (window.AmazonIapV2 === null) {
console.debug('Amazonアプリ内課金はAmazonアプリストアのアプリでのみ動作します');
} else {
window.AmazonIapV2.addListener('getUserDataResponse', function(resp) {});
window.AmazonIapV2.addListener('getProductDataResponse', function(data) {});
window.AmazonIapV2.addListener('purchaseResponse', this.onPurchaseResponse);
window.AmazonIapV2.addListener('getPurchaseUpdatesResponse', this.onPurchaseUpdatesResponse);
}
}.bind(this));
}
$(function() {
initialize();
});