Permalink
Browse files

Merge pull request #782 from poiuytrez/billingPlugin

[Android] Google Play In App Billing plugin
  • Loading branch information...
2 parents f699f4d + d7454ba commit d8d4acea3b915460709602a91a623cd468098100 @devgeeks devgeeks committed Nov 26, 2012
Showing with 3,743 additions and 0 deletions.
  1. +24 −0 Android/InAppBilling/com/android/vending/billing/IMarketBillingService.aidl
  2. +264 −0 Android/InAppBilling/com/smartmobilesoftware/inappbilling/InAppBillingPlugin.java
  3. +26 −0 Android/InAppBilling/inappbilling.js
  4. +746 −0 Android/InAppBilling/net/robotmedia/billing/BillingController.java
  5. +70 −0 Android/InAppBilling/net/robotmedia/billing/BillingReceiver.java
  6. +325 −0 Android/InAppBilling/net/robotmedia/billing/BillingRequest.java
  7. +289 −0 Android/InAppBilling/net/robotmedia/billing/BillingService.java
  8. +85 −0 Android/InAppBilling/net/robotmedia/billing/IBillingObserver.java
  9. +160 −0 Android/InAppBilling/net/robotmedia/billing/helper/AbstractBillingActivity.java
  10. +147 −0 Android/InAppBilling/net/robotmedia/billing/helper/AbstractBillingFragment.java
  11. +67 −0 Android/InAppBilling/net/robotmedia/billing/helper/AbstractBillingObserver.java
  12. +110 −0 Android/InAppBilling/net/robotmedia/billing/model/BillingDB.java
  13. +135 −0 Android/InAppBilling/net/robotmedia/billing/model/Transaction.java
  14. +77 −0 Android/InAppBilling/net/robotmedia/billing/model/TransactionManager.java
  15. +106 −0 Android/InAppBilling/net/robotmedia/billing/security/DefaultSignatureValidator.java
  16. +32 −0 Android/InAppBilling/net/robotmedia/billing/security/ISignatureValidator.java
  17. +114 −0 Android/InAppBilling/net/robotmedia/billing/utils/AESObfuscator.java
  18. +570 −0 Android/InAppBilling/net/robotmedia/billing/utils/Base64.java
  19. +32 −0 Android/InAppBilling/net/robotmedia/billing/utils/Base64DecoderException.java
  20. +75 −0 Android/InAppBilling/net/robotmedia/billing/utils/Compatibility.java
  21. +59 −0 Android/InAppBilling/net/robotmedia/billing/utils/Installation.java
  22. +75 −0 Android/InAppBilling/net/robotmedia/billing/utils/Security.java
  23. +155 −0 Android/InAppBilling/readme.md
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.vending.billing;
+
+import android.os.Bundle;
+
+interface IMarketBillingService {
+ /** Given the arguments in bundle form, returns a bundle for results. */
+ Bundle sendBillingRequest(in Bundle bundle);
+}
@@ -0,0 +1,264 @@
+package com.smartmobilesoftware.inappbilling;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.cordova.api.Plugin;
+import org.apache.cordova.api.PluginResult;
+import org.json.JSONArray;
+
+import net.robotmedia.billing.BillingController;
+import net.robotmedia.billing.BillingRequest.ResponseCode;
+import net.robotmedia.billing.helper.AbstractBillingObserver;
+import net.robotmedia.billing.model.Transaction;
+import net.robotmedia.billing.model.Transaction.PurchaseState;
+
+import android.app.Activity;
+import android.util.Log;
+
+// In app billing plugin
+public class InAppBillingPlugin extends Plugin {
+ // Yes, that's the two variables to edit :)
+ private static final String publicKey = "PASTE_HERE_YOUR_PUBLIC_KEY";
+ private static final byte[] salt = { 42, -70, -106, -41, 66, -53, 122,
+ -110, -127, -96, -88, 77, 127, 115, 1, 73, 17, 110, 48, -116 };
+
+ private static final String INIT_STRING = "init";
+ private static final String PURCHASE_STRING = "purchase";
+ private static final String OWN_ITEMS_STRING = "ownItems";
+
+
+ private final String TAG = "BILLING";
+ // Observer notified of events
+ private AbstractBillingObserver mBillingObserver;
+ private Activity activity;
+ private String callbackId;
+
+ // Plugin action handler
+ public PluginResult execute(String action, JSONArray data, String callbackId) {
+ // Save the callback id
+ this.callbackId = callbackId;
+ PluginResult pluginResult;
+
+ if (INIT_STRING.equals(action)) {
+ // Initialize the plugin
+ initialize();
+ // Wait for the restore transaction and billing supported test
+ pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
+ pluginResult.setKeepCallback(true);
+ return pluginResult;
+ } else if (PURCHASE_STRING.equals(action)) {
+ // purchase the item
+ try {
+
+ // Retrieve parameters
+ String productId = data.getString(0);
+ // Make the purchase
+ BillingController.requestPurchase(this.cordova.getContext(), productId, true /* confirm */, null);
+
+ pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
+ pluginResult.setKeepCallback(true);
+ } catch (Exception ex) {
+ pluginResult = new PluginResult(
+ PluginResult.Status.JSON_EXCEPTION, "Invalid parameter");
+ }
+
+ return pluginResult;
+
+ } else if (OWN_ITEMS_STRING.equals(action)){
+ // retrieve already bought items
+
+ ArrayList<String> ownItems = new ArrayList<String>();
+ ownItems = getOwnedItems();
+ // convert the list of strings to a json list of strings
+ JSONArray ownItemsJson = new JSONArray();
+ for (String item : ownItems){
+ ownItemsJson.put(item);
+ }
+
+ // send the result to the app
+ pluginResult = new PluginResult(PluginResult.Status.OK, ownItemsJson);
+ return pluginResult;
+ }
+
+ return null;
+ }
+
+ // Initialize the plugin
+ private void initialize() {
+ BillingController.setDebug(true);
+ // configure the in app billing
+ BillingController
+ .setConfiguration(new BillingController.IConfiguration() {
+
+ public byte[] getObfuscationSalt() {
+ return InAppBillingPlugin.salt;
+ }
+
+ public String getPublicKey() {
+ return InAppBillingPlugin.publicKey;
+ }
+ });
+
+ // Get the activity from the Plugin
+ // Activity test = this.cordova.getContext().
+ activity = cordova.getActivity();
+
+ // create a billingObserver
+ mBillingObserver = new AbstractBillingObserver(activity) {
+
+ public void onBillingChecked(boolean supported) {
+ InAppBillingPlugin.this.onBillingChecked(supported);
+ }
+
+ public void onPurchaseStateChanged(String itemId,
+ PurchaseState state) {
+ InAppBillingPlugin.this.onPurchaseStateChanged(itemId, state);
+ }
+
+ public void onRequestPurchaseResponse(String itemId,
+ ResponseCode response) {
+ InAppBillingPlugin.this.onRequestPurchaseResponse(itemId,
+ response);
+ }
+
+ public void onSubscriptionChecked(boolean supported) {
+ InAppBillingPlugin.this.onSubscriptionChecked(supported);
+ }
+
+ };
+
+ // register observer
+ BillingController.registerObserver(mBillingObserver);
+ BillingController.checkBillingSupported(activity);
+
+ }
+
+ public void onBillingChecked(boolean supported) {
+ PluginResult result;
+ if (supported) {
+ Log.d("BILLING", "In app billing supported");
+ // restores previous transactions, if any.
+ restoreTransactions();
+ result = new PluginResult(PluginResult.Status.OK, "In app billing supported");
+ // stop waiting for the callback
+ result.setKeepCallback(false);
+ // notify the app
+ this.success(result, callbackId);
+ } else {
+ Log.d("BILLING", "In app billing not supported");
+ result = new PluginResult(PluginResult.Status.ERROR,
+ "In app billing not supported");
+ // stop waiting for the callback
+ result.setKeepCallback(false);
+ // notify the app
+ this.error(result, callbackId);
+ }
+
+ }
+
+ // change in the purchase
+ public void onPurchaseStateChanged(String itemId, PurchaseState state) {
+ PluginResult result;
+
+ Log.i(TAG, "onPurchaseStateChanged() itemId: " + itemId);
+
+ // Check the status of the purchase
+ if(state == PurchaseState.PURCHASED){
+ // Item has been purchased :)
+ result = new PluginResult(PluginResult.Status.OK, itemId);
+ result.setKeepCallback(false);
+ this.success(result, callbackId);
+ } else {
+ // purchase issue
+ String message = "";
+ if (state == PurchaseState.CANCELLED){
+ message = "canceled";
+ } else if (state == PurchaseState.REFUNDED){
+ message = "refunded";
+ } else if (state == PurchaseState.EXPIRED){
+ message = "expired";
+ }
+ // send the result to the app
+ result = new PluginResult(PluginResult.Status.ERROR, message);
+ result.setKeepCallback(false);
+ this.error(result, callbackId);
+
+ }
+
+
+ }
+
+ // response from the billing server
+ public void onRequestPurchaseResponse(String itemId, ResponseCode response) {
+ PluginResult result;
+
+ // check the response
+ Log.d(TAG, "response code ");
+
+ if(response == ResponseCode.RESULT_OK){
+ // purchase succeeded
+ result = new PluginResult(PluginResult.Status.OK, itemId);
+ result.setKeepCallback(false);
+ this.success(result, callbackId);
+ } else {
+ // purchase error
+ String message = "";
+
+ // get the error message
+ if (response == ResponseCode.RESULT_USER_CANCELED){
+ message = "canceled";
+
+ } else if (response == ResponseCode.RESULT_SERVICE_UNAVAILABLE){
+ message = "network connection error";
+ } else if (response == ResponseCode.RESULT_BILLING_UNAVAILABLE){
+ message = "in app billing unavailable";
+ } else if (response == ResponseCode.RESULT_ITEM_UNAVAILABLE){
+ message = "cannot find the item";
+ } else if (response == ResponseCode.RESULT_DEVELOPER_ERROR){
+ message = "developer error";
+ } else if (response == ResponseCode.RESULT_ERROR){
+ message = "unexpected server error";
+ }
+ // send the result to the app
+ result = new PluginResult(PluginResult.Status.ERROR, message);
+ result.setKeepCallback(false);
+ this.error(result, callbackId);
+ }
+
+ }
+
+ public void onSubscriptionChecked(boolean supported) {
+
+ }
+
+ /**
+ * Restores previous transactions, if any. This happens if the application
+ * has just been installed or the user wiped data. We do not want to do this
+ * on every startup, rather, we want to do only when the database needs to
+ * be initialized.
+ */
+ private void restoreTransactions() {
+ if (!mBillingObserver.isTransactionsRestored()) {
+ BillingController.restoreTransactions(this.cordova.getContext());
+
+ }
+ }
+
+ // update bought items
+ private ArrayList<String> getOwnedItems() {
+ List<Transaction> transactions = BillingController
+ .getTransactions(this.cordova.getContext());
+ final ArrayList<String> ownedItems = new ArrayList<String>();
+ for (Transaction t : transactions) {
+ if (t.purchaseState == PurchaseState.PURCHASED) {
+ ownedItems.add(t.productId);
+ }
+ }
+ // The list of purchased items is now stored in "ownedItems"
+
+ return ownedItems;
+
+ }
+
+}
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2012 by Guillaume Charhon
+ */
+var inappbilling = {
+
+ // Initialize the plugin
+ init: function (success, fail) {
+ return cordova.exec( success, fail,
+ "InAppBillingPlugin",
+ "init", ["null"]);
+ },
+ // purchase an item
+ purchase: function (success, fail, productId) {
+ return cordova.exec( success, fail,
+ "InAppBillingPlugin",
+ "purchase", [productId]);
+ },
+ // get already own items
+ getOwnItems: function (success, fail) {
+ return cordova.exec( success, fail,
+ "InAppBillingPlugin",
+ "ownItems", ["null"]);
+ },
+
+
+};
Oops, something went wrong.

0 comments on commit d8d4ace

Please sign in to comment.