Java tutorial
package com.ubiLive.GameCloud.payment; import java.util.HashMap; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.Window; import org.json.JSONException; import org.json.JSONObject; import com.ubiLive.GameCloud.CloudGamePlayer; import com.ubiLive.GameCloud.Constants; import com.ubiLive.GameCloud.DebugLog; import com.ubiLive.GameCloud.Browser.WebBrowser; import com.ubiLive.GameCloud.googlepurchaseutil.IabHelper; import com.ubiLive.GameCloud.googlepurchaseutil.IabResult; import com.ubiLive.GameCloud.googlepurchaseutil.Inventory; import com.ubiLive.GameCloud.googlepurchaseutil.Purchase; /** * This activity performs the purchase of a new level * At first we access the server to get the available In App items - each In App item correlates to a game level; * Then we go through the In App items and find the level that the user is about to purchase. * Lastly, we get the offer for this level and perform the purchase. */ public class GoogleBillingActivity extends Activity { protected final static String TAG = GoogleBillingActivity.class.getName(); private IabHelper mHelper; private String mJsonData; private String mProductIdStr; // (arbitrary) request code for the purchase flow static final int RC_REQUEST = 10001; private HashMap<String, GooglePurchaseInfo> mGooglePurchaseMap = new HashMap<String, GooglePurchaseInfo>(); private GooglePurchaseInfo mGooglePurchaseInfo; public static String mStrId;//session ID for the server requestion -> client response (each times) private class GooglePurchaseInfo { public String idStr; public String packageNameStr; public String productIdStr; public String developerPayloadStr; } /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { /*refer to * Webview client google play in-app purchase spec * http://wiki.ubitus.net/pages/viewpage.action?pageId=32640257 * { * "id": "zkvkjxklrwekrejw" * "type": "set", * "google": { * "packageName": "devils", * "productId": "product_id", * "purchaseType": "inapp", * "developerPayload": "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ" * } * } */ String base64EncodedPublicKey = "DUMMY_BILLING_PUBLICKEY"; super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); Bundle bundleData = getIntent().getExtras(); if (CloudGamePlayer.sWebBrowser.getBillingStatus() == Constants.BILLING_STATUS_START) { DebugLog.d(TAG, "GoogleBillingActivity.onCreate() line50"); //finish(); return; } mJsonData = bundleData.getString("jsonData"); DebugLog.d(TAG, "BillingActivity.onCreate() mJsonData=" + mJsonData); // compute your public key and store it in base64EncodedPublicKey mHelper = new IabHelper(this, base64EncodedPublicKey); JSONObject json; try { json = new JSONObject(mJsonData); mStrId = json.getString("id"); GooglePurchaseInfo googlePurchaseInfo = new GooglePurchaseInfo(); googlePurchaseInfo.idStr = json.optString("id"); googlePurchaseInfo.packageNameStr = json.optString("packageName"); googlePurchaseInfo.productIdStr = json.optString("productId"); googlePurchaseInfo.developerPayloadStr = json.optString("developerPayload"); mGooglePurchaseMap.put(googlePurchaseInfo.productIdStr, googlePurchaseInfo); mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { public void onIabSetupFinished(final IabResult result) { DebugLog.d(TAG, "Setup finished."); if (!result.isSuccess()) { // Oh noes, there was a problem. // complain("Problem setting up in-app billing: " + result); return; } // Have we been disposed of in the meantime? If so, quit. if (mHelper == null) return; // IAB is fully set up. Now, let's get an inventory of stuff we own. DebugLog.d(TAG, "Setup successful. Querying inventory."); mHelper.queryInventoryAsync(mGotInventoryListener); } }); processGooglePurchase(googlePurchaseInfo.productIdStr); } catch (JSONException e) { // TODO Auto-generated catch block DebugLog.d(TAG, "exception = " + e.getMessage()); finish(); } CloudGamePlayer.sWebBrowser.setBillingStatus(Constants.BILLING_STATUS_START); DebugLog.d(TAG, "GoogleBillingActivity() leave "); } public void onDestroy() { super.onDestroy(); if (mHelper != null) { mHelper.dispose(); mHelper = null; } DebugLog.d(TAG, "GoogleBillingActivity() - shutting down license service"); } // Listener that's called when we finish querying the items and subscriptions we own IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() { public void onQueryInventoryFinished(final IabResult result, final Inventory inventory) { DebugLog.d(TAG, "Query inventory finished."); // Have we been disposed of in the meantime? If so, quit. if (mHelper == null) return; // Is it a failure? if (result.isFailure()) { // complain("Failed to query inventory: " + result); return; } DebugLog.d(TAG, "Query inventory was successful."); /* * Check for items we own. Notice that for each purchase, we check * the developer payload to see if it's correct! See * verifyDeveloperPayload(). */ } }; private void processGooglePurchase(String productIdStr) { mGooglePurchaseInfo = mGooglePurchaseMap.get(productIdStr); String result; DebugLog.d(TAG, "processGooglePurchase() productIdStr = " + productIdStr); if (mGooglePurchaseInfo != null) { // TODO Auto-generated method stub DebugLog.d(TAG, "processGooglePurchase() to call launchPurchaseFlow()"); if (mHelper != null) { mHelper.launchPurchaseFlow(this, mGooglePurchaseInfo.productIdStr, RC_REQUEST, mPurchaseFinishedListener, mGooglePurchaseInfo.developerPayloadStr); } } else { result = "{" + "\"code\": \"" + Constants.RESPONSE_500 + "\",\"message\": \" player internal error(500) \"}"; CloudGamePlayer.sWebBrowser.ubiGCPlayerCallback("googlePurchase", result); } } // Callback for when a purchase is finished IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() { public void onIabPurchaseFinished(IabResult result, Purchase purchase) { DebugLog.d(TAG, "onIabPurchaseFinished() Purchase finished: " + result + ", purchase: " + purchase); if (mHelper == null) { finish(); return; } if (result.isFailure()) { // complain("Error purchasing: " + result); // setWaitScreen(false); String resultStr = "{" + "\"code\": \"" + Constants.RESPONSE_500 + "\",\"message\": \" player internal error(500) \"}"; CloudGamePlayer.sWebBrowser.ubiGCPlayerCallback("googlePurchase", resultStr); finish(); return; } if (!verifyDeveloperPayload(purchase)) { // complain("Error purchasing. Authenticity verification failed."); // setWaitScreen(false); String resultStr = "{" + "\"code\": \"" + Constants.RESPONSE_500 + "\",\"message\": \" player internal error(500) \"}"; CloudGamePlayer.sWebBrowser.ubiGCPlayerCallback("googlePurchase", resultStr); finish(); return; } GooglePurchaseInfo googlePurchaseInfo = mGooglePurchaseMap.get(purchase.getSku()); String resultStr; if (googlePurchaseInfo != null) { DebugLog.d(TAG, "onIabPurchaseFinished() Purchase successful."); /** * * { * "id": "zkvkjxklrwekrejw" * "type": "result", * "code": "200", * "google": { * "orderId":"12999763169054705758.1371079406387615", * "packageName":"com.example.app", * "productId":"exampleSku", * "purchaseTime":1345678900000, * "purchaseState":0, * "developerPayload":"bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ", * "purchaseToken":"rojeslcdyyiapnqcynkjyyjh" * } * } */ resultStr = "{" + "\"id\": \"" + googlePurchaseInfo.idStr + "\"," + "\"type\": \"result\"," + "\"code\": \"" + Constants.RESPONSE_200 + "\"," + "\"google\": {\"orderId\": \"" + purchase.getOrderId() + "\"," + "\"packageName\": \"" + purchase.getPackageName() + "\"," + "\"productId\": \"" + purchase.getSku() + "\"," + "\"purchaseTime\": " + purchase.getPurchaseTime() + "," + "\"purchaseState\": " + purchase.getPurchaseState() + "," + "\"developerPayload\": \"" + purchase.getDeveloperPayload() + "\"," + "\"purchaseToken\": \"" + purchase.getToken() + "\"," + "}}"; mGooglePurchaseMap.remove(purchase.getSku()); } else { resultStr = "{" + "\"code\": \"" + Constants.RESPONSE_500 + "\",\"message\": \" player internal error(500) \"}"; } CloudGamePlayer.sWebBrowser.ubiGCPlayerCallback("googlePurchase", resultStr); CloudGamePlayer.sWebBrowser.setBillingStatus(Constants.BILLING_STATUS_END); WebBrowser.sIsBillingTriggered = false; finish(); // if (purchase.getSku().equals(SKU_GAS)) { // // bought 1/4 tank of gas. So consume it. // DebugLog.d(TAG, "Purchase is gas. Starting gas consumption."); // helper.consumeAsync(purchase, mConsumeFinishedListener); // } // else if (purchase.getSku().equals(SKU_PREMIUM)) { // // bought the premium upgrade! // DebugLog.d(TAG, "Purchase is premium upgrade. Congratulating user."); // alert("Thank you for upgrading to premium!"); // mIsPremium = true; // updateUi(); // setWaitScreen(false); // } // else if (purchase.getSku().equals(SKU_INFINITE_GAS)) { // // bought the infinite gas subscription // DebugLog.d(TAG, "Infinite gas subscription purchased."); // alert("Thank you for subscribing to infinite gas!"); // mSubscribedToInfiniteGas = true; // mTank = TANK_MAX; // updateUi(); // setWaitScreen(false); // } } }; /** Verifies the developer payload of a purchase. */ boolean verifyDeveloperPayload(Purchase p) { String payload = p.getDeveloperPayload(); /* * TODO: verify that the developer payload of the purchase is correct. It will be * the same one that you sent when initiating the purchase. * * WARNING: Locally generating a random string when starting a purchase and * verifying it here might seem like a good approach, but this will fail in the * case where the user purchases an item on one device and then uses your app on * a different device, because on the other device you will not have access to the * random string you originally generated. * * So a good developer payload has these characteristics: * * 1. If two different users purchase an item, the payload is different between them, * so that one user's purchase can't be replayed to another user. * * 2. The payload must be such that you can verify it even when the app wasn't the * one who initiated the purchase flow (so that items purchased by the user on * one device work on other devices owned by the user). * * Using your own server to store and verify developer payloads across app * installations is recommended. */ return true; } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { DebugLog.d(TAG, "onActivityResult(" + requestCode + "," + resultCode + "," + data); if (mHelper == null) return; // Pass on the activity result to the helper for handling if (!mHelper.handleActivityResult(requestCode, resultCode, data)) { // not handled, so handle it ourselves (here's where you'd // perform any handling of activity results not related to in-app // billing... super.onActivityResult(requestCode, resultCode, data); } else { DebugLog.d(TAG, "onActivityResult handled by IABUtil."); } } // Called when consumption is complete IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener() { public void onConsumeFinished(Purchase purchase, IabResult result) { DebugLog.d(TAG, "Consumption finished. Purchase: " + purchase + ", result: " + result); // if we were disposed of in the meantime, quit. if (mHelper == null) return; // We know this is the "gas" sku because it's the only one we consume, // so we don't check which sku was consumed. If you have more than one // sku, you probably should check... if (result.isSuccess()) { // successfully consumed, so we apply the effects of the item in our // game world's logic, which in our case means filling the gas tank a bit DebugLog.d(TAG, "Consumption successful. Provisioning."); // mTank = mTank == TANK_MAX ? TANK_MAX : mTank + 1; // saveData(); // alert("You filled 1/4 tank. Your tank is now " + String.valueOf(mTank) + "/4 full!"); } else { // complain("Error while consuming: " + result); } // updateUi(); // setWaitScreen(false); DebugLog.d(TAG, "End consumption flow."); } }; }