j3k0 / cordova-plugin-purchase

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

receipt verification responses #801

Closed sebastian-zarzycki-apzumi closed 5 years ago

sebastian-zarzycki-apzumi commented 5 years ago

system info

OSX Mojave 10.14.3 
Cordova-IOS 4.5.5
Device: iPhone iOS 12.1.4
Plugin Version: 7.4.1

Observed behavior

When it comes to receipt/purchase validation, the documentation says that product.verify() can be used in two ways. First is just calling the method and then listening for events. These events are defined as such:

verified(product)
    Called when receipt validation successful
unverified(product)
    Called when receipt verification failed
expired(product)
    Called when validation find a subscription to be expired

It can also be used as a promise, with following results:

    done(function(product){})
        called whether verification failed or succeeded.
    expired(function(product){})
        called if the purchase expired.
    success(function(product, purchaseData){})
        called if the purchase is valid and verified.
        purchaseData is the device dependent transaction details returned by the validator, which you can most probably ignore.
    error(function(err){})
        validation failed, either because of expiry or communication failure.
        err is a store.Error object, with a code expected to be store.ERR_PAYMENT_EXPIRED or store.ERR_VERIFICATION_FAILED.

The last one seems inconsistent, because it says "expiry or comm failure" but just next sentence says, that the code will be either "expiry or verification failed", which is not exactly the same thing. How is it?

Additionally, the server side validation can result in only 3 error codes:

store.INVALID_PAYLOAD   = 6778001;
store.CONNECTION_FAILED = 6778002;
store.PURCHASE_EXPIRED  = 6778003;

What is the exact mapping between all these three? Between event and promise and server response, it would seem that:

verified == success == { ok: true, data: { transaction: <transaction_data_here> }}
unverified == error (?) == { ok: false, data: { code: CONNECTION_FAILED, error: { message: 'Connection failed' }} == { ok: false, data: { code: INVALID_PAYLOAD, error: { message: 'Invalid Paylod' }} 
expired == expired == { ok: false, data: { code: PURCHASE_EXPIRED, error: { message: 'Purchase expired' }}

Is this above above correct? The question is, how to inform from the server, that the receipt/purchase is actually not right, because our own logic (i.e. we've checked with Apple, and the result is fine, but we've noticed that someone is using transaction ids that belong to own another account, etc.) - what should the error response be - PURCHASE_EXPIRED or INVALID_PAYLOAD?

Would INVALID_PAYLOAD and CONNECTION_FAILED both lead to purchase being treated as not validated (unverified)?

What is the consequence of receiving INVALID_PAYLOAD and/or CONNECTION_FAILED? Would the product.owned changed to false? What about the state?

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.