Skip to content

Commit

Permalink
Merge branch 'master' into feature/new-android-billing
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesmontemagno committed Sep 1, 2020
2 parents fcf0fcf + 65e4426 commit 2543e51
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 68 deletions.
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ A simple In-App Purchase plugin for Xamarin and Windows to query item informatio
## Documentation
Get started by reading through the [In-App Billing Plugin documentation](https://jamesmontemagno.github.io/InAppBillingPlugin/).

There are changes in version 4.0 so read below.

## NuGet
* NuGet: [Plugin.InAppBilling](https://www.nuget.org/packages/Plugin.InAppBilling) [![NuGet](https://img.shields.io/nuget/v/Plugin.InAppBilling.svg?label=NuGet)](https://www.nuget.org/packages/Plugin.InAppBilling/)

Expand All @@ -31,7 +33,21 @@ Dev Feed: https://ci.appveyor.com/nuget/inappbillingplugin
### Checkout my podcast on IAP
I co-host a weekly development podcast, [Merge Conflict](http://mergeconflict.fm), about technology and recently covered IAP and this library: [Merge Conflict 28: Demystifying In-App Purchases](http://www.mergeconflict.fm/57678-merge-conflict-28-demystifying-in-app-purchases)

## Version 3 Linker Settings
## Version 4 Major Update - Android

Version 4.X updates to the new Android billing client. This means there are few important changes:
1.) You must acknowledge all purchases within 3 days, by calling `AcknowledgePurchaseAsync` or the Consume API if it a consumable.
2.) You must hanle Pending Transactions from outside of you app. See [docs from Google](https://developer.android.com/google/play/billing/integrate#pending)

### Pending Transactions:
* If the result of PurchaseAsync is PurchaseState.PaymentPending, store the order details locally and inform the user that they will have access to the product when the payment completes
* When the user starts the app (and/or visits a particular page), if the stored PurchaseState is PaymentPending, call GetPurchasesAsync and query the result for a purchase that matches the stored purchase.
* If the PurchaseState for this purchase is still PaymentPending, show the same no-access message
* If the PurchaseState is Purchased, call ConsumePurchaseAsync or AcknowledgePurchaseAsync, depending on the product type

I highly recommend reading the entire [Google Play Billing System docs](https://developer.android.com/google/play/billing/).

## Version 3+ Linker Settings

For linking if you are setting **Link All** you may need to add:

Expand Down
17 changes: 15 additions & 2 deletions docs/GettingStarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,25 @@ Each app store has you create them in a different area.
* Android: Go to Google Play Console -> Select App -> Store presence -> In-app products (you can only create on if you have uploaded a version of your app with this plugin or the Vending permission set).
* Microsoft: Go to Dashboard -> Select App -> Add-ons

## Permissions & Additional Setup - Version 4

## Permissions & Additional Setup Considerations
In version 4 we use Xamarin.Essentials so you must ensure you initialize it in your Android project. It is setup by default in new projects:

```csharp
protected override void OnCreate(Bundle savedInstanceState) {
//...
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState); // add this line to your code, it may also be called: bundle
//...
```

That's it.

## Permissions & Additional Setup - Version 2

### Android:

The `com.android.vending.BILLING` permission is required to use In-App Billing on Android and this library ill automatically added it your Android Manifest when you compile. No need to add them manually!
The `com.android.vending.BILLING` permission is required to use In-App Billing on Android and this library will automatically added it your Android Manifest when you compile. No need to add them manually!

You must place this code in your Main/Base Activity where you will be requesting purchases from.

Expand Down
65 changes: 0 additions & 65 deletions nuget/readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,68 +2,3 @@ In App Billing Plugin for Xamarin & Windows

Find the latest setup guides, documentation, and testing instructions at:
https://github.com/jamesmontemagno/InAppBillingPlugin

## News
- Change to "ConnectAsync()" on ANDROID! Please pass in the ItemType that you are about to purchase! The default is normal in app purchase.

## Additional Required Setup (Please Read!)

## Android
You must set your app to compile against API 25 or higher and be able to install the latest android support libraries.

This Plugin uses the CurrentActivity Plugin and will add a MainApplication.cs file to your Android application. This is extremely important and should not be deleted. Please see
http://github.com/jamesmontemagno/CurrentActivityPlugin for more information.

In your BaseActivity or MainActivity (for Xamarin.Forms) add this code:

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
InAppBillingImplementation.HandleActivityResult(requestCode, resultCode, data);
}

## Android Current Activity Setup

This plugin uses the [Current Activity Plugin](https://github.com/jamesmontemagno/CurrentActivityPlugin/blob/master/README.md) to get access to the current Android Activity. Be sure to complete the full setup if a MainApplication.cs file was not automatically added to your application. Please fully read through the [Current Activity Plugin Documentation](https://github.com/jamesmontemagno/CurrentActivityPlugin/blob/master/README.md). At an absolute minimum you must set the following in your Activity's OnCreate method:

```csharp
Plugin.CurrentActivity.CrossCurrentActivity.Current.Activity = this;
```

It is highly recommended that you use a custom Application that are outlined in the Current Activity Plugin Documentation](https://github.com/jamesmontemagno/CurrentActivityPlugin/blob/master/README.md)


### Android Security
I recommend reading the Google Play services Security and Design that will walk you through your options on storing your public key. InAppBilling Pluging offers Android developers an additional interface, IInAppBillingVerifyPurchase to implement to verify the purchase with their public key and helper methods to encrypt and decrypt. It is recommended to atleast follow the XOR guidance if you do not want to setup a verification server.

IInAppBillingVerifyPurchase has 1 Method: Task VerifyPurchase(string signedData, string signature). It returns a boolean that validates that the signed data and signature match based on the public key. If you pass in null to the purchase or get purchases methods no verification will be done.

The simplest and easiest (not necessarily the most secure) way is to do the following:

Take your public key and break into 3 parts
Run each through the helper XOR method: Plugin.InAppBilling.InAppBillingImplementation.InAppBillingSecurity.TransformString
Save each value out and put them in your app
Implement the interface with this funcationality:

public class Verify : IInAppBillingVerifyPurchase
{
const string key1 = @"XOR_key1";
const string key2 = @"XOR_key2";
const string key3 = @"XOR_key3";

public Task<bool> VerifyPurchase(string signedData, string signature)
{

#if __ANDROID__
var key1Transform = Plugin.InAppBilling.InAppBillingImplementation.InAppBillingSecurity.TransformString(key1, 1);
var key2Transform = Plugin.InAppBilling.InAppBillingImplementation.InAppBillingSecurity.TransformString(key2, 2);
var key3Transform = Plugin.InAppBilling.InAppBillingImplementation.InAppBillingSecurity.TransformString(key3, 3);

return Task.FromResult(Plugin.InAppBilling.InAppBillingImplementation.InAppBillingSecurity.VerifyPurchase(key1Transform + key2Transform + key3Transform, signedData, signature));
#else
return Task.FromResult(true);
#endif
}
}

Plugin.InAppBilling.InAppBillingImplementation.InAppBillingSecurity.VerifyPurchase takes in your public key which you now have reversed back to standard and will do proper RSA validation on the signed data.

0 comments on commit 2543e51

Please sign in to comment.