• Save
Android In-App Billing @ Barcelona GTUG
Upcoming SlideShare
Loading in...5
×
 

Android In-App Billing @ Barcelona GTUG

on

  • 2,625 views

 

Statistics

Views

Total Views
2,625
Views on SlideShare
2,513
Embed Views
112

Actions

Likes
7
Downloads
0
Comments
0

1 Embed 112

http://www.marketing-android.fr 112

Accessibility

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

Android In-App Billing @ Barcelona GTUG Android In-App Billing @ Barcelona GTUG Presentation Transcript

  • Android In-App Billing Demystified
  • Agenda• In-App Billing Overview• In-App Billing in Android• Android Market Billing Service• Android Billing Library• Administering & Testing In-App Billing• Security Best Practices
  • Freemium
  • Digital goods
  • Digital content
  • Subscriptions
  • Virtual currency
  • IAB for the user...• Faster• Simpler• Contextual• “Harmless”• “Inexpensive”
  • IAB generates more sales
  • Agenda• In-App Billing Overview• In-App Billing in Android• Android Market Billing Service• Android Billing Library• Administering & Testing In-App Billing• Security Best Practices
  • Options• Android Market In-App Billing• PayPal Mobile Payments Library• Others• Any web payment processor• Custom implementation
  • Android Market IAB• Android Market only• 30% of the sale price• Android 1.6 upwards• Only digital goods
  • PayPal Mobile Payments• Starts at 2.9% of the sale price + transaction fee• Android 1.5 upwards• Physical goods allowed
  • Others• Paythru• Movend• Open Payments• And a long list of other dubious looking websites
  • “All fees received by Developers for Productsdistributed via the Market must be processed by the Markets Payment Processor.” http://www.android.com/us/developer-distribution-agreement.html
  • Agenda• In-App Billing Overview• In-App Billing in Android• Android Market Billing Service• Android Billing Library• Administering In-App Billing• Security Best Practices
  • Pre-requisites• Services• AIDL• BroadcastReceiver• PendingIntent
  • Overviewapp Android IAB Marketrequests Server
  • Messaging sequence
  • IAB requests• CHECK_BILLING_SUPPORTED• REQUEST_PURCHASE• GET_PURCHASE_INFORMATION• CONFIRM_NOTIFICATIONS• RESTORE_TRANSACTIONS
  • IAB requests• MarketBillingService interface defined in an Android Interface Definition Language file (IMarketBillingService.aidl)• IAB requests sent by single IPC method (sendBillingRequest()) of the interface• Request type and parameters are sent as a Bundle
  • Binding to MarketBillingServicetry {  boolean bindResult = mContext.bindService(    new Intent("com.android.vending.billing.MarketBillingService.BIND"), this,    Context.BIND_AUTO_CREATE);  if (bindResult) {    Log.i(TAG, "Service bind successful.");  } else {    Log.e(TAG, "Could not bind to the MarketBillingService.");  }} catch (SecurityException e) {  Log.e(TAG, "Security exception: " + e);}public void onServiceConnected(ComponentName name, IBinder service) {  Log.i(TAG, "MarketBillingService connected.");  mService = IMarketBillingService.Stub.asInterface(service);}
  • Request bundle parameters• Shared • BILLING_REQUEST: request type • API_VERSION: 1 • PACKAGE_NAME: app package• Specific • ITEM_ID, NONCE, NOTIFY_ID, DEVELOPER_PAYLOAD
  • Request bundleprotected Bundle makeRequestBundle(String method) {  Bundle request = new Bundle();  request.putString(BILLING_REQUEST, method);  request.putInt(API_VERSION, 1);  request.putString(PACKAGE_NAME, getPackageName());  return request;}
  • Making a requestBundle request = makeRequestBundle("REQUEST_PURCHASE");request.putString(ITEM_ID, mProductId);Bundle response = mService.sendBillingRequest(request);
  • IAB responses• The IAB service responds to every request with a synchronous response• Followed by 0..N asynchronous responses depending of the request type
  • Synchronous responses• RESPONSE_CODE: status information and error information about a request• REQUEST_ID: used to match asynchronous responses with requests• PURCHASE_INTENT: PendingIntent, which you use to launch the checkout activity. REQUEST_PURCHASE only.
  • Asynchronous responses• Broadcast intents: • RESPONSE_CODE • IN_APP_NOTIFY • PURCHASE_STATE_CHANGED
  • Receiving async responses public void onReceive(Context context, Intent intent) {    String action = intent.getAction();    if (ACTION_PURCHASE_STATE_CHANGED.equals(action)) {      String signedData = intent.getStringExtra(INAPP_SIGNED_DATA);      String signature = intent.getStringExtra(INAPP_SIGNATURE);      // Do something with the signedData and the signature.    } else if (ACTION_NOTIFY.equals(action)) {      String notifyId = intent.getStringExtra(NOTIFICATION_ID);      // Do something with the notifyId.    } else if (ACTION_RESPONSE_CODE.equals(action)) {      long requestId = intent.getLongExtra(INAPP_REQUEST_ID, -1);      int responseCodeIndex = intent.getIntExtra(INAPP_RESPONSE_CODE,        ResponseCode.RESULT_ERROR.ordinal());      // Do something with the requestId and the responseCodeIndex.    } else {      Log.w(TAG, "unexpected action: " + action);    }  }
  • Check Billing Supported
  • Check Billing SupportedParameters BasicSync response keys RESPONSE_CODE RESULT_OK RESULT_BILLING_UNAVAILABLEResponse codes RESULT_ERROR RESULT_DEVELOPER_ERRORAsync response RESPONSE_CODE
  • Request Purchase
  • Request Purchase BasicParameters ITEM_ID DEVELOPER_PAYLOAD RESPONSE_CODESync response keys PURCHASE_INTENT REQUEST_ID RESULT_OKResponse codes RESULT_ERROR RESULT_DEVELOPER_ERROR RESPONSE_CODEAsync response IN_APP_NOTIFY
  • Get Purchase Information BasicParameters NONCE NOTIFY_IDS RESPONSE_CODESync response keys REQUEST_ID RESULT_OKResponse codes RESULT_ERROR RESULT_DEVELOPER_ERROR RESPONSE_CODEAsync response PURCHASE_STATE_CHANGED
  • Purchase State Changed JSON{ "nonce" : 1836535032137741465, "orders" : { "notificationId" : "android.test.purchased", "orderId" : "transactionId.android.test.purchased", "packageName" : "com.example.dungeons", "productId" : "android.test.purchased", "developerPayload" : "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQ", "purchaseTime" : 1290114783411, "purchaseState" : 0 }}
  • Purchase States• Purchased (0)• Canceled (1)• Refunded (2)
  • Confirm Notifications BasicParameters NONCE NOTIFY_IDS RESPONSE_CODESync response keys REQUEST_ID RESULT_OKResponse codes RESULT_ERROR RESULT_DEVELOPER_ERRORAsync response RESPONSE_CODE
  • Unsolicited In-App Notify• Purchase when app is running in various devices• Refunds
  • Unsolicited In-App Notify
  • Restore Transactions
  • Restore Transactions BasicParameters NONCE RESPONSE_CODESync response keys REQUEST_ID RESULT_OKResponse codes RESULT_ERROR RESULT_DEVELOPER_ERROR RESPONSE_CODEAsync response PURCHASE_STATE_CHANGED
  • Security Controls• Signed purchase data• In-App Notify Nonces
  • Purchase State Changed Extras• inapp_signed_data: Signed JSON string (unencrypted)• inapp_signature: Use the Android Market public key to validate
  • Agenda• In-App Billing Overview• In-App Billing in Android• Android Market Billing Service• Android Billing Library• Administering & Testing In-App Billing• Security Best Practices
  • requestPurchase("com.example.item");
  • Android Billing Library • https://github.com/robotmedia/ AndroidBillingLibrary • Beta but... • “Better than starting from scratch”
  • Features• Full Android IAB Service implementation• Auto-confirmations• Obfuscated purchases database• Implements security best-practices• Half-decent unit testing coverage
  • Overview
  • AndroidManifest.xml <!-- Add this permission to your manifest --> <uses-permission android:name="com.android.vending.BILLING" /> <application> <!-- Add this service and receiver to your application --> <service android:name="net.robotmedia.billing.BillingService" /> <receiver android:name="net.robotmedia.billing.BillingReceiver"> <intent-filter> <action android:name="com.android.vending.billing.IN_APP_NOTIFY" /> <action android:name="com.android.vending.billing.RESPONSE_CODE" /> <actionandroid:name="com.android.vending.billing.PURCHASE_STATE_CHANGED" /> </intent-filter> </receiver> </application>
  • Set Configuration public void onCreate() { super.onCreate(); BillingController.setDebug(true); BillingController.setConfiguration(new BillingController.IConfiguration() { @Override public byte[] getObfuscationSalt() { return new byte[] {41, -90, -116, -41, 66, -53, 122, -110, -127, -96, -88, 77, 127 } @Override public String getPublicKey() { return "your public key here"; } }); }
  • Check Billing Supported @Override public void onCreate(Bundle savedInstanceState) { // ... BillingController.registerObserver(mBillingObserver); BillingController.checkBillingSupported(this); // ... } public void onBillingChecked(boolean supported) { if (!supported) { showDialog(DIALOG_BILLING_NOT_SUPPORTED_ID); } }
  • Request PurchaseBillingController.requestPurchase(this, productId, true /*confirm*/);@Overridepublic void onPurchaseIntent(String itemId, PendingIntent purchaseIntent) { BillingController.startPurchaseIntent(activity, purchaseIntent, null);}@Overridepublic void onRequestPurchaseResponse(String itemId, ResponseCode response) {}@Overridepublic void onPurchaseStateChanged(String itemId, PurchaseState state) {}
  • Restore Transactionsif (!mBillingObserver.isTransactionsRestored()) { BillingController.restoreTransactions(this); Toast.makeText(this, R.string.restoring_transactions,Toast.LENGTH_LONG).show();}@Overridepublic void onTransactionsRestored() { final SharedPreferences preferences =PreferenceManager.getDefaultSharedPreferences(activity); final Editor editor = preferences.edit(); editor.putBoolean(KEY_TRANSACTIONS_RESTORED, true); editor.commit();}
  • Suggestedimplementation
  • Agenda• In-App Billing Overview• In-App Billing in Android• Android Market Billing Service• Android Billing Library• Administering & Testing In-App Billing• Security Best Practices
  • Purchase type• Managed per user account • premium, digital content, unique virtual goods• Unmanaged • subscriptions, virtual currency, unlimited virtual goods
  • Managing In-App Products
  • Public key
  • Reserved product ids• android.test.purchased• android.test.canceled• android.test.refunded• android.test.item_unavailable
  • Test purchase process
  • Signed test responsesApplication ever Draft uploaded & Userbeen published? unpublished? * * Developer Yes No Test user Yes Yes *
  • Agenda• In-App Billing Overview• In-App Billing in Android• Android Market Billing Service• Android Billing Library• Administering & Testing In-App Billing• Security Best Practices
  • Best practices• Random nonces• Obfuscate purchase data• Embedding public key• Code obfuscation• Server-side signature validation
  • Gracias!