SlideShare a Scribd company logo
1 of 70
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 Products
distributed via the Market must be processed by the
             Market's 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
Overview

app
                      Android
  IAB                 Market
requests
                       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
          MarketBillingService
try {
  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 bundle

protected 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 request


Bundle 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
               Supported
Parameters                      Basic
Sync response keys        RESPONSE_CODE
                             RESULT_OK
                     RESULT_BILLING_UNAVAILABLE
Response codes
                            RESULT_ERROR
                      RESULT_DEVELOPER_ERROR
Async response            RESPONSE_CODE
Request Purchase
Request Purchase
                                Basic
Parameters                    ITEM_ID
                       DEVELOPER_PAYLOAD
                         RESPONSE_CODE
Sync response keys      PURCHASE_INTENT
                            REQUEST_ID
                            RESULT_OK
Response codes             RESULT_ERROR
                     RESULT_DEVELOPER_ERROR
                         RESPONSE_CODE
Async response
                          IN_APP_NOTIFY
Get Purchase
             Information
                                Basic
Parameters                    NONCE
                             NOTIFY_IDS
                          RESPONSE_CODE
Sync response keys
                            REQUEST_ID
                             RESULT_OK
Response codes             RESULT_ERROR
                      RESULT_DEVELOPER_ERROR
                          RESPONSE_CODE
Async 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
                               Basic
Parameters                   NONCE
                            NOTIFY_IDS
                         RESPONSE_CODE
Sync response keys
                           REQUEST_ID
                            RESULT_OK
Response codes            RESULT_ERROR
                     RESULT_DEVELOPER_ERROR
Async response           RESPONSE_CODE
Unsolicited In-App
       Notify

• Purchase when app is running in
  various devices
• Refunds
Unsolicited In-App
      Notify
Restore Transactions
Restore Transactions
                                Basic
Parameters
                              NONCE
                          RESPONSE_CODE
Sync response keys
                            REQUEST_ID
                             RESULT_OK
Response codes             RESULT_ERROR
                      RESULT_DEVELOPER_ERROR
                          RESPONSE_CODE
Async 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" />
                <action
android: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 Purchase
BillingController.requestPurchase(this, productId, true /*confirm*/);


@Override
public void onPurchaseIntent(String itemId, PendingIntent purchaseIntent) {
	 BillingController.startPurchaseIntent(activity, purchaseIntent, null);
}

@Override
public void onRequestPurchaseResponse(String itemId, ResponseCode response) {

}

@Override
public void onPurchaseStateChanged(String itemId, PurchaseState state) {

}
Restore Transactions
if (!mBillingObserver.isTransactionsRestored()) {
	 BillingController.restoreTransactions(this);
	 Toast.makeText(this, R.string.restoring_transactions,
Toast.LENGTH_LONG).show();
}

@Override
public void onTransactionsRestored() {
	 final SharedPreferences preferences =
PreferenceManager.getDefaultSharedPreferences(activity);
	 final Editor editor = preferences.edit();
	 editor.putBoolean(KEY_TRANSACTIONS_RESTORED, true);
	 editor.commit();
}
Suggested
implementation
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 responses
Application ever   Draft uploaded &
                                        User
been 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!
Android In-App Billing @ Barcelona GTUG

More Related Content

Viewers also liked (11)

Recycling council of bc
Recycling council of bcRecycling council of bc
Recycling council of bc
 
BPStudy #42 MongoDB and MyBike.JP and Me
BPStudy #42  MongoDB and MyBike.JP and MeBPStudy #42  MongoDB and MyBike.JP and Me
BPStudy #42 MongoDB and MyBike.JP and Me
 
Find out about your task
Find out about your taskFind out about your task
Find out about your task
 
e2e Projects
e2e Projectse2e Projects
e2e Projects
 
ガラケーの識別子
ガラケーの識別子ガラケーの識別子
ガラケーの識別子
 
Infographic: The Brazilian Games Market
Infographic: The Brazilian Games MarketInfographic: The Brazilian Games Market
Infographic: The Brazilian Games Market
 
Alla ricerca del Graal
Alla ricerca del GraalAlla ricerca del Graal
Alla ricerca del Graal
 
Andyscoggcamp revised
Andyscoggcamp revisedAndyscoggcamp revised
Andyscoggcamp revised
 
Gaceta oficial nº 40.965
Gaceta oficial nº 40.965Gaceta oficial nº 40.965
Gaceta oficial nº 40.965
 
Tracking social media campaigns @ editech
Tracking social media campaigns @ editechTracking social media campaigns @ editech
Tracking social media campaigns @ editech
 
Linked in 002
Linked in 002Linked in 002
Linked in 002
 

Similar to Android In-App Billing @ Barcelona GTUG

INTEGRATED SHOPPING ASSISTANCE WITH FREDGE AND MOBILE
INTEGRATED SHOPPING ASSISTANCE WITH FREDGE AND MOBILEINTEGRATED SHOPPING ASSISTANCE WITH FREDGE AND MOBILE
INTEGRATED SHOPPING ASSISTANCE WITH FREDGE AND MOBILE
Rajesh Roky
 

Similar to Android In-App Billing @ Barcelona GTUG (20)

IAP auto renewable in practice
IAP auto renewable  in practiceIAP auto renewable  in practice
IAP auto renewable in practice
 
Samsung IAP SDK
Samsung IAP SDKSamsung IAP SDK
Samsung IAP SDK
 
2012 SVCodeCamp: In App Payments with HTML5
2012 SVCodeCamp: In App Payments with HTML52012 SVCodeCamp: In App Payments with HTML5
2012 SVCodeCamp: In App Payments with HTML5
 
AdVenture Capitalist Post-Mortem
AdVenture Capitalist Post-MortemAdVenture Capitalist Post-Mortem
AdVenture Capitalist Post-Mortem
 
HTML5 Gaming Payment Platforms
HTML5 Gaming Payment PlatformsHTML5 Gaming Payment Platforms
HTML5 Gaming Payment Platforms
 
Selling Physical GoodsThrough Apps & Other Monetization Strategies (MBL306) |...
Selling Physical GoodsThrough Apps & Other Monetization Strategies (MBL306) |...Selling Physical GoodsThrough Apps & Other Monetization Strategies (MBL306) |...
Selling Physical GoodsThrough Apps & Other Monetization Strategies (MBL306) |...
 
Big commerce app development
Big commerce app developmentBig commerce app development
Big commerce app development
 
Dropwizard with MongoDB and Google Cloud
Dropwizard with MongoDB and Google CloudDropwizard with MongoDB and Google Cloud
Dropwizard with MongoDB and Google Cloud
 
Paypal Integration For Android Application By LetsNurture
Paypal Integration For Android Application By LetsNurturePaypal Integration For Android Application By LetsNurture
Paypal Integration For Android Application By LetsNurture
 
Android Accessibility - The missing manual
Android Accessibility - The missing manualAndroid Accessibility - The missing manual
Android Accessibility - The missing manual
 
Social Gold in-Flash Webinar Jan 2010
Social Gold in-Flash Webinar Jan 2010Social Gold in-Flash Webinar Jan 2010
Social Gold in-Flash Webinar Jan 2010
 
Social Gold In-Flash Payments Webinar
Social Gold In-Flash Payments WebinarSocial Gold In-Flash Payments Webinar
Social Gold In-Flash Payments Webinar
 
Interconnect Mobile Application Development on Bluemix!!
Interconnect Mobile Application Development on Bluemix!!Interconnect Mobile Application Development on Bluemix!!
Interconnect Mobile Application Development on Bluemix!!
 
API Product Management and Strategy
API Product Management and StrategyAPI Product Management and Strategy
API Product Management and Strategy
 
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
 
Workshop CQRS and DDD
Workshop CQRS and DDDWorkshop CQRS and DDD
Workshop CQRS and DDD
 
INTEGRATED SHOPPING ASSISTANCE WITH FREDGE AND MOBILE
INTEGRATED SHOPPING ASSISTANCE WITH FREDGE AND MOBILEINTEGRATED SHOPPING ASSISTANCE WITH FREDGE AND MOBILE
INTEGRATED SHOPPING ASSISTANCE WITH FREDGE AND MOBILE
 
CQRS and Event Sourcing
CQRS and Event Sourcing CQRS and Event Sourcing
CQRS and Event Sourcing
 
[Hands-on] CQRS(Command Query Responsibility Segregation) 와 Event Sourcing 패턴 실습
[Hands-on] CQRS(Command Query Responsibility Segregation) 와 Event Sourcing 패턴 실습[Hands-on] CQRS(Command Query Responsibility Segregation) 와 Event Sourcing 패턴 실습
[Hands-on] CQRS(Command Query Responsibility Segregation) 와 Event Sourcing 패턴 실습
 
Self checkout application presentation
Self checkout application presentationSelf checkout application presentation
Self checkout application presentation
 

Recently uploaded

Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptxHarnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
FIDO Alliance
 
Hyatt driving innovation and exceptional customer experiences with FIDO passw...
Hyatt driving innovation and exceptional customer experiences with FIDO passw...Hyatt driving innovation and exceptional customer experiences with FIDO passw...
Hyatt driving innovation and exceptional customer experiences with FIDO passw...
FIDO Alliance
 
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
Muhammad Subhan
 

Recently uploaded (20)

Intro to Passkeys and the State of Passwordless.pptx
Intro to Passkeys and the State of Passwordless.pptxIntro to Passkeys and the State of Passwordless.pptx
Intro to Passkeys and the State of Passwordless.pptx
 
How we scaled to 80K users by doing nothing!.pdf
How we scaled to 80K users by doing nothing!.pdfHow we scaled to 80K users by doing nothing!.pdf
How we scaled to 80K users by doing nothing!.pdf
 
The Metaverse: Are We There Yet?
The  Metaverse:    Are   We  There  Yet?The  Metaverse:    Are   We  There  Yet?
The Metaverse: Are We There Yet?
 
Design Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptxDesign Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptx
 
WebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM PerformanceWebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM Performance
 
TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...
TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...
TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...
 
Introduction to FIDO Authentication and Passkeys.pptx
Introduction to FIDO Authentication and Passkeys.pptxIntroduction to FIDO Authentication and Passkeys.pptx
Introduction to FIDO Authentication and Passkeys.pptx
 
Generative AI Use Cases and Applications.pdf
Generative AI Use Cases and Applications.pdfGenerative AI Use Cases and Applications.pdf
Generative AI Use Cases and Applications.pdf
 
1111 ChatGPT Prompts PDF Free Download - Prompts for ChatGPT
1111 ChatGPT Prompts PDF Free Download - Prompts for ChatGPT1111 ChatGPT Prompts PDF Free Download - Prompts for ChatGPT
1111 ChatGPT Prompts PDF Free Download - Prompts for ChatGPT
 
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptxHarnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
 
Frisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdf
Frisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdfFrisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdf
Frisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdf
 
Continuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
Continuing Bonds Through AI: A Hermeneutic Reflection on ThanabotsContinuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
Continuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
 
Long journey of Ruby Standard library at RubyKaigi 2024
Long journey of Ruby Standard library at RubyKaigi 2024Long journey of Ruby Standard library at RubyKaigi 2024
Long journey of Ruby Standard library at RubyKaigi 2024
 
Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...
Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...
Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...
 
Syngulon - Selection technology May 2024.pdf
Syngulon - Selection technology May 2024.pdfSyngulon - Selection technology May 2024.pdf
Syngulon - Selection technology May 2024.pdf
 
WebRTC and SIP not just audio and video @ OpenSIPS 2024
WebRTC and SIP not just audio and video @ OpenSIPS 2024WebRTC and SIP not just audio and video @ OpenSIPS 2024
WebRTC and SIP not just audio and video @ OpenSIPS 2024
 
Hyatt driving innovation and exceptional customer experiences with FIDO passw...
Hyatt driving innovation and exceptional customer experiences with FIDO passw...Hyatt driving innovation and exceptional customer experiences with FIDO passw...
Hyatt driving innovation and exceptional customer experiences with FIDO passw...
 
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
 
How to Check CNIC Information Online with Pakdata cf
How to Check CNIC Information Online with Pakdata cfHow to Check CNIC Information Online with Pakdata cf
How to Check CNIC Information Online with Pakdata cf
 
Using IESVE for Room Loads Analysis - UK & Ireland
Using IESVE for Room Loads Analysis - UK & IrelandUsing IESVE for Room Loads Analysis - UK & Ireland
Using IESVE for Room Loads Analysis - UK & Ireland
 

Android In-App Billing @ Barcelona GTUG

  • 1.
  • 2.
  • 3. Android In-App Billing Demystified
  • 4. 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
  • 10. IAB for the user... • Faster • Simpler • Contextual • “Harmless” • “Inexpensive”
  • 11. IAB generates more sales
  • 12. 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
  • 13. Options • Android Market In-App Billing • PayPal Mobile Payments Library • Others • Any web payment processor • Custom implementation
  • 14. Android Market IAB • Android Market only • 30% of the sale price • Android 1.6 upwards • Only digital goods
  • 15. PayPal Mobile Payments • Starts at 2.9% of the sale price + transaction fee • Android 1.5 upwards • Physical goods allowed
  • 16. Others • Paythru • Movend • Open Payments • And a long list of other dubious looking websites
  • 17. “All fees received by Developers for Products distributed via the Market must be processed by the Market's Payment Processor.” http://www.android.com/us/developer-distribution-agreement.html
  • 18. Agenda • In-App Billing Overview • In-App Billing in Android • Android Market Billing Service • Android Billing Library • Administering In-App Billing • Security Best Practices
  • 19. Pre-requisites • Services • AIDL • BroadcastReceiver • PendingIntent
  • 20. Overview app Android IAB Market requests Server
  • 22. IAB requests • CHECK_BILLING_SUPPORTED • REQUEST_PURCHASE • GET_PURCHASE_INFORMATION • CONFIRM_NOTIFICATIONS • RESTORE_TRANSACTIONS
  • 23. 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
  • 24. Binding to MarketBillingService try {   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); }
  • 25. Request bundle parameters • Shared • BILLING_REQUEST: request type • API_VERSION: 1 • PACKAGE_NAME: app package • Specific • ITEM_ID, NONCE, NOTIFY_ID, DEVELOPER_PAYLOAD
  • 26. Request bundle protected 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; }
  • 27. Making a request Bundle request = makeRequestBundle("REQUEST_PURCHASE"); request.putString(ITEM_ID, mProductId); Bundle response = mService.sendBillingRequest(request);
  • 28. IAB responses • The IAB service responds to every request with a synchronous response • Followed by 0..N asynchronous responses depending of the request type
  • 29. 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.
  • 30. Asynchronous responses • Broadcast intents: • RESPONSE_CODE • IN_APP_NOTIFY • PURCHASE_STATE_CHANGED
  • 31. 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);     }   }
  • 33. Check Billing Supported Parameters Basic Sync response keys RESPONSE_CODE RESULT_OK RESULT_BILLING_UNAVAILABLE Response codes RESULT_ERROR RESULT_DEVELOPER_ERROR Async response RESPONSE_CODE
  • 35. Request Purchase Basic Parameters ITEM_ID DEVELOPER_PAYLOAD RESPONSE_CODE Sync response keys PURCHASE_INTENT REQUEST_ID RESULT_OK Response codes RESULT_ERROR RESULT_DEVELOPER_ERROR RESPONSE_CODE Async response IN_APP_NOTIFY
  • 36. Get Purchase Information Basic Parameters NONCE NOTIFY_IDS RESPONSE_CODE Sync response keys REQUEST_ID RESULT_OK Response codes RESULT_ERROR RESULT_DEVELOPER_ERROR RESPONSE_CODE Async response PURCHASE_STATE_CHANGED
  • 37. 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 } }
  • 38. Purchase States • Purchased (0) • Canceled (1) • Refunded (2)
  • 39. Confirm Notifications Basic Parameters NONCE NOTIFY_IDS RESPONSE_CODE Sync response keys REQUEST_ID RESULT_OK Response codes RESULT_ERROR RESULT_DEVELOPER_ERROR Async response RESPONSE_CODE
  • 40. Unsolicited In-App Notify • Purchase when app is running in various devices • Refunds
  • 43. Restore Transactions Basic Parameters NONCE RESPONSE_CODE Sync response keys REQUEST_ID RESULT_OK Response codes RESULT_ERROR RESULT_DEVELOPER_ERROR RESPONSE_CODE Async response PURCHASE_STATE_CHANGED
  • 44. Security Controls • Signed purchase data • In-App Notify Nonces
  • 45. Purchase State Changed Extras • inapp_signed_data: Signed JSON string (unencrypted) • inapp_signature: Use the Android Market public key to validate
  • 46.
  • 47.
  • 48. 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
  • 50. Android Billing Library • https://github.com/robotmedia/ AndroidBillingLibrary • Beta but... • “Better than starting from scratch”
  • 51. Features • Full Android IAB Service implementation • Auto-confirmations • Obfuscated purchases database • Implements security best-practices • Half-decent unit testing coverage
  • 53. 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" /> <action android:name="com.android.vending.billing.PURCHASE_STATE_CHANGED" /> </intent-filter> </receiver> </application>
  • 54. 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"; } }); }
  • 55. 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); } }
  • 56. Request Purchase BillingController.requestPurchase(this, productId, true /*confirm*/); @Override public void onPurchaseIntent(String itemId, PendingIntent purchaseIntent) { BillingController.startPurchaseIntent(activity, purchaseIntent, null); } @Override public void onRequestPurchaseResponse(String itemId, ResponseCode response) { } @Override public void onPurchaseStateChanged(String itemId, PurchaseState state) { }
  • 57. Restore Transactions if (!mBillingObserver.isTransactionsRestored()) { BillingController.restoreTransactions(this); Toast.makeText(this, R.string.restoring_transactions, Toast.LENGTH_LONG).show(); } @Override public void onTransactionsRestored() { final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity); final Editor editor = preferences.edit(); editor.putBoolean(KEY_TRANSACTIONS_RESTORED, true); editor.commit(); }
  • 59. 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
  • 60. Purchase type • Managed per user account • premium, digital content, unique virtual goods • Unmanaged • subscriptions, virtual currency, unlimited virtual goods
  • 61. Managing In-App Products
  • 62.
  • 64. Reserved product ids • android.test.purchased • android.test.canceled • android.test.refunded • android.test.item_unavailable
  • 66. Signed test responses Application ever Draft uploaded & User been published? unpublished? * * Developer Yes No Test user Yes Yes *
  • 67. 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
  • 68. Best practices • Random nonces • Obfuscate purchase data • Embedding public key • Code obfuscation • Server-side signature validation

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n