To accept payments in your mobile app, you will need to do a number of actions.
Payments need to be taken through the built-in mechanism by Apple (App Store), Google (Play Store), etc. These app distribution marketplaces typically forbid charging the users outside of their platforms, so they can take a commission (often 30%, but sometimes 15%). There are exceptions to this rule, but they are outside of the scope of this tutorial.
Generally, your payments are either related to a subscription (a recurring payment schedule that can be cancelled by the user at any time) or an in-app purchase (one-off payment for a digital product, which can be used for a non-recurring subscription also (such as lifetime).
You should set up your buyable products and subscriptions directly in the iTunes Connect (for iOS) or Google Play Console (for Android). That's a straight forward web-based step-by-step process which you can do once logged into those web app consoles.
For each product or subscription option you should choose a unique product ID which should be in the format of my_product_id (lower case, alphanumeric characters and underlines). It's recommended to use the same name on both App Store and Google Play store accounts to prevent confusion. Be very careful when setting them up, because once you use a product id, you cannot delete and reuse it.
The price and availability will be set also directly in the store. Try to keep the Apple and Google Play store prices as close to each other as you can to avoid having angry users later on.
Once your products are set up, add the nuget package Plugin.InAppBilling to your iOS, Android and UWP projects.
It's also recommended to read this guide for better understanding of how it works.
You will need to apply the linker skip settings in your iOS and Android projects in Release configuration. Otherwise you will get runtime errors when publishing the app!
In your app, implement the subscription or shopping page as per your requirements and design. The products you publish in the app, must match the same product IDs as the ones you set up in the previous step.
It is recommended that in your app domain project, you have the necessary classes to represent your products. For example a class named SubscriptionProduct, to include all product Ids, and other descriptions, stored in a Json file in your app can be a good idea.
The prices may change, and are in fact different on each app store and each user location. This means that you need to dynamically fetch the latest price information for the products in your app to ensure the prices you show in the app are the same as ones set up in the App stores' web console. Once you have the correct price, for performance, you can cache it locally, but still it's recommneded to fetch the updated prices regularly, (e.g. daily).
You can obtain the latest prices for all your products and subscriptions by making a single call for each type.
{
try
{
var connected = await Billing.ConnectAsync(type);
if (!connected) return false;
var items = await Billing.GetProductInfoAsync(type, productIds);
if (items == null) return false;
foreach (var item in items)
SubscriptionProduct.Update(item.ProductId, item.LocalizedPrice, item.MicrosPrice / 1000000m);
SubscriptionProduct.SavePrices();
return true;
}
finally
{
try { await Billing.DisconnectAsync(); }
catch { Zebble.Device.Log.Error("Failed to disconnect from billing!"); }
}
}
// if needed, have a similar call for in-app purchases.
// TODO: Implement a full store implementation as Zebble.Billing with client and server components.
The Store class needs an initialization routine which loads the product json (overridable) manages the price updates, purchase event calls, server components, ...