[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
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

Add in-app purchase for MacOS #11292

Merged
merged 17 commits into from
Jan 10, 2018
Merged

Conversation

AdrienFery
Copy link
Contributor

In order to release a commercial application on the Mac Apple Store, it must use in-app purchase (see App Store Guidelines). It is why I have added the in-app purchase feature for MacOS into Electron. I have tested the build and it works well but I didn't implement automatic tests.

Let me know if you see some modifications to do.

See in-app-purchase.md for the module documentation.

screen shot

@AdrienFery AdrienFery requested review from a team November 30, 2017 13:29
@holgersindbaek
Copy link

Looking forward to seeing this in production... a much needed feature for Electron!

@holgersindbaek
Copy link

Can anyone merge this or tell me what needs to be done before it can be merged?

Copy link
Member
@jkleinsc jkleinsc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AdrienFery it looks like our CI is failing because of incorrectly formatted code. You can run npm run lint locally to identify the formatting issues.

filenames.gypi Outdated
'atom/browser/in_app_purchase.h',
'atom/browser/in_app_purchase_mac.mm',
'atom/browser/in_app_purchase_observer.h',
'atom/browser/in_app_purchase_observer_mac.mm',
'atom/browser/atom_browser_main_parts.cc',
'atom/browser/atom_browser_main_parts.h',
'atom/browser/atom_browser_main_parts_mac.mm',
Copy link
Contributor
@alexeykuzmin alexeykuzmin Nov 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feature will never be used on any platform other than macOS,
can you please put all of its files under a OS check at the bottom of the file?
You will need to create a new section ['OS=="mac"', { right under the ['OS=="win"', {.

UPD Files with "_mac" suffix are already fine, they won't used on any other platform,
but I guess we need to filter the other files too.

}

if (typeof quantity !== 'number') {
quantity = 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}

if (typeof callback !== 'function') {
callback = function() {};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please handle absence of a callback on the native side.
It doesn't make much sense to create and call an empty function.

return binding.getReceiptURL();
},

purchaseProduct: function(productID, quantity, callback) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to allow this method to be called in forms
purchaseProduct(someId, 2) and purchaseProduct(someId, function() {}),
you will have to check the type of the second argument to decide if it is quantity or callback.

You can do it like this:

if (typeof quantity == 'function') {
  quantity = 1
  callback = quantity
}

@@ -8,6 +8,7 @@ module.exports = [
{name: 'dialog', file: 'dialog'},
{name: 'globalShortcut', file: 'global-shortcut'},
{name: 'ipcMain', file: 'ipc-main'},
{name: 'inAppPurchase', file: 'in-app-purchase'},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It also should be available on macOS only.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should I do to restrict this to macOS only ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, there's not existing way to do it. I guess I or somebody else can add it after this PR is merged.
Let's skip it for now.

@alexeykuzmin
Copy link
Contributor

but I didn't implement automatic tests.

It means that it will be broken soon.

@AdrienFery
Copy link
Contributor Author

@alexeykuzmin Any idea how to implement automatic tests ? I don't think that it is possible to interact with the Apple Store Dialog to sign in and to confirm the purchase.

@alexeykuzmin
Copy link
Contributor

Any idea how to implement automatic tests ? I don't think that it is possible to interact with the Apple Store Dialog to sign in and to confirm the purchase.

@zcbenz @deepak1556 any ideas how this feature can be tested?

@AdrienFery
Copy link
Contributor Author

The built on jenkins failed. I don't understand why. I just tested to built on my Mac and it works.

@jkleinsc
Copy link
Member
jkleinsc commented Dec 4, 2017

@AdrienFery Electron uses the macOS 10.10 SDK to build (see https://electronjs.org/docs/development/build-instructions-osx#macos-sdk) which is why the build failed in CI. This code change needs to be compatible with the macOS 10.10 SDK.

@zcbenz zcbenz self-assigned this Jan 10, 2018
@zcbenz
Copy link
Contributor
zcbenz commented Jan 10, 2018

Currently we don't have a way to test things that require code sign, we are simply relying on users to test them, for example the Handoff feature and the Mac App Store build.

I'll add a few simple tests for the APIs to verify the methods actually exist.

@zcbenz
Copy link
Contributor
zcbenz commented Jan 10, 2018

I'm going to turn inAppPurchase to an EventEmitter to make it easier to extend the APIs in future.

@holgersindbaek
Copy link

@zcbenz Ok. Is it possible to somehow build a production ready app using the GitHub master branch of electron?

@sferoze
Copy link
sferoze commented Jan 18, 2018

@holgersindbaek @zcbenz I am with you here. I would like to build a production-ready app which includes this merge for IAP.

I need to submit my app ASAP, so being able to just build and use this version would be great. Currently, I use the production version of electron using NPM. In the past, I have added NPM packages which point to git URLs. Wonder if that is possible here... or if we need to build it first?

@holgersindbaek
Copy link

@sferoze I've tried to see if I could build a production app using the GitHub version of Electron, but it doesn't seem to be possible. Electron seem to always use the officiel version of Electron to build for production.

You can build for development using the GitHub version, but not for production.

@sferoze
Copy link
sferoze commented Jan 18, 2018

@holgersindbaek thanks a lot for the info. this was really helpful in bringing light to the current status of the issue

@nabati
Copy link
nabati commented Jan 25, 2018

Thank you for the PR, it's been educational.

We have another use case which also makes use of StoreKit; according to Apples guidelines, it won't be allowed to have custom prompts that request reviews, but one should make use of the requestReview method.

I'm wondering

  • If exposing that method can fit within this module as it is.
  • If exposing that method would fit in this module if it was renamed to something more general such as StoreKit, and move the existing methods to StoreKit.inAppPurchase.
  • If we should create a separate module for that thin slice of the API.

What are you're thoughts?

@AdrienFery
Copy link
Contributor Author

If you want to add more StoreKit features, I think that the module should be renamed to something more general.

@holgersindbaek
Copy link

Any news on when this will go into the official version of Electron?

@AdrienFery
Copy link
Contributor Author
AdrienFery commented Feb 20, 2018

@sferoze In StoreKit, In-App Purchase doesn't have any subscription method. You can use subscription directly with this implementation.

The SKProductSubscriptionPeriod class contains only information about the subscription duration of the product.

Class SKProductSubscriptionPeriod
An object containing the subscription period duration information.

@zeke
Copy link
Contributor
zeke commented Feb 20, 2018

@holgersindbaek we are shooting for a 2.0 beta this week. If I'm not mistaken, this change should land in that release.

@yuri-karkh
Copy link

Hi guys, is there any guide exists? I try to const remote = require( 'electron' ).remote and remote.inAppPurchase.addTransactionListener is undefined, I don't see this method neither via console.log( remote.inAppPurchase ). Any advice?
inapppurchase object

@AdrienFery
Copy link
Contributor Author

Remark: I have added a method GetProducts to this module in my local fork. It allows to get the products (see SKProduct) and the local formatted price of the product. I will create a pull request pretty soon to add this feature and to improve the documentation.

@yuri-karkh Which version of Electron do you use ?

@yuri-karkh
Copy link

I used 2.0.0-beta1 @AdrienFery as it was released only in this new version

@AdrienFery
Copy link
Contributor Author
AdrienFery commented Feb 27, 2018

@yuri-karkh You should listen for the transactions-updated event instead.

const remote = require( 'electron' ).remote;
remote.inAppPurchase.on('transactions-updated', transactionListener);

@zeke
Copy link
Contributor
zeke commented Feb 27, 2018

I will create a pull request pretty soon to add this feature and to improve the documentation.

👍

If you could also add a short tutorial in docs/tutorial/in-app-purchases.md with some basic sample code, that would be 💯

@AdrienFery AdrienFery deleted the in-app-purchase branch March 8, 2018 15:49
@yuri-karkh
Copy link

Hi @AdrienFery, could u please advice:
require('electron').remote.inAppPurchase.purchaseProduct("some.product.id",1,function(e){}); calling this method has no any effect as I see, is there anything else I should care about before this call? (v2.0.0-beta5)

@yuri-karkh
Copy link

hi @AdrienFery sorry to bother u again, but have a question again if u have a minute:
I use electron@2.0.0-beta.7, I have changed Info.plist to my bundle id (double checked) and when I calling inAppPurchase.productPurchase nothing happens now. Also tested canMakePayments, getReceiptURL methods they look ok. No errors in console.

console

@AdrienFery
Copy link
Contributor Author

@yuri-karkh What is your bundleID and your productID ?

@yuri-karkh
Copy link

bundleID = "com.gentlereader.dev" and productID = "demoprod" @AdrienFery

@JeganMSD
Copy link

As @yuri-karkh said there is no method like getProducts.. @AdrienFery ...
Would you please provide the detailed Tutorial so that developers would feel easy to use this package.

@JeganMSD
Copy link

Thread

23 Crashed:: Dispatch queue: SKProductsRequest reply queue
0 libobjc.A.dylib 0x00007fff8dfbd097 objc_msgSend + 23
1 com.apple.StoreKit 0x0000000106324421 -[SKRequest _sendFinishToDelegate] + 55
2 com.apple.StoreKit 0x00000001063240f4 -[SKRequest _sendFinishedForUserInfo:] + 207
3 com.apple.StoreKit 0x00000001063236ab __47-[SKProductsRequest issueRequestForIdentifier:]_block_invoke + 53
4 libxpc.dylib 0x00007fff948c25cc _xpc_connection_call_event_handler + 58
5 libxpc.dylib 0x00007fff948c11df _xpc_connection_mach_event + 2124
6 libdispatch.dylib 0x00007fff9931eae2 _dispatch_client_callout4 + 9
7 libdispatch.dylib 0x00007fff9931f39c _dispatch_mach_msg_invoke + 143
8 libdispatch.dylib 0x00007fff9931d617 _dispatch_queue_drain + 359
9 libdispatch.dylib 0x00007fff9931e682 _dispatch_mach_invoke + 154
10 libdispatch.dylib 0x00007fff9931d617 _dispatch_queue_drain + 359
11 libdispatch.dylib 0x00007fff9931e9c1 _dispatch_queue_invoke + 110
12 libdispatch.dylib 0x00007fff9931cf87 _dispatch_root_queue_drain + 75
13 libdispatch.dylib 0x00007fff9931e177 _dispatch_worker_thread2 + 40
14 libsystem_pthread.dylib 0x00007fff9624fef8 _pthread_wqthread + 314
15 libsystem_pthread.dylib 0x00007fff96252fb9 start_wqthread + 13

I'm getting this error while I called purchaseProduct()

@JeganMSD
Copy link

Waiting for your faster reply @AdrienFery .Thanks in advance

@sferoze
Copy link
sferoze commented Jun 23, 2018

@JeganMSD @yuri-karkh

With the purchaseProduct() method, you can console.log the response in the callback. It should be true or false if product is valid or not.

This is working for me but the issue I am having is that the response says the product is invalid. Even though I have gone into iTunes Connect and added the subscription just like I have done for iOS.

I think the issue is that you need to call getProducts() before purchaseProduct() otherwise it will always return as an invalid product. @AdrienFery is this correct. You added the getProducts() method and that needs to be called before purchaseProduct() for purchaseProduct() to work?

@JeganMSD
Copy link

yes @sferoze now working fine.I will ask you doubts during development.Thanks for your reply

@holgersindbaek
Copy link

@JeganMSD Some of my users are getting the same error. I can't replicate it, but I'm quite sure it happens when I call "remote.inAppPurchase.getProducts".

I know it happened to you on "purchaseProduct", but what did you do to fix it?

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

Successfully merging this pull request may close these issues.

10 participants