Quickstart: Using the Windows Phone 8.1 Wallet APIs

This topic describes how to interact with Wallet using the Windows.ApplicationModel.Wallet API.

To see the code described here in action, download and run the Wallet Quickstart sample.

Prerequisites

Many of the methods used to interact with Wallet are asynchronous. To learn how to write asynchronous apps, see Quickstart: Using the await operator for asynchronous programming.

Creating a new Wallet item

When creating a Wallet item programmatically, you create an instance of WalletItem, defining the type of item you want to create and setting properties on that item. The following example creates a membership card and defines properties such as colors, display name, images to be shown on the item and a bar code representation of the membership account number.

// Create the membership card.
WalletItem card = new WalletItem(WalletItemKind.MembershipCard, "Contoso Loyalty Card");

// Set colors, to give the card our distinct branding.
card.BodyColor = Windows.UI.Colors.Brown;
card.BodyFontColor = Windows.UI.Colors.White;
card.HeaderColor = Windows.UI.Colors.SaddleBrown;
card.HeaderFontColor = Windows.UI.Colors.White;

// Set basic properties.
card.IssuerDisplayName = "Contoso Coffee";

// Set some images.
card.Logo336x336 =  await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///assets/coffee336x336.png"));

card.Logo99x99 =    await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///assets/coffee99x99.png"));

card.Logo159x159 = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///assets/coffee159x159.png"));

card.HeaderBackgroundImage = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///assets/header640x130.png"));

// Set the loyalty card points and show them on the detailed view of card and in the list view.
WalletItemCustomProperty prop = new WalletItemCustomProperty("Coffee Points", "99");
prop.DetailViewPosition = WalletDetailViewPosition.FooterField1;
prop.SummaryViewPosition = WalletSummaryViewPosition.Field1;
card.DisplayProperties["PointsId"] = prop;

// Show the branch.
prop = new WalletItemCustomProperty("Branch", "Contoso on 5th");
prop.DetailViewPosition = WalletDetailViewPosition.HeaderField1;
card.DisplayProperties["BranchId"] = prop;

// Add the customer account number.
prop = new WalletItemCustomProperty("Account Number", "12345678");
prop.DetailViewPosition = WalletDetailViewPosition.FooterField2;

// We don't want this field entity extracted as it will be interpreted as a phone number.
prop.AutoDetectLinks = false;
card.DisplayProperties["AcctId"] = prop;

// Encode the user's account number as a Qr Code to be used in the store.
card.Barcode = new WalletBarcode(WalletBarcodeSymbology.Qr, "12345678");

// Add a promotional message to the card.
card.DisplayMessage = "Tap here for your 15% off coupon";
card.IsDisplayMessageLaunchable = true;

Note that in the preceding code, the display name you give to the item in the constructor cannot be null or empty. If it is, an InvalidOperationException will be thrown.

The types of item you can add to Wallet are defined in the WalletItemKind enumeration.

Inserting a Wallet item into Wallet

Once you've created a Wallet item, you can insert it into Wallet using the WalletItemStore.AddAsync method. The first thing to do is to request an instance of the default Wallet store.

// Request an instance of the default wallet store
wallet = await WalletManager.RequestStoreAsync();

Next, you insert the Wallet item that you created by calling the AddAsync asynchronous action on the store object. Make sure the ID you give for the item is unique across your app, or the insertion will thrown an exception.

Adding a Wallet item.

await wallet.AddAsync("CoffeeLoyalty123", card);

Updating an existing item

You can update any property of an item that is already in Wallet, provided the item was inserted by your app. To do so, you first retrieve the item from Wallet using the ID, or key, you gave it when creating the item. In this example, we are assuming an item with ID "CoffeeLoyalty123" had previously been inserted into Wallet.

// Find an existing wallet item.
walletItem = await wallet.GetWalletItemAsync("CoffeeLoyalty123");

If the item is not found, the preceding code will return null and you should check for that possibility. Once you have the Wallet item instance, you can then update properties on the item. An example of updating a property is shown in the following code.

// Update a property on the wallet item.
walletItem.DisplayProperties["PointsId"].Value = CoffePointsValue.Text;

// Update the item in the wallet.
await wallet.UpdateAsync(walletItem);

Adding a transaction to an item

If you want to record usage, or transactions, used with a particular card, you can do so by adding those transactions to the item in the Wallet. This is demonstrated in the following code.

// Create a transaction.
WalletTransaction walletTransaction = new WalletTransaction();
walletTransaction.Description = "Double tall latte";
walletTransaction.DisplayAmount = "$3.27";

// The date and time of the transaction
walletTransaction.TransactionDate = DateTime.Now;

// Don't display the time of the transaction, just the date.
walletTransaction.IgnoreTimeOfDay = false;

// A string representing where the transaction took place.
walletTransaction.DisplayLocation = "Contoso on 5th";

// Add the transaction to the TransactionHistory of this item.
walletItem.TransactionHistory.Add("txnid123", walletTransaction);

// Update the item in Wallet.
await wallet.UpdateAsync(walletItem);

Deleting a Wallet item

If a card has expired, or you want to remove it for any other reason from Wallet, you can do so with the DeleteAsync method.

Request an instance of the Wallet store, if you don't have one already

// Request an instance of the default wallet store
wallet = await WalletManager.RequestStoreAsync();

Find the item you want to delete

// Find an existing wallet item.
walletItem = await wallet.GetWalletItemAsync("CoffeeLoyalty123");

Delete the item

await wallet.DeleteAsync(walletItem.Id);

Adding relevancy data to an item

Adding this information promotes the item in the main summary view in Wallet on the particular date, or at the particular location. When the item becomes relevant based on the relevancy data you set on the item, a toast notification pop-up message is also displayed to the user. For example, a relevant date for a boarding pass is the date of the flight. Another example is the location of a cinema for a movie ticket. This enables items to show up in the summary list when they are most relevant.

// Create a new relevant location object.
WalletRelevantLocation location = new WalletRelevantLocation();
location.DisplayMessage = "Welcome to Contoso Coffee on 5th";

// Set the desired location.
var position = new Windows.Devices.Geolocation.BasicGeoposition();
position.Latitude = 47.63;
position.Longitude = -122.2147;
location.Position = position;

// Add this location to the RelevantLocations collection on the item.
// Note: The key for each entry must be unique in the collection. 
walletItem.RelevantLocations.Add("5thId", location);

// Add a relevant date.
walletItem.RelevantDate = DateTime.Now;
walletItem.RelevantDateDisplayMessage = "Free coffee day";

// Update the item in Wallet.
await wallet.UpdateAsync(walletItem);

Launching your app with a verb

An item can have a set of custom verbs associated with it. These verbs are actions that the user can perform. Example verbs are "open app", "visit our website", "add a reminder" and so on. If one of these verbs is tapped on the card, your app will be launched by the system and you can then carry out the desired action.

Add the verb to the Wallet item.

// Add a verb to the wallet item. In this example, we are adding 
// a verb to allow the user to add funds to their account.
walletItem.Verbs.Add("addfunds", new WalletVerb("Add Funds"));

// Update the item in Wallet.
await wallet.UpdateAsync(walletItem);

Once the verb has been added, it will show on the item. When the user taps on the verb, your app will launch and you can take appropriate action based on the verb and ID of the item that was tapped.

Launching Wallet from an app

You can launch Wallet to show the summary view or to display one of your items. The following code shows how to launch Wallet and show the summary view.

// Launch Wallet
await wallet.ShowAsync();

To launch Wallet and display the details of an item, call ShowAsync and pass in the ID of the item that you want to display.

Importing a Wallet item package

A Wallet item package is a zip file container with a .mswallet extension that contains the data describing a Wallet item. The user can open these items from an email or web page on the phone and import the item directly into Wallet. You can also do this programmatically from your app by using the ImportItemAsync method. The following code snippet shows you how this is done.

Use the Storagefile API to get the .mswallet file. In this example, the file is located in the Assets folder of the installed app.

// Import another membership card, represented by the .mswallet file located in the Assets folder of this sample. 
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///assets/ContosoCoffeePikePlace.mswallet")); 

Once you have the file, import it as a WalletItem using the ImportItemAsync method.

walletItem = await wallet.ImportItemAsync(file); 

If the system fails to import the item represented by the file object, an exception will be thrown and your code should handle that possibility. If the item was successfully imported, a WalletItem object is returned. This is useful if you want to update properties of the item you just imported. Just change the properties on this object and then call UpdateAsync to update the item in Wallet.

Note  An app can only import Wallet item packages associated with the app. The value of the ProductId field in the WalletItem.xml metadata file must match the product Id of the app.

Handling app activation by Wallet

There are a number of scenarios when your app can be activated as the result of the user doing something inside Wallet. For example, the user might tap on a transaction or a verb on a Wallet item associated with your app. The following code snippet illustrates how you can detect activation and determine what specific wallet action caused the activation.

/// <summary>
/// Both the OnLaunched and OnActivated event handlers need to make sure the root frame has been created, so the common 
/// code to do that is factored into this method and called from both.
/// </summary>
private void CreateRootFrame()
{
    // Do not repeat app initialization when the Window already has content,
    // just ensure that the window is active
    if (RootFrame != null)
        return;

    // Create a Frame to act as the navigation context and navigate to the first page
    RootFrame = new Frame();

    //Associate the frame with a SuspensionManager key                                
    SuspensionManager.RegisterFrame(RootFrame, "AppFrame");

    // Set the default language
    RootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];

    RootFrame.NavigationFailed += OnNavigationFailed;

    // Place the frame in the current Window
    Window.Current.Content = RootFrame;
} 
/// <summary>
/// The OnActivated event occurs when the app has been activated through an action other than the normal opening of the app
/// by the user from the start page. In this Wallet sample, activation occurs when the user taps on 
/// an action on a card associated with this app in Wallet. 
/// In this event handler, the activation arguments are then passed to the MainPage.
/// To see how this activation is handled in this sample, see DetectActivationKind in MainPage.xaml.cs
/// </summary>
/// <param name="e"></param>
protected async override void OnActivated(IActivatedEventArgs e)
{
    // Check whether app was activated due to a Wallet action
    if (e.Kind == ActivationKind.WalletAction)
    {
        Debug.WriteLine("Activated by a Wallet action");

        // Cast the incoming arguments to a WalletActionActivatedEventArgs object
        WalletActionActivatedEventArgs walletActivationArgs = e as WalletActionActivatedEventArgs;

        // Check the properties of the WalletActionActivatedEventArgs to determine what
        // action and item caused the app to be activated.
        Debug.WriteLine("ActionId = {0}", walletActivationArgs.ActionId);
        Debug.WriteLine("ActionKind = {0}", walletActivationArgs.ActionKind);
        Debug.WriteLine("ItemId = {0}", walletActivationArgs.ItemId);
    }

    CreateRootFrame();

    // Restore the saved session state only when appropriate
    if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
    {
        try
        {
            await SuspensionManager.RestoreAsync();
        }
        catch (SuspensionManagerException)
        {
            //Something went wrong restoring state.
            //Assume there is no state and continue
        }
    }

    if (RootFrame.Content == null)
    {
        // When the navigation stack isn't restored navigate to the first page,
        // configuring the new page by passing required information as a navigation
        // parameter
        RootFrame.Navigate(typeof(MainPage), e);
    }

    Window.Current.Activate();
} 
protected async override void OnLaunched(LaunchActivatedEventArgs e)
{

#if DEBUG
    if (System.Diagnostics.Debugger.IsAttached)
    {
        this.DebugSettings.EnableFrameRateCounter = true;
    }
#endif
    CreateRootFrame();

    if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
    {
        // Restore the saved session state only when appropriate
        try
        {
            await SuspensionManager.RestoreAsync();
        }
        catch (SuspensionManagerException)
        {
            //Something went wrong restoring state.
            //Assume there is no state and continue
        }
    }

    if (RootFrame.Content == null)
    {
        // When the navigation stack isn't restored navigate to the first page,
        // configuring the new page by passing required information as a navigation
        // parameter
        RootFrame.Navigate(typeof(MainPage), e.Arguments);
    }

    // Ensure the current window is active
    Window.Current.Activate();
} 

For more information on the kind of actions that can activate your app, see WalletActionKind.

Summary and next steps

In this topic, you were introduced to the Windows Phone 8.1Wallet APIs that can be used to programmatically add and manage Wallet items. You can only manage items that your app creates and have no access to items created outside of your app. The items you create are automatically associated with your app.

To see the code described here in action, download and run the Wallet Quickstart sample.

Wallet Quickstart sample

Windows.ApplicationModel.Wallet

Overview of Wallet for Windows Phone Store apps

Quickstart: Creating and distributing Wallet item packages (.mswallet files)