Closed jonhcbs closed 3 months ago
Hey John,
You're correct that what's happening is that the SDK is transitioning to offline operation between /create and /confirm. Like you mention, this can happen due to a flaky or intermittent network connection; in other cases, like for pi_3OsxcLAPQoqa93xj2JnQu8kA
, the SDK retried a payment offline because Stripe's backend returned a transient 500 error. When the SDK comes back online, some of these payments will decline due to insufficent funds, etc.
This auto-transition is intentional behavior and not a bug -- the SDK automatically retries failed confirmations offline even if the PI is created online, so you can complete the transaction even if you lost connectivity immediately after a /create call. If you don't want this to happen, one option is to use the per-transaction offlineBehavior
param on collectPaymentMethod
to force the SDK to operate fully online/offline. This will prevent transitions mid-transaction, but requires you to manage your own network transitions -- you'll have to write extra code to consume the networkStatus
from the SDK and set the param accordingly.
Can you say more about how you would expect network transitions to work? Are you looking for the SDK to retry more often before transitioning to offline mode/never to transition in the middle of a transaction/something else?
yes, we don't want the sdk transit to offline state in this case, because our app is still in online. we expected that if payment intent is created online, then should confirm payment intent online. since even the network is weak or intermittent, still have the possibility to confirm intent online.
In other words, we want the sdk's offline behavior to be in control. for example, we want this payment or payment intent to be created/confirm online, sdk should not transit to offline in the mid of the process automatically. Or even if network is totally down, but user do not want to use offline, sdk should also not go to offline automatically.
we didn't see offlineBehavior
param in collectPaymentMethod. can you confirm or share some sample code?
We did see createPaymentIntent have the param, but the problem is we create payment Intent in backend when online, but not via sdk. any way to set offlineBehavior
in our case?
- (nullable SCPCancelable *)collectPaymentMethod:(SCPPaymentIntent *)paymentIntent completion:(SCPPaymentIntentCompletionBlock)completion NS_SWIFT_NAME(collectPaymentMethod(_:completion:));
Got it, thanks. Re: offlineBehavior
, apologies, that was a typo -- you're correct that offlineBehavior
is on the SDK createPaymentIntent
method. There isn't an equivalent on collect
or confirm
.
Unfortunately, we currently don't have an easy workaround for this scenario; we recommend that offline mode users create their PaymentIntents client-side while online and offline. We'll take this as feedback.
Just so I can understand the use case better -- is there a particular reason you prefer to create PIs server-side while online? How does your integration determine whether to create the PaymentIntent through your backend vs the SDK -- do you use the SDK's networkStatus
?
that's a historical reason that we create paymentIntent in server-side while online, maybe there is other logic in server-side when create paymentIntent, for example save paymentIntent to server db or some statistics reason etc.
Because our app also have an offline state, if app is offline then create payment intent via sdk, otherwise create online in backend. Not the SDK's networkStatus.
using the SDK's networkStatus is not correct, since maybe it is online when create payment intent, but when confirm it is offline.
Thanks for the insight into your payment state machine and network tracking. We'll evaluate what it would take to add offlineBehavior
to collectPaymentMethod
or confirmPaymentIntent
, but we'll need to assess broader usage patterns to determine the optimal solution shape. Most offline users today create their PaymentIntents client-side, but it's possible we'll see additional signal as our beta progresses.
As a side note -- the possibility of switching to offline operation mid-transaction is true regardless of SDK 3.2.1 vs. 3.3 usage. We recommend you upgrade to prevent the bug we mentioned in our previous communication, where payment forwarding fails with error INTEGRATION_ERROR.SCPErrorForwardingTestModePaymentInLiveMode
.
Please let us know if you experience any other rough edges, and apologies we don't have a nearer-term solution for you.
There may be some risk for us to change create paymentIntent to client when online, since there is some logic in backend. Is it possible that when create PI online, we can pass a parameter to stripe such as "offline_behavior": "require_online"
, so that backend will create a require online PI, and sdk will not confirm this kind of PI offline?
Seems this is another workaround to fix this, but don't know if stripe api or sdk support this?
I didn't see this param in docs. https://docs.stripe.com/api/payment_intents/create, can you help a look? thanks.
Yeah, offlineBehavior
is an SDK-only configuration option, unfortunately. It doesn't currently exist on the backend PaymentIntent
object, and it can't be specified on the public /create
API.
ok, If there is any plan to support this kind of case please tell us. Thanks
Since our user is still complained about this. So just want to confirm what's the default OfflineBehavior for sdk? Maybe the default behavior is SCPOfflineBehaviorPreferOnline
from the source code? so the sdk will transit to offline by itself, but not in our control.
Could we set the default OfflineBehavior to SCPOfflineBehaviorRequireOnline? so that sdk will not transit to offline by itself in this case, even the payment intent is created in backend.
Could you help check if could add this config? I think it's not a big change if works.
typedef NS_ENUM(NSInteger, SCPOfflineBehavior) {
/**
When network connectivity is available, this PaymentIntent will be transacted online. When network connectivity is unavailable, the PaymentIntent will be transacted offline.
*/
SCPOfflineBehaviorPreferOnline,
/**
The PaymentIntent will only be transacted when network connectivity is available.
*/
SCPOfflineBehaviorRequireOnline,
/**
The PaymentIntent will only be transacted offline, regardless of network connectivity.
*/
SCPOfflineBehaviorForceOffline
} NS_SWIFT_NAME(OfflineBehavior);
@dver-stripe
Unfortunately, that change would be disruptive to other workflows. You're correct that the current default is PreferOnline
, which allows the SDK to automatically switch to offline operation. Changing it to RequireOnline
would mean that users who don't explicitly set offlineBehavior
(the majority of users) would suddenly have offline mode disabled by default.
Apologies that this continues to be a pain point for you. We'll keep looking into solutions on our side.
Summary
When using in online mode, we found there is an issue some times, not very often but happens several times this month.
Steps:
1 start a payment, create a payment intent when online.
2 collectPaymentMethod // success 3 confirmPaymentIntent
but at this point sdk will change to offline state for some reason network not stable issue etc.
we add the log and noticed that
offlineStatus.sdk.networkStatus
value is 1 , that is offline status.sdk Confirm Payment Intent returns success, but it is not correct state. it is an offline confirm. some times sdk will later return
Your card was declined.
orYour card has insufficient funds.
etc error.since sdk returns capture success, we think that this payment is success, and the order is finished and customer left. but actually payment Intent capture fail, this is bad.
The problem is we don't want to sdk change to offline by itself which is out of control, if confirmPaymentIntent when online but sdk changed to offline suddenly, just return error or retry ? Since the payment Intent is an online PI with
pi_
prefix, should not confirm success offline ? not sure it is a bug or not. We are mostly using sdk 3.2.1 version now.Below is some payment intent which have this issue.
Code to reproduce
Actually we can not reproduce this, we find this issue from the logs.
iOS version
16.x 17.x etc but not related to ios version
Installation method
cocoapods
SDK version
3.2.1
Other information
firmwareVersion: 2.01.00.20-SZZZ_Prod_US_v10-480001 readerSN: STRM26214141499