Browse Source

iOS InAppPurchases: Use recommended receipt verification procedure

v6.1.6
reuk 4 years ago
parent
commit
2073e46e79
No known key found for this signature in database GPG Key ID: 9ADCD339CFC98A11
1 changed files with 51 additions and 36 deletions
  1. +51
    -36
      modules/juce_product_unlocking/native/juce_ios_InAppPurchases.cpp

+ 51
- 36
modules/juce_product_unlocking/native/juce_ios_InAppPurchases.cpp View File

@@ -544,10 +544,10 @@ struct InAppPurchases::Pimpl : public SKDelegateAndPaymentObserver
void fetchReceiptDetailsFromAppStore (NSData* receiptData, const String& secret)
{
auto requestContents = [NSMutableDictionary dictionaryWithCapacity: (NSUInteger) (secret.isNotEmpty() ? 2 : 1)];
[requestContents setObject: [receiptData base64EncodedStringWithOptions:0] forKey: nsStringLiteral ("receipt-data")];
[requestContents setObject: [receiptData base64EncodedStringWithOptions:0] forKey: @"receipt-data"];
if (secret.isNotEmpty())
[requestContents setObject: juceStringToNS (secret) forKey: nsStringLiteral ("password")];
[requestContents setObject: juceStringToNS (secret) forKey: @"password"];
NSError* error;
auto requestData = [NSJSONSerialization dataWithJSONObject: requestContents
@@ -559,47 +559,62 @@ struct InAppPurchases::Pimpl : public SKDelegateAndPaymentObserver
return;
}
#if JUCE_IN_APP_PURCHASES_USE_SANDBOX_ENVIRONMENT
auto storeURL = "https://sandbox.itunes.apple.com/verifyReceipt";
#else
auto storeURL = "https://buy.itunes.apple.com/verifyReceipt";
#endif
verifyReceipt ("https://buy.itunes.apple.com/verifyReceipt", requestData);
}
void verifyReceipt (const String& endpoint, NSData* requestData)
{
const auto nsurl = [NSURL URLWithString: juceStringToNS (endpoint)];
// TODO: use juce URL here
auto* urlPtr = [NSURL URLWithString: nsStringLiteral (storeURL)];
auto storeRequest = [NSMutableURLRequest requestWithURL: urlPtr];
[storeRequest setHTTPMethod: nsStringLiteral ("POST")];
if (nsurl == nullptr)
return;
const auto storeRequest = [NSMutableURLRequest requestWithURL: nsurl];
[storeRequest setHTTPMethod: @"POST"];
[storeRequest setHTTPBody: requestData];
auto task = [[NSURLSession sharedSession] dataTaskWithRequest: storeRequest
completionHandler:
^(NSData* data, NSURLResponse*, NSError* connectionError)
{
if (connectionError != nil)
{
sendReceiptFetchFail();
}
else
{
NSError* err;
constexpr auto sandboxURL = "https://sandbox.itunes.apple.com/verifyReceipt";
const auto shouldRetryWithSandboxUrl = [isProduction = (endpoint != sandboxURL)] (NSDictionary* receiptDetails)
{
if (isProduction)
if (const auto* status = getAs<NSNumber> (receiptDetails[@"status"]))
return [status intValue] == 21007;
return false;
};
[[[NSURLSession sharedSession] dataTaskWithRequest: storeRequest
completionHandler: ^(NSData* responseData, NSURLResponse*, NSError* connectionError)
{
if (connectionError == nullptr)
{
NSError* err = nullptr;
if (NSDictionary* receiptDetails = [NSJSONSerialization JSONObjectWithData: responseData options: 0 error: &err])
{
if (shouldRetryWithSandboxUrl (receiptDetails))
{
verifyReceipt (sandboxURL, requestData);
return;
}
if (NSDictionary* receiptDetails = [NSJSONSerialization JSONObjectWithData: data options: 0 error: &err])
processReceiptDetails (receiptDetails);
else
sendReceiptFetchFail();
}
}];
processReceiptDetails (receiptDetails);
return;
}
}
[task resume];
sendReceiptFetchFail();
}] resume];
}
void processReceiptDetails (NSDictionary* receiptDetails)
{
if (auto receipt = getAs<NSDictionary> (receiptDetails[nsStringLiteral ("receipt")]))
if (auto receipt = getAs<NSDictionary> (receiptDetails[@"receipt"]))
{
if (auto bundleId = getAs<NSString> (receipt[nsStringLiteral ("bundle_id")]))
if (auto bundleId = getAs<NSString> (receipt[@"bundle_id"]))
{
if (auto inAppPurchases = getAs<NSArray> (receipt[nsStringLiteral ("in_app")]))
if (auto inAppPurchases = getAs<NSArray> (receipt[@"in_app"]))
{
Array<Listener::PurchaseInfo> purchases;
@@ -608,14 +623,14 @@ struct InAppPurchases::Pimpl : public SKDelegateAndPaymentObserver
if (auto* purchaseData = getAs<NSDictionary> (inAppPurchaseData))
{
// Ignore products that were cancelled.
if (purchaseData[nsStringLiteral ("cancellation_date")] != nil)
if (purchaseData[@"cancellation_date"] != nil)
continue;
if (auto transactionId = getAs<NSString> (purchaseData[nsStringLiteral ("original_transaction_id")]))
if (auto transactionId = getAs<NSString> (purchaseData[@"original_transaction_id"]))
{
if (auto productId = getAs<NSString> (purchaseData[nsStringLiteral ("product_id")]))
if (auto productId = getAs<NSString> (purchaseData[@"product_id"]))
{
auto purchaseTime = getPurchaseDateMs (purchaseData[nsStringLiteral ("purchase_date_ms")]);
auto purchaseTime = getPurchaseDateMs (purchaseData[@"purchase_date_ms"]);
if (purchaseTime > 0)
{


Loading…
Cancel
Save