In App purchases in C++

storeV1 seemed a lot less robust than storeV2, but also simpler. My original code used it but as it didn’t work anyway I switched over to V2.

storeV2 and iOnlinePurchases are linked. To enable add the following to Config/IOS/IOSEngine.ini

 [OnlineSubsystemIOS.Store]
 bSupportsInAppPurchasing=True
 bUseStoreV2=True

My purchase code is below. CompletePurchase is code of mine that looks at my own DB using the offerID to workout what to give the player.

I only have consumables at the moment and found that FinalizePurchase needs to be called to prevent them being rewarded repeatedly. However this didn’t work in 4.15 without a minor engine modification - or I couldn’t work out how to make it work as the delegate was coming through without a valid TransactionId (added below).

auto delegate = [this](const FOnlineError &result, const TSharedRef<FPurchaseReceipt> &r)
{
	if (result.bSucceeded)
	{
			for (auto &o : r->ReceiptOffers)
			{
				CompletePurchase(o.OfferId);
			}

			m_Purchases->FinalizePurchase(GetUserId(), r->TransactionId);
	}
};
FPurchaseCheckoutRequest request;
FOfferNamespace offerNamespace;

request.AddPurchaseOffer(offerNamespace, rOfferId, 1, true);


FOnPurchaseCheckoutComplete dele;
dele.BindLambda(delegate);

m_Purchases->Checkout(GetUserId(), request, dele);

Engine modification - add the line below after GenerateReceipt:

     void FOnlinePurchaseIOS::OnTransactionCompleteResponse(EPurchaseTransactionState Result, const FStoreKitTransactionData& TransactionData)
     {
   ...
                 TSharedRef<FPurchaseReceipt> FinalReceipt = UserPendingTransaction->GenerateReceipt();
                 FinalReceipt->TransactionId = TransactionData.GetTransactionIdentifier();

This got me working, though I’m not through certification yet, just entering a TestFlight Beta…