in-app-purchase icon indicating copy to clipboard operation
in-app-purchase copied to clipboard

[iOS] iap.isValidated() returns false for receipt with "Sandbox validation successful"

Open svzi opened this issue 5 years ago • 9 comments

Hi there!

I'm trying to use this plugin to validate my in-app-purchases. For Android receipt validation my code is working as expected, but for Apple Sandbox receipts it fails, even when the verbose debug output of the plugin tells me, the the receipt has been validated successfully.

I'm using this code (simplified for demonstration purposes):

await iap.setup();
const res = await iap.validate(receipt);
if (iap.isValidated(res)) {
    // get the purchased items that have not been expired or canceled
    const options: any = {
        ignoreCanceled: true,
        ignoreExpired: true,
    };
    const purchaseDataList: any[] = iap.getPurchaseData(googleRes, options);
    if (purchaseDataList.length > 0) {
        let foundValid: boolean = false;
        purchaseDataList.forEach(purchase => {
            console.log('iap.isValidated(purchase):', iap.isValidated(purchase));
            if (iap.isValidated(purchase)) {
                // found valid receipt
                foundValid = true;
            }
        });
    }
}

This is what my console output returns when validating a sandbox receipt (Apple):

[1566490909230][VERBOSE] <Apple> Sandbox validation successful: { receipt: 
   { receipt_type: 'ProductionSandbox',
     adam_id: 0,
     app_item_id: 0,
     bundle_id: 'com.abc.xyq',
     application_version: '1.0.0',
     download_id: 0,
     version_external_identifier: 0,
     receipt_creation_date: '2019-08-22 16:20:41 Etc/GMT',
     receipt_creation_date_ms: '1566490841000',
     receipt_creation_date_pst: '2019-08-22 09:20:41 America/Los_Angeles',
     request_date: '2019-08-22 16:21:49 Etc/GMT',
     request_date_ms: '1566490909209',
     request_date_pst: '2019-08-22 09:21:49 America/Los_Angeles',
     original_purchase_date: '2013-08-01 07:00:00 Etc/GMT',
     original_purchase_date_ms: '1375340400000',
     original_purchase_date_pst: '2013-08-01 00:00:00 America/Los_Angeles',
     original_application_version: '1.0',
     in_app: [ [Object] ] },
  status: 0,
  environment: 'Sandbox',
  sandbox: true }

iap.isValidated(purchase): false

What do I need to make iap.isValidated() return true for this receipt?

Any help would be really much appreciated!

Best, Sven

svzi avatar Aug 22 '19 19:08 svzi

Hello,

iap.isValidated() expects the returned object of iap.validate().

The code below needs to be removed.

console.log('iap.isValidated(purchase):', iap.isValidated(purchase));
            if (iap.isValidated(purchase)) {
                // found valid receipt
                foundValid = true;
            }

Cheers

voltrue2 avatar Aug 22 '19 22:08 voltrue2

Just to be clear, this code would be sufficient:

await iap.setup();
const res = await iap.validate(receipt);
if (iap.isValidated(res)) {
    // found valid receipt
    foundValid = true;
}

No need to call iap.getPurchaseData(googleRes, options); and validate each of the returned objects?

svzi avatar Aug 23 '19 06:08 svzi

Hello, Yes the code you pasted above is sufficient. getPurchaseData() is just a support function that may help make your life simpler but not required.

Cheers!

voltrue2 avatar Aug 26 '19 04:08 voltrue2

Thanks a lot for clarification @voltrue2 !

svzi avatar Aug 26 '19 08:08 svzi

Sorry, I need to bother you again @voltrue2 !

With the code I mentioned here (https://github.com/voltrue2/in-app-purchase/issues/280#issuecomment-524193545), my validation returns true for a sandbox receipt that should not be true in my opinion:

...
<Apple> Try validate against sandbox: https://sandbox.itunes.apple.com/verifyReceipt
<Apple> https://sandbox.itunes.apple.com/verifyReceipt validation response: { auto_renew_status: 0, latest_expired_receipt_info: { original_purchase_date_pst: '2019-09-10 08:30:26 America/Los_Angeles', quantity: '1', unique_vendor_identifier: 'xxx', bvrs: '1.
2019-09-25T06:50:24.042Z 92cb8113-62cb-4e8d-991b-121efcd0ea85 [1569394224042]<Apple> https://sandbox.itunes.apple.com/verifyReceipt validation response: { auto_renew_status: 0,
latest_expired_receipt_info:
{ original_purchase_date_pst: '2019-09-10 08:30:26 America/Los_Angeles',
quantity: '1',
unique_vendor_identifier: 'xxx',
bvrs: '1.2.2',
expires_date_formatted: '2019-09-19 13:41:11 Etc/GMT',
is_in_intro_offer_period: 'false',
purchase_date_ms: '1568896871000',
expires_date_formatted_pst: '2019-09-19 06:41:11 America/Los_Angeles',
is_trial_period: 'false',
item_id: 'yyy',
unique_identifier: 'zzz',
original_transaction_id: 'aaa',
subscription_group_identifier: 'bbb',
transaction_id: 'ccc',
bid: 'this.that',
web_order_line_item_id: 'ccc',
purchase_date: '2019-09-19 12:41:11 Etc/GMT',
product_id: 'ddd',
expires_date: '1568900471000',
original_purchase_date: '2019-09-10 15:30:26 Etc/GMT',
purchase_date_pst: '2019-09-19 05:41:11 America/Los_Angeles',
original_purchase_date_ms: '1568129426000' },
status: 21006,
auto_renew_product_id: 'ddd',
receipt:
{ original_purchase_date_pst: '2019-09-10 08:30:26 America/Los_Angeles',
quantity: '1',
unique_vendor_identifier: 'xxx',
bvrs: '1.2.2',
expires_date_formatted: '2019-09-19 09:41:11 Etc/GMT',
is_in_intro_offer_period: 'false',
purchase_date_ms: '1568882471000',
expires_date_formatted_pst: '2019-09-19 02:41:11 America/Los_Angeles',
is_trial_period: 'false',
item_id: 'yyy',
unique_identifier: 'zzz',
original_transaction_id: 'aaa',
subscription_group_identifier: 'bbb',
transaction_id: 'ccc',
web_order_line_item_id: 'ddd',
version_external_identifier: '0',
purchase_date: '2019-09-19 08:41:11 Etc/GMT',
product_id: 'this.that',
expires_date: '1568886071000',
original_purchase_date: '2019-09-10 15:30:26 Etc/GMT',
purchase_date_pst: '2019-09-19 01:41:11 America/Los_Angeles',
bid: 'this.that',
original_purchase_date_ms: '1568129426000' },
expiration_intent: '1',
is_in_billing_retry_period: '0' }
<Apple> Valid receipt, but has been cancelled (not expired yet)

That receipt is canceled and has expired about 6 days ago. Any idea why this receipt is reported back as valid???

Best, Sven

svzi avatar Sep 25 '19 17:09 svzi

Hello @svzi , Have you resolve this issue? I am facing similar issue. I am always getting true from isValidate()

jayna456 avatar Nov 18 '19 06:11 jayna456

@jayna456 It probably depends on what you're trying to verify. To you validate subscriptions or simple purchases, or both?

svzi avatar Nov 19 '19 07:11 svzi

Hello @svzi , I want to validate subscriptions. I figured out the problem. in getPurchaseData() I am passing ignoreExpired as true. Just removed that and problem solved..

jayna456 avatar Nov 19 '19 16:11 jayna456

@jayna456 👍

svzi avatar Nov 20 '19 09:11 svzi