stripe / stripe-terminal-ios

Stripe Terminal iOS SDK
https://stripe.com/docs/terminal/sdk/ios
Other
105 stars 65 forks source link

Tap To Pay reader - Detect merchant is already registered #252

Open AnshulMindbody opened 1 year ago

AnshulMindbody commented 1 year ago

Greetings, we are implementing the 'Tap to Pay' feature in our iOS app. However, I haven't found any information in the Stripe documentation on how to determine whether a user is already registered with Apple. Is there a way to identify this? We ask because we plan to adjust the workflow based on this information; for example, the 'Tap to Pay' option would only be visible to users if the merchant is registered by an admin.

Thanks for your help!

bric-stripe commented 1 year ago

Hi @AnshulMindbody the current recommendation is to attempt to connect with tosAcceptancePermitted set to false in the SCPLocalMobileConnectionConfiguration and check for the SCPErrorAppleBuiltInReaderTOSNotYetAccepted error.

AnshulMindbody commented 1 year ago

@bric-stripe,

Based on your suggestion, we tried setting the tosAcceptancePermitted property to false in the SCPLocalMobileConnectionConfiguration. However, even after initializing it with a false value, querying config.tosAcceptancePermitted subsequently returns true. As a result, the terms and conditions screen remains visible. Here's a snippet of our code:

let config = LocalMobileConnectionConfiguration(locationId: configuration.locationId, merchantDisplayName: configuration.businessName, onBehalfOf: configuration.accountName, tosAcceptancePermitted: false)
print(config.tosAcceptancePermitted) // This unexpectedly outputs true.

We are currently using Stripe SDK 2.23.1. Any guidance or clarification on this matter would be appreciated.

bric-stripe commented 1 year ago

@AnshulMindbody sorry for the trouble here. There's a typo in that initializer's implementation 😞. If you use the LocalMobileConnectionConfigurations designated initializer it should work. So add the returnReadResultsImmediately: true param to that init and it should prevent the typo from incorrectly setting that property.

This is fixed (unintentionally) in our just released 3.0.0 that requires using builders to build the connection configuration instances, but would require other changes. But passing the returnReadResultsImmediately: true should unblock you.

bric-stripe commented 1 year ago

Hi, we just release v2.23.2 that has a fix to that initializer. If you update to that release you won't need the suggested work around. Thanks for reporting!

AnshulMindbody commented 1 year ago

Hi, @bg-stripe thanks for the update I want to use the method that apple has exposed isAccountLinked(using:) documentation.). Is there any way to use this method?

aelbialyclio commented 1 year ago

@bric-stripe I would also like to add if we can use this method from Apple linkAccount(using:) and what would the token value be. We sometimes need to have control on asking the user to accept the terms of service.

bric-stripe commented 1 year ago

Is there any way to use this method?

no, there's no support for this today and the SDK doesn't expose the token that would be needed for this. I'll provide the request for this to the team. It would likely be that the SDK exposes a new method for this. To help prioritize could you outline your use case where linkAccount(using:) would be preferred over connectReader with a connection config using tosAcceptancePermitted: false? Is it convenience for a simpler, non-async single method, or are there scenarios you have that would require this over discover > connect?

aelbialyclio commented 1 year ago

Hi @bric-stripe thank you for your quick response. Yes the use case for us is we are looking to implement Tap To Pay and we have two types of users admins and non-admins. According to Apple's Human Interface Guidelines in this section here:

Present the Tap to Pay on iPhone terms and conditions to the appropriate business representative. Specifically, if your app supports both administrator and nonadministrator accounts, be sure to present the terms and conditions to an administrator. If a nonadministrator tries to activate the feature, present a message explaining that administrator access is required.

Here's the link to this reference: https://developer.apple.com/design/human-interface-guidelines/tap-to-pay-on-iphone#:~:text=Present%20the%20Tap%20to%20Pay%20on%20iPhone%20terms%20and%20conditions%20to%20the%20appropriate%20business%20representative.

To check for if a non admin user is accessing the feature having something like isAccountLinked(using:) would be really useful or even just a boolean property to know if the current user has accepted the terms and conditions. I'm not sure if this is the same use case that @AnshulMindbody has as well

For the:

be sure to present the terms and conditions to an administrator

Having the linkAccount(using:) would allow us to bring up the sheet as Apple has here when a user clicks a button for example.

This would be the scenario we are looking for so we do not have to unnecessarily discover then connect to a reader, it would provide a quicker feedback to our users as well.

I would also like to note that we are using the React Native SDK It would be great if this gets implemented there as well to also have a property or a function in the React Native SDK to know if the terms and conditions have been accepted and to bring up the sheet. I know there's this open issue in that repo as well that would cover this request. If not, we can look to have a native module if we can get some properties or function to know if the user has accepted the terms and conditions and to show the sheet upon clicking a button for example, but having it in the React Native SDK would be ideal.

Hope this helps! It would be really nice to have these functionalities to go with Apple's Human Interface Guidelines. Thank you for all your support! We really appreciate the communication, detail and quick feedback!

thecodeside commented 1 year ago

Good Morning, @bric-stripe Why this ticket was closed without any answer? We also would need this kind of feature. We want it bad :) Current implementation is extremely hard to explain to our users, especially when we have different types of users in our app - admins, and field workers.

marcin-mucha commented 1 year ago

Following Apple's linkAccount(using:) API and exposing such method by SDK would be a really convenient for us. We're planning the new flow where we want to discover/connect to the local reader at the begining of the payment flow, before the user sees the "Tap to Pay on iPhone" button (to speed up the TTP experience). Having such method would allow us to skip unnecessary discovery/connection process by simply checking non async method result at the begining of the flow.

bric-stripe commented 1 year ago

Hi, re-opening and tagging as an active feature request. Thanks for the use cases.

AnshulMindbody commented 1 year ago

Thanks, @bric-stripe. Do you have a timeline for when this will be available? And Also is it possible for you to include this in release 2.23.+ ?

bric-stripe commented 1 year ago

Do you have a timeline for when this will be available

No timeline. Team still needs to discuss what the API should look like[^1] and then get it planned and prioritized. It will take some time.

[^1]: since the SDK internally will need to fetch the token for this to be used it likely won't be a simple synchronous method, but will be simpler then having to discover and then connect to try to get the results back.

is it possible for you to include this in release 2.23.+

No. We continue to support 2.23.x but only for critical fixes.

koenpunt commented 1 year ago

Another downside of trying to connect and checking the error for SCPErrorAppleBuiltInReaderTOSNotYetAccepted is that it will present the geolocation authorization dialog.

AnshulMindbody commented 1 year ago

Another downside of trying to connect and checking the error for SCPErrorAppleBuiltInReaderTOSNotYetAccepted is that it will present the geolocation authorization dialog.

Yes, Totally agree @koenpunt I also observe the similar behaviour @bric-stripe why the geolocation authorization dialog is needed?

koenpunt commented 1 year ago

why the geolocation authorization dialog is needed?

Because it's required to receive payments, but a method to check whether the link exist shouldn't require it. That said, in general it would be nice if the automatic location prompt could be disabled in the same way the TOS acceptance can be disabled, to have control over how this feature is introduced, instead of showing the location prompt and the Apple TOS UI on top of each other.

AnshulMindbody commented 1 year ago

why the geolocation authorization dialog is needed? Because it's required to receive payments, but a method to check whether the link exist shouldn't require it. That said, in general it would be nice if the automatic location prompt could be disabled in the same way the TOS acceptance can be disabled, to have control over how this feature is introduced, instead of showing the location prompt and the Apple TOS UI on top of each other.

My point is that it should not be displayed at the time of connection, but should instead be shown at the time of payment.

koenpunt commented 1 year ago

My point is that it should not be displayed at the time of connection, but should instead be shown at the time of payment.

AFAIK it's the Apple SDK that requires the location when connecting to the reader, so the only way you can achieve that is by postponing connecting to the reader until payment, but that would cause a noticeable delay.

MeteC commented 6 months ago

Adding to this - we're currently working on bringing a TTP feature to our users, and need to work on the UI flow that comes up specifically after T&Cs have been accepted and provisioning is occurring. I've asked Apple about the best way to "unprovision" and unaccept the T&Cs in order to facilitate work and testing on this flow - factory resetting devices every time is obviously out - and they said to directly use PaymentCardReader's relinkAccount() method.

Given this open thread, I'm guessing we don't have any direct access to the PaymentCardReader being used by Stripe.

I wonder does anyone have a good way to "reset" things and retrigger T&Cs + provisioning, when using Stripe TTP?

Or perhaps our perceived need to have direct access to the PaymentCardReader might be more fuel for this conversation in any case...

koenpunt commented 6 months ago

I wonder does anyone have a good way to "reset" things and retrigger T&Cs + provisioning, when using Stripe TTP?

You can unlink your merchants in the Apple Business Register.

It does take some time to propagate to devices, but at least it doesn't require a factory reset.

MeteC commented 6 months ago

Awesome that's really helpful. (I had to muck around a bit this morning to actually finish setting up on the business register, but then I could see my development Merchant ID in there.) Thanks!

inzqne commented 6 months ago

Hello @bric-stripe I was wondering if there are any updates on this feature. My app requires only admins of an account to accept the T&C and I don't see a clear way of doing so currently. Any guidance on how to do this today with the cleanest workaround?

nabilfreeman commented 2 months ago

I wonder does anyone have a good way to "reset" things and retrigger T&Cs + provisioning, when using Stripe TTP?

You can unlink your merchants in the Apple Business Register.

It does take some time to propagate to devices, but at least it doesn't require a factory reset.

How can we find our Merchant ID in the Stripe Dashboard?

We would really like the ability to unlink merchants as it would make QA much easier.

To be clear, we are the platform facilitating TTP for our merchants.

inzqne commented 2 months ago

I wonder does anyone have a good way to "reset" things and retrigger T&Cs + provisioning, when using Stripe TTP?

You can unlink your merchants in the Apple Business Register. It does take some time to propagate to devices, but at least it doesn't require a factory reset.

How can we find our Merchant ID in the Stripe Dashboard?

We would really like the ability to unlink merchants as it would make QA much easier.

To be clear, we are the platform facilitating TTP for our merchants.

@nabilfreeman So far for QA purposes, the easiest way I've found is to create a fresh connect account in test mode. Not the most elegant solution but in case you need an immediate solution.

vcapillaTW commented 3 days ago

I wonder does anyone have a good way to "reset" things and retrigger T&Cs + provisioning, when using Stripe TTP?

You can unlink your merchants in the Apple Business Register.

It does take some time to propagate to devices, but at least it doesn't require a factory reset.

Hi!!

How long I should wait? I do it on Friday but, I've restarted my iPhone today but, when I try Tap to Pay is not asking to me for re-link.

Thank you very much!

vcapillaTW commented 4 hours ago

I found a way to do the unlink:

If you try to go inside this https://support.apple.com/en-bw/guide/apple-business-connect/abcb71e19fc3/web

Under the How do I unlink a Tap to Pay on iPhone merchant ID from an Apple Account? you can see a LINK.

That link redirects to https://dev.businessconnect.apple.com/taptopay/removeall that of course is not accessible If you remove dev. you can access to all the Merchant IDs to remove the one that you want to remove