Click here to see your recently viewed pages and most viewed pages.
Hide
Google Wallet Instant Buy APIs

Instant Buy API for iOS Tutorial

This tutorial guides you through integrating Instant Buy into a purchase flow, in the context of an example bike store. The tutorial provides details and complete source code to help you complete the the integration steps summarized in the integration overview, with the end goal of reproducing a flow similar to the one depicted in the process flow diagram. All of the bundle and framework resources you'll need, in addition to all the source files for the sample, are included in google_wallet_ios_sample-0.1.498.zip.

Contents

Create a client ID

Create a client ID for OAuth 2.0, to enable preauthorization checking. Start in the Google Developers Console by selecting APIs and auth and then Credentials in the left menu.

  1. Go to the Google Developers Console.
  2. Select a project, or create a new one.
  3. Click on CREATE NEW CLIENT ID, enter a name for your app, and then in the Create Client ID lightbox, do the following:
    1. Select Installed application for the Application type.
    2. Select iOS
    3. In the Bundle ID field, enter the bundle identifier from your application's project summary.
    4. If your app is published in the Apple iTunes App Store, enter your app's App Store identifier in the App Store ID field. You can determine the ID from the "id" part of your app's URL on iTunes website: http://itunes.apple.com/us/app/id
  4. In the API Access pane, locate the section Client ID for iOS applications and note or copy the Client ID and Client Secret that you will need later to run your app.

Add the Google Wallet Instant Buy SDK

  1. Download the Google Wallet Instant Buy SDK, if you haven't already. The SDK includes:

    • GoogleWalletSDK.framework
    • GoogleOpenSource.framework
    • GoogleWalletSDK.bundle This is a resource bundle with assets for the "Buy with Google button.
    • The sample Xcode project.
  2. Extract the files from the downloaded SDK archive.

  3. Drag and drop the following resources from the SDK into the Frameworks folder of your XCode project:

    • GoogleWalletSDK.framework
    • GoogleWalletSDK.bundle
    • GoogleOpenSource.framework
  4. Include the GoogleWalletSDK.bundle in your XCode project to add it to your target. Go to Build Phases > Copy Bundle Resources and click on +. Find and add the GoogleWalletSDK.bundle. This ensures that the assets are copied as part of the build.

  5. Add the ObjC linker flag to the app target's build settingss:

    Other Linker Flags: -ObjC
    
  6. In your app's Info tab, add a URL type and enter your bundle ID as the identifier and scheme. The scheme for the URL type used by Instant Buy to call back to your app is google-wallet-merchant-app-<base32_app_name>. The scheme ends with a lower case base32 string of the app identifier. For the sample app, this looks like the following (do not copy this string for your app's name):

Graphic that shows the identifier and URL Schemas fields with the value of com.example.bundle entered

Implement the GWAWalletClientDelegate protocol

To adopt the GWAWalletClientDelegate protocol, you'll need to import it, and then implement a list of related methods in your view controller.

In viewcontroller.m, add the following:

#import <GoogleWalletSDK/GoogleWalletSDK.h>

@interface BKSDetailViewController ()<GWAWalletClientDelegate>
...
@end

In viewcontroller.m, implement the methods in the GWAWalletClientDelegate protocol. These are the callback methods that are called by the GWAWalletClient object:

#pragma mark - GWAWalletClientDelegate

- (void)walletClient:(GWAWalletClient *)walletClient
 didLoadMaskedWallet:(GWAMaskedWallet *)maskedWallet {

}

- (void)walletClient:(GWAWalletClient *)walletClient
didFailToLoadMaskedWalletWithError:(NSError *)error {

}
- (void)walletClient:(GWAWalletClient *)walletClient
   didLoadFullWallet:(GWAFullWallet *)fullWallet {

}

- (void)walletClient:(GWAWalletClient *)walletClient
didFailToLoadFullWalletWithError:(NSError *)error {

}

- (void)walletClient:(GWAWalletClient *)walletClient userIsPreauthorized:(BOOL)userIsPreauthorized {

}

Initialize the GWAWalletClient

The wallet client object, GWAWalletClient, communicates with Google Wallet. The wallet client becomes functional after your app establishes an asynchronous connection with the service.

Set up GWAWalletClient with the delegate in viewWillAppear. This ensures that the correct delegate gets the callbacks.

The following code snippet illustrates how an app can instantiate wallet client:

                 _walletClient = [GWAWalletClient sharedInstance];
     _walletClient.environment = kGWAEnvironmentSandbox;
        _walletClient.delegate = self;

Handle OpenURL

In your AppDelegate.m, import GoogleWalletSDK.h.

#import GoogleWalletSDK/GoogleWalletSDK.h

Call GWAWalletClient handleOpenUrl:sourceApplication:annotation: from your app delegate's URL handler. This handler appropriately handles the URL that your application receives after a call to one of the GWAWalletClient methods such as loadMaskedWallet:.

- (BOOL)application:(UIApplication *)application
              openURL:(NSURL *)url
    sourceApplication:(NSString *)sourceApplication
           annotation:(id)annotation {
  // Forward the URL to the Wallet Client for handling
  if ([GWAWalletClient handleOpenURL:url
                   sourceApplication:sourceApplication
                          annotation:annotation]) {
    return YES;
  }
  return NO;
}

Check for prior authorization

It is a good practice to determine whether users have previously authorized Google Wallet as a default payment method to use with your app. For preauthorized users, you can streamline your UI in these ways:

  • Highlight the Buy with Google button or move it to the top of a list of payment methods.
  • Make your "continue checkout" button default to Google Wallet and direct the user directly to the purchase confirmation page.

To check for preauthorization, call the checkForPreauthorization method on GWAWalletClient.

 // Check for pre-auth
 [_walletClient checkForPreauthorization];

This in turn calls the userIsPreauthorized: method on the delegate to indicate whether the user had already pre-authorized.

 - (void)walletClient:(GWAWalletClient *)walletClient
  userIsPreauthorized:(BOOL)userIsPreauthorized {
    NSLog(@"userIsPreauthorized %@", userIsPreauthorized ? @"YES" : @"NO");
     }

Create a GWAMaskedWalletRequest

The masked wallet request defines the fields you'll need from the user's Google Wallet to create an order. You'll create this request object in order to pass it to the Buy with Google button in the next step.

Set up the GWAMaskedWalletRequest by passing in the necessary properties such as estimatedTotalPrice and currencyCode.

GWAMaskedWalletRequest *request = [[GWAMaskedWalletRequest alloc]
                                      initWithCurrencyCode:@"USD"
                                       estimatedTotalPrice:@"10.99"];
    request.phoneNumberRequired = YES;
request.shippingAddressRequired = YES;
                   request.cart = [[GWACart alloc] init…];

Add the "Buy with Google" Button

  1. In your UIViewController's .h file, import GoogleWalletSDK/GoogleWalletSDK.h and declare the GWAWalletButton as a property:

    @property (nonatomic, retain) IBOutlet GWAWalletButton *walletButton;
    
  2. In the View controller's .m file import GoogleWalletSDK/GoogleWalletSDK.h

  3. Add the GWAWalletButton to your storyboard or XIB file, or instantiate it programatically. Drag a UIButton or view onto your view controller and set its custom class to GWAWalletButton. The resources for the "Buy with Google" button are contained in the bundle GoogleWalletSDK.bundle.

  4. Set the maskedWalletRequest (created in the prior step) on the button:

    _maskedWalletRequest = …;
    _walletButton.maskedWalletRequest = _maskedWalletRequest;
    

On click, this button invokes loadMaskedWallet automatically. Google then authenticates the user and displays the "chooser" — the dialog for selecting among payment methods and addresses. Once the buyer makes a selection, the response is received in one of the following delegate methods:

(void)walletClient:(GWAWalletClient *)walletClient
   didLoadMaskedWallet:(GWAMaskedWallet *)maskedWallet;

Or, in case of an error:

(void)walletClient:(GWAWalletClient *)walletClient
didFailToLoadMaskedWalletWithError:(NSError *)error;

Confirm with the user and (optionally) change the masked wallet

After the app obtains the masked wallet, it typically presents a confirmation page which displays the following information:

  • The user's selected payment options, from the paymentDescriptions property of GWAMaskedWallet
  • The user's Google account email address from the email property
  • The user's selected shipping address (if applicable) from the shippingAddress property
  • The total cost of the items purchased in the transaction. At this point the app has the shipping address and billing address, so it can calculate the exact total purchase price, including taxes and shipping costs, and display it.

This page should also allow the user to change the Google Wallet payment instrument and change the shipping address for the purchase via GWAWalletClient.changeMaskedWalletWithGoogleTransactionId:merchantTransactionId:. You can create a selector to call when the change button is clicked. For example:

- (IBAction)changeMaskedWallet:(id)sender {
  [_walletClient changeMaskedWalletWithGoogleTransactionId:self.maskedWallet.googleTransactionId
                                     merchantTransactionId:self.maskedWallet.merchantTransactionId];
}

Here, the googleTransactionId and the merchantTransactionId from the masked wallet are passed to the changeMaskedWalletWithGoogleTransactionId:merchantTransactionId: call.

Create a GWAFullWalletRequest

As with the masked wallet request, you'll first create a request object for the full wallet (which includes the proxy card to use for payment), and then load it separately. To create the request, add the line items, the cart object, along with the relevant transaction IDs:

  NSMutableArray *lineItems = [[NSMutableArray alloc] init];
  [lineItems addObject:[[GWALineItem alloc]
                           initWithItemDescription:@"Item"
                                     unitPrice:@"10.00"
                                      quantity:@"1"]];

  [lineItems
      addObject:[[GWALineItem alloc]
                    initWithItemDescription:@"Shipping"
                             totalPrice:@"5.00"
                                   role:kGWALineItemRoleShipping]];

  [lineItems addObject:[[GWALineItem alloc]
                           initWithItemDescription:@"Tax"
                                    totalPrice:@"1.00"
                                          role:kGWALineItemRoleTax]];

  GWACart *cart =
      [[GWACart alloc] initWithCurrencyCode:kBKSCurrencyCode
                                 totalPrice:@"16.00"
                                  lineItems:lineItems];

  GWAFullWalletRequest *fullWalletRequest = [[GWAFullWalletRequest alloc]
      initWithGoogleTransactionId:googleTransactionId
                             cart:cart
            merchantTransactionId:merchantTransactionId];

Load the full wallet

Make the GWAWalletClient loadFullWallet: call when the user has had a chance to review the order details and clicked on a "Place Order" or equivalent button.

[client loadFullWallet:fullWalletRequest];

If this call succeeds, the walletClient:didLoadFullWallet:" delegate method will be called. The full wallet can then be used to get the GWAProxyCard to send to the payment processor. In case of an error, walletClient:didFailToLoadFullWalletWithError: is called with the specific error message.

GWAProxyCard *proxyCard = [fullWallet proxyCard];
NSString *pan = [proxyCard pan];
NSString *cvn = [proxyCard cvn];
NSDateComponents *expirationDate = [proxyCard expirationDate];
GWAAddress *address = [fullWallet shippingAddress];

// The array of paymentDescriptions objects contains structured information
// about the user's backing payment instruments in use for this particular transaction.
// This should also be sent back to the backend server and shown on the user's receipt.
NSArray *paymentDescriptions = [fullWallet paymentDescriptions];

In some scenarios, Google's risk engine returns a CVN or password challenge to the user in a call to loadFullWallet. Once the user types in the necessary information, an updated masked wallet object is returned in a call to didLoadMaskedWallet:(GWAMaskedWallet *)maskedWallet. Make sure your app responds to this delegate method and appropriately updates the masked wallet information on the view controller. For example:

- (void)walletClient:(GWAWalletClient *)walletClient
    didLoadMaskedWallet:(GWAMaskedWallet *)maskedWallet {.
  self.maskedWallet = maskedWallet;
  [self.tableView reloadData];
}

Notify Google Wallet of your Transaction Processing

Once you have obtained the payment instrument information from the GWAProxyCard and processed the payment, notify Google Wallet of the success or failure of the payment. You can map his status to one of the values in the GWATransactionStatus enum such as such as kGWATransactionStatusSuccess, kGWATransactionStatusAVSDecline, kGWATransactionStatusBadCard, etc. Finally, call GWAWalletClient.notifyTransactionStatus to send the status back to Google.

[_walletClient notifyTransactionStatus:kGWATransactionStatusSuccess];