j3k0 / cordova-plugin-purchase

In-App Purchase for Cordova on iOS, Android and Windows
https://purchase.cordova.fovea.cc
1.29k stars 529 forks source link

Missing documentation for Receipt Validation #1530

Open selcukbeyhan opened 2 months ago

selcukbeyhan commented 2 months ago

I saw that for the validation of receipts, there are some options available: Function or Server/Backend. However, there is no documentation about the specification of the expected validator. Otherwise, the plugin tries to verify the receipt various times.

I am running my plugin in DEBUG log level and see my log console is full of messages like this below: ..... ..... ⚡️ [log] - [CdvPurchase.Validator] DEBUG: Validation requests=101 responses=199 ⚡️ [log] - [CdvPurchase] DEBUG: Calling callback: type=receiptUpdated() name=#6417eca207b1ced3763b9bb798bdbc49 reason=adapterListener_receiptsUpdated ⚡️ [log] - LIFEPLANNER Receipt is updated ⚡️ [log] - [CdvPurchase] INFO: verify(Receipt) ⚡️ [log] - [CdvPurchase.Validator] DEBUG: Schedule validation: {"className":"Receipt","transactions":[{"className":"Transaction","transactionId":"appstore.application","state":"finished","products" ..... .....

Reminder of relevant code section:

            private async runOnReceipt(receipt: Receipt, callback: Callback<ReceiptResponse>) {

                if (receipt.platform === Platform.TEST) {
                    this.log.debug('Using Test Adapter mock verify function.');
                    return Test.Adapter.verify(receipt, callback);
                }
                if (!this.controller.validator) {
                    this.incrResponsesCounter();
                    // for backward compatibility, we consider that the receipt is verified.
                    callback({
                        receipt,
                        payload: {
                            ok: true,
                            data: {
                                id: receipt.transactions[0].transactionId,
                                latest_receipt: true,
                                transaction: { type: 'test' } // dummy data
                            }
                        }
                    });
                    return;
                }
                const body = await this.buildRequestBody(receipt);
                if (!body) {
                    this.incrResponsesCounter();
                    return;
                }

                if (typeof this.controller.validator === 'function')
                    return this.runValidatorFunction(this.controller.validator, receipt, body, callback);

                const target: Validator.Target = typeof this.controller.validator === 'string'
                    ? {
                        url: this.controller.validator,
                        timeout: 20000, // validation request will timeout after 20 seconds by default
                    }
                    : this.controller.validator;

                return this.runValidatorRequest(target, receipt, body, callback);
            }
yannickBona commented 2 months ago

@selcukbeyhan If you don't need to validate the receipt on App Load, you can set the need needAppReceipt option to false. If you have subscriptions and you need to validate the receipt to ensure it is not expired, receipt validation on page load is key.

In my case the receipt validation is only triggered when a purchase is made and I let my server handle the rest

await store.initialize([
          {
            platform: Platform.APPLE_APPSTORE,
            options: { needAppReceipt: false },
          },
        ]);
selcukbeyhan commented 2 months ago

@selcukbeyhan If you don't need to validate the receipt on App Load, you can set the need needAppReceipt option to false. If you have subscriptions and you need to validate the receipt to ensure it is not expired, receipt validation on page load is key.

In my case the receipt validation is only triggered when a purchase is made and I let my server handle the rest

await store.initialize([
          {
            platform: Platform.APPLE_APPSTORE,
            options: { needAppReceipt: false },
          },
        ]);

Thanksa. lot for the suggestion. I didnt see that flag. However, do you have any documentation about this server side validation logic? Like an interface contract: what is called when and what values to return, etc.