Closed metalllus closed 3 years ago
@metalllus payWithGooglePay/payWithApplePay is removed in v3, but reason is not unnecessary. It's because everything was remade and refactored.
Will implements. But I won't have time to implement it right away, but welcome to create a pull request.
If you can, please tell me why it is not convenient to have a PaymentSheet.
If you can, please tell me why it is not convenient to have a PaymentSheet.
For me, it is a question of UI design and functionality. When I coded my PWA I made a custom implementation of the payment interface thru Stripe Elements to fit my site both design-wise and functionality-wise. When I upgraded the PWA to Ionic hybrid app I found out that everything I had prepared works fine, the only thing that does not work is invoking the GooglePay/Apple Pay interface on mobile to get the paymentMethod to use in Stripe.js confirmCardPayment() method to finish the payment. This cannot be done via the PaymentRequest in Stripe.js, on mobile it simply does not work. Hence it would be totally awesome to have the possibility to do just these things:
This way all the people who have their custom implementation up and running with Stripe.js would need to change only a few lines of code to make their Google Pay/Apple Pay working on mobile and could continue using their web implementation because as I said everything else works fine on Ionic, no need to use the payment sheet.
Hi - I haven't looked too deeply into this plugin, but what @metalllus says seems to absolutely hit the nail on the head - I want to be able design my own flow, and when the time comes the Apple or Google pay native UI is called from this Capacitor plugin, which then lets me do with the payment information what I wish.
@metalllus, not sure how you use stripe.js in mobile project. It will be working on web but won't work in mobile apps. Could you let me know how?
@Phoenix-Alpha I use it the same way as on the web, no changes whatsover. After all, when porting my app from a web Angular PWA to Ionic native, the only features one needs to change are the ones using native device features, i. e. geolocation, camera, etc. In case of Stripe, the only part that relies on native device features is the call to Apple Pay/Google Pay. Everything else can be done with the Stripe.js web library. Tested with iPhone and Android simulators. Therefore the only thing I need from this plugin is to call the Apple Pay/Google Pay native interface to get the payment method to be used afterwards to confirm the Apple Pay/Google Pay payment.
@metalllus, thanks for your explanation. AFAIK, stripe.js is only working on websites hosted on https in live mode. It works on non-https though in test mode. Not sure your app is working fine in live mode?
@Phoenix-Alpha You are absolutely right my friend, my bad. I did not take into account the https requirement in live mode and did not test for that, unfortunately :( Thanks a million for setting me straight.
I just upgraded to v1.1.0 of @capacitor-community/stripe to see if apple pay works. I guess not. Looks great though otherwise.
I have the same issue with my Ionic app in that I need to support Apple pay to be allowed to accept donations in the app store. All other payment functions are working fine using Stripe.js.
I had this working with the previous version of @capacitor-community/stripe but it required a merchantId whereas Apple Pay on Stripe.js does not require a merchantId.
Unfortunately the only way to use Apple pay on Stripe.js is outside of the Ionic app then via a success url to a webpage and finally back to the app with a deeplink. Not a great user experience and not sure if it would pass the app review process.
So I am still looking for solutions.
Any near term plans to add apple and google pay?
Support Apple Pay with https://github.com/capacitor-community/stripe/releases/tag/v3.1.0
GooglePay's reference: https://stripe.com/docs/google-pay
@madmacc
Any near term plans to add apple and google pay?
Apple Pay is supported with v3.1.0. We will support Google Pay, too. I will work when I have time, but I won't have time to implement it right away. Welcome create a pull request.
Just a reminder for everybody viewing this thread - I was wrong and javascript SDK WILL NOT work in ionic native environment. It is quite deceiving becausing everything works fine in development mode but once you switch to production, the stripe javascript sdk starts demanding HTTPS and you are done. There is no way to get around it in ionic native environment, as far I know. Therefore I had to switch to the payment sheet provided by this plugin as I could not find any other way to make payments work on native.
@rdlabo Awesome that's great thanks for the hard work. I'll give Apple Pay a try this week. Google pay is not such a priority for me.
@metalllus Yes but that is just for Apple pay as it requires https://. A webview (Ionic) or iFrame and is blocked by Stripe as it requires the request urlScheme to be https:// and Ionic uses a local urlScheme of capacitor:// not https:// All other Stripe.js functionality works fine from Ionic.
I actually submitted a request to Stripe to allow capacitor:// and they said it is in the list to be reviewed but I doubt they will implement it.
@madmacc you mean that standard card payments implemented via the javascript SDK work for you in production mode on native devices (iOS and Android) in Ionic/Capacitor? In my solution I implemented card payments with Stripe Elements to generate fields for the user to enter card information, in dev mode everything works fine including the payment itself but in production mode, the Stripe Elements card fields do not even get displayed.
@metalllus Yes they work fine. I use various Stripe Elements and other various calls to get products, payment methods etc. I have this in a production mobile app and it has worked for around 5000 users.
To clarify what do you mean by production mode vs dev mode? I am using an Ionic prod build and using a live stripe account.
@madmacc I've found the same thing. I naively switched my app over to a device-hosted capacitor build (previously we were showing an online webpage, basically) and Stripe has continued to work, including showing elements. We still get the warning about live mode over http but creating a new setupIntent has continued to work, so 🤷 I have no idea what the real limitations are.
@danproudfoot The only limitation I have found so far has been Apple Pay. The only solutions I have found for Apple pay are to use this Capacitor plugin or to redirect the user externally to a web page to use apple pay and then on completion use a deep link via a web page to take them back to the app.
@rdlabo hi, two questions/observations:
@madmacc today I dug deeper and yes, the card payments do indeed work on native platforms via the javascript SDK, I managed to make a real payment on the iPhone emulator.
@metalllus
how is the isApplePayAvailable() method
I forgot implement isApplePayAvailable
method. I fixed https://github.com/capacitor-community/stripe/releases/tag/v3.1.1
the ApplePayEventsEnum.Completed listener fires
Sorry, this is my mistake: https://github.com/capacitor-community/stripe/commit/2f02b9c423fe370953471e8a61f52019168bec1d
This event is Canceled(fixed v3.1.2). Stripe may returned userCancellation
. Is there an error in the log of Xcode? ??
@rdlabo I tested this on an iPhone emulator and a real ios device. It appears to work on the emulator although I did not put the payment through. On the real device I get the error below on Stripe.presentApplePay and it does not display it.
I am using development Stripe Mode not live.
ERROR MESSAGE: {"errorMessage":"STPApplePayContext is failed","message":"STPApplePayContext is failed"}
⚡️ [error] - {"errorMessage":"STPApplePayContext is failed","message":"STPApplePayContext is failed"}
⚡️ [error] - ERROR {"rejection":{"errorMessage":"STPApplePayContext is failed"},"promise":{"__zone_symbol__state":0,"__zone_symbol__value":"..."},"zone":{"_parent":{"_parent":null,"_name":"<root>","_properties":{},"_zoneDelegate":{"_taskCounts":{"microTask":0,"macroTask":0,"eventTask":0},"zone":"...","_parentDelegate":null,"_forkZS":null,"_forkDlgt":null,"_forkCurrZone":null,"_interceptZS":null,"_interceptDlgt":null,"_interceptCurrZone":null,"_invokeZS":null,"_invokeDlgt":null,"_invokeCurrZone":null,"_handleErrorZS":null,"_handleErrorDlgt":null,"_handleErrorCurrZone":null,"_scheduleTaskZS":null,"_scheduleTaskDlgt":null,"_scheduleTaskCurrZone":null,"_invokeTaskZS":null,"_invokeTaskDlgt":null,"_invokeTaskCurrZone":null,"_cancelTaskZS":null,"_cancelTaskDlgt":null,"_cancelTaskCurrZone":null,"_hasTaskZS":null,"_hasTaskDlgt":null,"_hasTaskDlgtOwner":null,"_hasTaskCurrZone":null}},"_name":"angular","_properties":{"isAngularZone":true},"_zoneDelegate":{"_taskCounts":{"microTask":0,"macroTask":0,"eventTask":13},"zone":"...","_parentDelegate":"...","_forkZS":null,"_forkDlgt":null,"_forkCurrZone":null,"_interceptZS":null,"_interceptDlgt":null,"_interceptCurrZone":null,"_invokeZS":{"name":"angular","properties":"..."},"_invokeDlgt":"...","_invokeCurrZone":"...","_handleErrorZS":"...","_handleErrorDlgt":"...","_handleErrorCurrZone":"...","_scheduleTaskZS":{"name":""},"_scheduleTaskDlgt":"...","_scheduleTaskCurrZone":"...","_invokeTaskZS":"...","_invokeTaskDlgt":"...","_invokeTaskCurrZone":"...","_cancelTaskZS":"...","_cancelTaskDlgt":"...","_cancelTaskCurrZone":"...","_hasTaskZS":"...","_hasTaskDlgt":"...","_hasTaskDlgtOwner":"...","_hasTaskCurrZone":"..."}},"task":{"type":"microTask","state":"notScheduled","source":"Promise.then","zone":"angular","runCount":0}}
@rdlabo I tested this on an iPhone emulator and a real ios device. It appears to work on the emulator although I did not put the payment through. On the real device I get the error below on Stripe.presentApplePay and it does not display it.
I am using development Stripe Mode not live.
ERROR MESSAGE: {"errorMessage":"STPApplePayContext is failed","message":"STPApplePayContext is failed"} ⚡️ [error] - {"errorMessage":"STPApplePayContext is failed","message":"STPApplePayContext is failed"} ⚡️ [error] - ERROR {"rejection":{"errorMessage":"STPApplePayContext is failed"},"promise":{"__zone_symbol__state":0,"__zone_symbol__value":"..."},"zone":{"_parent":{"_parent":null,"_name":"<root>","_properties":{},"_zoneDelegate":{"_taskCounts":{"microTask":0,"macroTask":0,"eventTask":0},"zone":"...","_parentDelegate":null,"_forkZS":null,"_forkDlgt":null,"_forkCurrZone":null,"_interceptZS":null,"_interceptDlgt":null,"_interceptCurrZone":null,"_invokeZS":null,"_invokeDlgt":null,"_invokeCurrZone":null,"_handleErrorZS":null,"_handleErrorDlgt":null,"_handleErrorCurrZone":null,"_scheduleTaskZS":null,"_scheduleTaskDlgt":null,"_scheduleTaskCurrZone":null,"_invokeTaskZS":null,"_invokeTaskDlgt":null,"_invokeTaskCurrZone":null,"_cancelTaskZS":null,"_cancelTaskDlgt":null,"_cancelTaskCurrZone":null,"_hasTaskZS":null,"_hasTaskDlgt":null,"_hasTaskDlgtOwner":null,"_hasTaskCurrZone":null}},"_name":"angular","_properties":{"isAngularZone":true},"_zoneDelegate":{"_taskCounts":{"microTask":0,"macroTask":0,"eventTask":13},"zone":"...","_parentDelegate":"...","_forkZS":null,"_forkDlgt":null,"_forkCurrZone":null,"_interceptZS":null,"_interceptDlgt":null,"_interceptCurrZone":null,"_invokeZS":{"name":"angular","properties":"..."},"_invokeDlgt":"...","_invokeCurrZone":"...","_handleErrorZS":"...","_handleErrorDlgt":"...","_handleErrorCurrZone":"...","_scheduleTaskZS":{"name":""},"_scheduleTaskDlgt":"...","_scheduleTaskCurrZone":"...","_invokeTaskZS":"...","_invokeTaskDlgt":"...","_invokeTaskCurrZone":"...","_cancelTaskZS":"...","_cancelTaskDlgt":"...","_cancelTaskCurrZone":"...","_hasTaskZS":"...","_hasTaskDlgt":"...","_hasTaskDlgtOwner":"...","_hasTaskCurrZone":"..."}},"task":{"type":"microTask","state":"notScheduled","source":"Promise.then","zone":"angular","runCount":0}}
In my case, on the emulator everything works fine and the payment goes through no problem. On real device though I have exactly the same issue as @madmacc.
This is similar trouble??: https://stackoverflow.com/questions/31525861/apple-pay-pkpaymentauthorizationviewcontroller-always-returning-nil-when-loaded
Or this pull request: https://github.com/tipsi/tipsi-stripe/pull/89/files
Maybe reject response is here: https://github.com/capacitor-community/stripe/blob/master/ios/Plugin/ApplePay/ApplePayExecutor.swift#L70
@rdlabo @madmacc Ok guys, I am sorry. The problem was caused by my mistake. I did not know the mechantDisplayName in the createApplePay() method should actually hold the merchantIdentifier. The property name is not ideal, it is quite confusing because I think the displayName is something else. But once I entered the merchant ID, everything works.
@metalllus Yes, great!! Thanks your confirm. And this is right, label of merchantDisplayName
is wrong. I will fix this. Thanks.
@rdlabo suggestion: wouldn't it be better if the isApplePayAvailable()
method resolved with true
if applePay is available and with false
if it is not available? Then it would be cleaner to use with async/await
syntax to avoid having to use .then()
.
@metalllus I had done the same thing and not put the merchant Id in. Good spotting.
I have almost got it working now. I am using a connected Stripe account that is connected to my platform Stripe account to put the payment through to so it is a bit more complicated. I have set up the merchant id in Apple and merchant certificate in Stripe.
I will give it another try later this week.
The payments showing up under the connected account as incomplete "The customer has not entered their payment method.". I get the following error in Xcode from the connected device:
To Native -> Stripe presentApplePay 133613050
2021-08-31 09:30:31.389685+1200 App[63628:3882226] [connection] nw_endpoint_handler_set_adaptive_read_handler [C4.1.1 142.250.71.78:443 ready channel-flow (satisfied (Path is satisfied), viable, interface: en0, ipv4, dns)] unregister notification for read_timeout failed
2021-08-31 09:30:31.389920+1200 App[63628:3882226] [connection] nw_endpoint_handler_set_adaptive_write_handler [C4.1.1 142.250.71.78:443 ready channel-flow (satisfied (Path is satisfied), viable, interface: en0, ipv4, dns)] unregister notification for write_timeout failed
2021-08-31 09:30:39.930607+1200 App[63628:3881287] LOG ANALYTICS: ["analytics_ua": "analytics.stripeios-1.0", "app_name": "App", "shipping_type": "shipping", "required_billing_address_fields": "zip", "app_version": "1.0", "publishable_key": "unknown", "ocr_type": "none", "event": "stripeios.token_creation", "bindings_version": "21.5.1", "required_shipping_address_fields": "none", "company_name": "App", "additional_info": [], "device_type": "iPhone10,4", "token_type": "card", "ui_usage_level": "partial", "product_usage": ["STPApplePayContext"], "os_version": "14.6", "apple_pay_enabled": 1, "apple_merchant_identifier": "unknown", "additional_payment_methods": "none"]
2021-08-31 09:30:40.147544+1200 App[63628:3882226] [connection] nw_endpoint_handler_set_adaptive_read_handler [C5.1.1 13.55.153.188:443 ready channel-flow (satisfied (Path is satisfied), viable, interface: en0, ipv4, dns)] unregister notification for read_timeout failed
2021-08-31 09:30:40.147767+1200 App[63628:3882226] [connection] nw_endpoint_handler_set_adaptive_write_handler [C5.1.1 13.55.153.188:443 ready channel-flow (satisfied (Path is satisfied), viable, interface: en0, ipv4, dns)] unregister notification for write_timeout failed
2021-08-31 09:30:40.215131+1200 App[63628:3882226] CredStore - performQuery - Error copying matching creds. Error=-25300, query={
class = inet;
"m_Limit" = "m_LimitAll";
ptcl = htps;
"r_Attributes" = 1;
sdmn = Stripe;
srvr = "api.stripe.com";
sync = syna;
}
My code: The payment intent is created with a connectedStripeAccountId.
const paymentIntent = await this.stripeService.createPaymentIntentApplePayTest(this.member, 100);
return await Stripe.createApplePay({
paymentIntentClientSecret: paymentIntent.client_secret,
paymentSummaryItems: [{
label: 'Hivepass test payment',
amount: 1.00
}],
merchantIdentifier: 'merchant.app.hivepass.applepaytest',
countryCode: 'NZ',
currency: 'NZD',
});
@madmacc yea, I think your error is not related to the plugin itself, it must have something to do with your nonstandard stripe use case. The way you use the plugin is exactly the same as mine, I see no problem there.
@metalllus Agreed. I'm sure it would work with a standard account. I may need a to use a merchant id for each connected account rather than the platform account. Hopefully not though as I plan to have 1000's of connected accounts. I will check with Stripe support.
@rdlabo could you please give us a rough estimate, how long it will take you to add also google pay? A few weeks, a month...?
@metalllus
suggestion: wouldn't it be better if the isApplePayAvailable() method resolved with true if applePay is available and with false if it is not available? Then it would be cleaner to use with async/await syntax to avoid having to use .then().
Capacitor API has Unimplemented
method: https://capacitorjs.com/docs/plugins/ios
So we should not get false
.
If you want to get true/false, please run this code:
const result = await Stripe.isApplePayAvailable().then(() => true).catch(() => false);
I want to use Capacitor's API correctly as much as possible.
@metalllus I'd like to work this month, but I don't know. I welcome pull request as there are limits to what I can do on my own.
@metalllus
suggestion: wouldn't it be better if the isApplePayAvailable() method resolved with true if applePay is available and with false if it is not available? Then it would be cleaner to use with async/await syntax to avoid having to use .then().
Capacitor API has
Unimplemented
method: https://capacitorjs.com/docs/plugins/ios So we should not getfalse
.If you want to get true/false, please run this code:
const result = await Stripe.isApplePayAvailable().then(() => true).catch(() => false);
I want to use Capacitor's API correctly as much as possible.
Understood, thank you.
@metalllus I may understood how to implements google pay. will release in this week !
@metalllus I may understood how to implements google pay. will release in this week !
@rdlabo great man, you're the best
@metalllus released at next version: https://github.com/capacitor-community/stripe/pull/97#issuecomment-913093412
But I don't have Android Device, so I can't test what is work. Google Pay can't use at emulator... If someone confirms to work, I will release it in the main.
@rdlabo I tested using the Stripe test environment, on emulator the GooglePay interface is displayed fine, I confirm payment, stripe tries to display some sort of a hook screen on emulator and then my app crashes. I see no error in the Android Studio after the crash. However, the payment itself goes through fine. My guess is it crashes when the completed listener fires. My app also crashes if I display the Google Pay interface and cancel the payment with the cancel button in the top left corner - seem like when payment canceled listener fires. Maybe this has something to do with the listeners?
On my real android device, I get this error during app launch.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: sk.myapp.app, PID: 3076
java.lang.IllegalStateException: PaymentConfiguration was not initialized. Call PaymentConfiguration.init().
at com.stripe.android.PaymentConfiguration$Companion.loadInstance(PaymentConfiguration.kt:74)
at com.stripe.android.PaymentConfiguration$Companion.getInstance(PaymentConfiguration.kt:66)
at com.stripe.android.googlepaylauncher.GooglePayLauncher.
I added
<meta-data android:name="com.google.android.gms.wallet.api.enabled" android:value="true" />
<meta-data android:name="com.getcapacitor.community.stripe.country_code" android:value="@string/country_code"/>
<meta-data android:name="com.getcapacitor.community.stripe.merchant_display_name" android:value="@string/merchant_display_name"/>
<meta-data android:name="com.getcapacitor.community.stripe.google_pay_is_testing" android:value="@bool/google_pay_is_testing"/>
under manifest/application to AndroidManifest.xml
and
<string name="country_code">SK</string>
<string name="merchant_display_name">Widget Store</string>
<bool name="google_pay_is_testing">true</bool>
to strings.xml
@metalllus Thanks for testing.
Did you run initialize first??
Stripe.initialize({
publishableKey: "Your Publishable Key""",
});
And I did some update now(I don't know if it resolve error). Please try v3.2.0-4
. Thanks.
@rdlabo I did initialize, yes. First I initialize, then check if google pay is available and if yes, only then I display GooglePay button. It all functions great on the emulator, the payment succeeds. This time on your new version v3.2.0-4, the payment succeeds and the completed listener never fires so the app does not crash. The cancel button still crashes the app.
When I run the same code on a real device I get the error I sent you during build in Android Studio, the app does not compile at all. No change in v3.2.0-4.
@metalllus
the app does not compile at all. No change in v3.2.0-4.
I understood. for Google Pay, we may need initialize in plugin load. I will work.
@metalllus released v3.2.0-5. This version require new variables:
<string name="publishable_key">Your Publishable Key</string>
<bool name="enable_google_pay">true</bool>
<meta-data
android:name="com.getcapacitor.community.stripe.publishable_key"
android:value="@string/publishable_key"/>
<meta-data
android:name="com.getcapacitor.community.stripe.enable_google_pay"
android:value="@bool/enable_google_pay"/>
How about work?? (This development may difficult without Andoid real devices ...)
@rdlabo Ok, we are making progress, now we have exactly the same behavior on the emulator and on real device. The app compiles, the payment is successful. The only problem we have is that the listeners do not fire at all. Everything else seems to work fine. I have experienced no app crashes. If you manage to fix the listeners I think we are done.
To add the listeners, I use
Stripe.addListener(GooglePayEventsEnum.Completed, () => {
...
});
@metalllus Really?! Thanks for awesome news!! I was wondering if I would buy a real Android device for thisφ(・・
listeners is fixed v3.2.0-6. This reason is my typo... Please test. Thanks.
@rdlabo Everything works, great. Tested in emulator and on real device. However, all this was tested ONLY with the stripe test environment. If I want to pay with stripe live account, do I have to do this?
With live payments the google-pay-is-testing in strings.xml should be false?
<bool name="google_pay_is_testing">false</bool>
And one final thing, in your docs these to sentences should be exchanged.
@metalllus
If I want to pay with stripe live account, do I have to do this?
Yes. With <bool name="google_pay_is_testing">false</bool>
is changed GooglePayEnvironment.Test
or GooglePayEnvironment.Production
. When you passed process of 5
, please change to true
.
Oh, yes. I will change. Thanks!
@metalllus Can you give screenshot of Google Pay for readme ? Like: https://github.com/capacitor-community/stripe/blob/master/demo/screenshots/apple-pay-ios.png
I remembered I can't shot this...
@rdlabo I do not know why but the Stripe always displays the interface in Slovak language, even if I set country_code to US in strings.xml, it makes no difference. I wanted to switch to English to make you a screenshot in English but it does not work. Maybe my Stripe account settings override this, I am not sure. Why doesn't it work for you in the emulator? In my case everything works no problem.
@metalllus Stripe check device language, may not strings.xml. (in iOS is right). Please try to change device language. thanks.
@rdlabo here you go.
Hi, ok, so this is the thing. I have an Angular Firebase PWA with implemented payments thru Stripe.js (Stripe Elements). When I upgraded my project to Ionic 5 Capacitor, my implementation works (card payments work fine) except for Apple Pay and Google Pay. My question is if it is possible to use your plugin solely to make the Google Pay/Apple Pay payment on native device after the user selects payment with Apple Pay/Google Pay in my UI. I do not need the payment sheet I just need to invoke the Google Pay/Apple Pay on the native device. The web implementation of Stripe.js cannot do this on native device, it works only on the web.