Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(ios) On-device receipt validation/parsing #1184

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

dpa99c
Copy link
Collaborator

@dpa99c dpa99c commented Apr 9, 2021

Changes proposed in this pull request (specific to iOS):

  • Relates to [IOS] Function to get the on-device receipt #1170
  • Enables on-device validation/parsing of app store receipts using components from the RMStore library.
    • The decoded receipt payload is attached as a JSON structure to the app store receipt response alongside the base64-encoded binary version.
      • Pulls in the OpenSSL library via Cocoapods to perform the cryptographic decryption operation
    • Adds new setBundleDetails() API function to manually set bundle package name and version (rather than automatically trust the one in the app plist - see here)
  • Supports optional success/error callbacks when calling finish()

Reasoning:

  • Firstly, this is not a replacement for the recommended server-side validation/parsing of app store receipts such as provided by billing.fovea.cc.
    • If you are concerned about security and possibility of exploitation of your paid app features, then you should use server-side validation
  • However, in some circumstances where the in-app products are low-value or niche, server-side validation/parsing is overkill and client-side validation/parsing of the app store receipt within the app is sufficient and easier.
  • This PR adds the ability for the plugin to validate/parse app store receipts on the device; it's then the app developers choice whether to also carry out server-side validation/parsing.

TODO:

  • This PR currently doesn't expose the new functionality in the JS store API, it just adds the functionality to the Objective-C and JS layers of the Cordova plugin API.
  • Maybe an option could be added to as to whether to use the output of on-device receipt parsing to update the store DB?

To test this pull request with cordova:

# 1: Uninstall the plugin (if already installed)
cordova plugin rm cordova-plugin-purchase

# 2: Install from github
cordova plugin add "https://github.com/dpa99c/cordova-plugin-purchase.git#ios_local_receipt"

@j3k0
Copy link
Owner

j3k0 commented Apr 16, 2021

@dpa99c I've read that OpenSSL adds several MB to the size of the app. Is this correct? If so, maybe the feature should be opt-in with an install-time flag?

@dpa99c
Copy link
Collaborator Author

dpa99c commented Apr 16, 2021

@j3k0 yeah, the OpenSSL iOS/arm64 framework weighs in at around 20Mb.
Though I'm not sure how we'd make it an optional addition at installation time since it's included via the <podspec> in config.xml - the Cordova plugin mechanism doesn't really support that.
I guess we could do something similar to what I've done for the diagnostic plugin which is to run a node script on the node postinstall hook in order to comment in/out the relevant portion of config.xml.
Any suggestions how we could do it more easily?

@j3k0
Copy link
Owner

j3k0 commented Apr 16, 2021

Maybe the simplest solution is to maintain a separate branch? (cordova-purchase-plugin-local for example).

I wouldn't want my app to go from under 2MB (actual size of my test app on iOS) to 22MB for a feature I don't even need (when using a server-side validator or no validation at all). Maybe we can ask the cordova team if they have any other suggestions?

@dpa99c
Copy link
Collaborator Author

dpa99c commented Apr 16, 2021

Another option is to try to use the built-in iOS crypto libraries to do the pkcs7 decoding. That way we wouldn't need to include OpenSSL at all.
This gist is pretty old but contains an implementation for OSX so similar libraries to iOS. Maybe there's an up-to-date fork for iOS.
The RMStore library I've used is quite convenient so it might be possible to swap out just the crypto operation and use the rest of the library.
I'll look into it when I get a bit of time.

@stale
Copy link

stale bot commented Apr 17, 2022

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.

@stale stale bot added the wontfix label Apr 17, 2022
@stale stale bot removed the wontfix label Oct 3, 2022
@dpa99c dpa99c changed the title (ios) WIP: On-device receipt validation/parsing (ios) On-device receipt validation/parsing Oct 3, 2022
@dpa99c
Copy link
Collaborator Author

dpa99c commented Oct 3, 2022

@j3k0 I've updated this PR branch onto your latest master branch and also made the inclusion of the iOS receipt validation functionality optional via a plugin variable:

By default, it will not be enabled and therefore the large OpenSSL library will not be pulled into the app build.

To enable the functionality, you must do so with a plugin variable at plugin installation time:

cordova plugin add cordova-plugin-purchase --variable LOCAL_RECEIPT_VALIDATION=true

Since some references are made to the local validation classes in the InAppPurchase class, when the functionality is disabled the plugin includes stubs of the local validation classes to keep the compiler happy.

Hopefully this should provide a way you will consider acceptable of make the functionality available to those who want it without adversely affecting other plugin users who don't want to use it.
If you have time, please take a look at the changes in the PR and let me know your thoughts.

@dpa99c dpa99c force-pushed the ios_local_receipt branch 2 times, most recently from 900c221 to cbb7082 Compare November 20, 2023 11:55
@dpa99c
Copy link
Collaborator Author

dpa99c commented Nov 20, 2023

@j3k0 I've updated the PR branch to align with latest (v13) of the plugin - any reason not to merge this now?

It's an opt-in feature so by default is disabled and the plugin will behave as it currently does, with the iOS receipt validation functionality stubbed out. It's only activated if the user installs the plugin with the specified plugin variable above.
Therefore I can see no negative consequences for the existing implementation if this feature is merged.

@dpa99c dpa99c force-pushed the ios_local_receipt branch 4 times, most recently from 6cd9bb5 to c610581 Compare November 22, 2023 15:30
…ture (disabled by default) which is enabled via a plugin variable
@j3k0
Copy link
Owner

j3k0 commented Nov 23, 2023

Hey @dpa99c - this is nice.

I think this should be a separate plugin (the way braintree support is added to this plugin by installing "cordova-plugin-purchase-braintre"). This way there's no need to hack into the plugin xml file, which I think might backfire on non-pure cordova platforms (capacitor, monaca, ...)

I'm busy finalizing another project, then I will look into this right after.

@dpa99c
Copy link
Collaborator Author

dpa99c commented Nov 23, 2023

@j3k0 I've tweaked the npm postinstall script this PR introduces so it looks at package.json for the plugin variable to activate iOS local receipt verification, and ignores any error if config.xml does not exist.

This allows it to work in a Capacitor project (which I have tested - not sure about Monaca) by adding the following block to package.json (which Cordova CLI adds to a Cordova project):

{
  "cordova": {
    "plugins": {
      "cordova-plugin-purchase": {
        "LOCAL_RECEIPT_VALIDATION": "true"
      }
    }
  }
}

I looked into whether the dependency on OpenSSL could be eliminated by using the built-in iOS crypto libraries but unfortunately they don't support the PCKS7 operations required to decrypt the receipt.

As to publishing this as a different plugin, that would require keep it in sync with the main plugin which isn't something I'd have to for, but maybe someone else is willing to take on that maintenance?

@JothikannanC
Copy link

JothikannanC commented Dec 21, 2023

why not merge this? Apple Store deprecated their [verifyreceipt], it would be good option

@hooliapps
Copy link

Hello

Do you have any working example code please ?

For Auto renewable subscription, one product only, i just need the expiry date or also the purchase data will be ok.

  • Restore purchases options

cordova plugin add "https://github.com/dpa99c/cordova-plugin-purchase.git#ios_local_receipt" --variable LOCAL_RECEIPT_VALIDATION=true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants