j3k0 / cordova-plugin-purchase

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

[13.X] Question: Where to find raw transaction data after purchase? #1359

Closed nathanielop closed 1 year ago

nathanielop commented 1 year ago

Not a bug or issue, but trying to migrate to 13.X, had my own server-side validation for the receipts previously. As of 13.X, the output on the server side looks like the following for iOS (when passing the result of the finished event into the server; store.when().finished(p => submitToServer(p))

{
  className: 'Transaction',
  transactionId: '2000000XXXX',
  state: 'finished',
  products: [ { id: 'monthly' } ],
  platform: 'ios-appstore',
  originalTransactionId: '200000020XXXX',
  purchaseDate: '2022-12-21T21:13:06.000Z'
}

I understand that I could set store.validator and get the native transaction passed through there, however, our existing flow necessitates that we validate the transaction after it has been approved (and during the user creation process in our API), so we need to have some method for retrieving/passing the native transaction after the validator has completed.

Note there is no data in here to verify. Previously there was txn.appStoreReceipt or txn.purchaseToken which I could use to validate it. I've looked around the API and see the CdvPurchase.AppleAppStore as a potential way to get to the transaction data, but not sure what is the best way to do so. As this plugin just recently moved to 13.X, there is also no documentation on the guide regarding self-validation.

Thanks.

j3k0 commented 1 year ago

Hi,

The validator is called after the transaction has been approved. The normal flow is "approved > (eventual validator) > verified > finished".

If you don't set a validator, the product will generally just go from "approved" to "finished".

I don't advise the approach (not only me, I believe Apple and Google wouldn't as well), because in principle you should finish a transaction only AFTER delivery, which is generally when the receipt is validated. The call to finish is to acknowledge that you processed the transaction and delivered the virtual good / feature.

Documentation for the validation function is here: https://github.com/j3k0/cordova-plugin-purchase/blob/master/api/interfaces/CdvPurchase.Validator.Function.md (with details on the input and output of the function by checking the types passed to the function)

nathanielop commented 1 year ago

Makes sense I guess. I was waiting until finishing the transaction before creating the subscription, but I guess I should create the subscription during the verification step and then finish after the subscription is created. I guess the term "verify" just tripped me up because it felt like a separate step from delivering the product.

rdlabo commented 1 year ago

For my product subscription, I needed to send appStoreReceipt and purchaseToken to the backend. You can get the data by doing the following.

CdvPurchase.store.when()
    .verified(async (receipt) => {
        if (this.platform.is('ios')) {
          const { appStoreReceipt } = (receipt.sourceReceipt as CdvPurchase.AppleAppStore.SKApplicationReceipt).nativeData;
        } else  if (this.platform.is('android')) {
          const { purchaseToken  } = (receipt.sourceReceipt as CdvPurchase.GooglePlay.Receipt);
        }
      })
  });