@@ -37,49 +37,63 @@ + (void)startBuyerVerificationFlow:(nonnull NSString *)paymentSourceId
3737 [SQIPBuyerAction fromStringDictionary: buyerActionString money: moneyMap];
3838 SQIPContact *contact = [SQIPContact fromDictionary: contactMap];
3939
40- UIViewController *rootViewController =
41- [UiUtilities activeRootViewController ];
42-
4340 SQIPVerificationParameters *params = [[SQIPVerificationParameters alloc ]
4441 initWithPaymentSourceID: paymentSourceId
4542 buyerAction: buyerAction
4643 locationID: locationId
4744 contact: contact];
4845
49- if ([rootViewController isKindOfClass: [UINavigationController class ]]) {
50- [rootViewController.navigationController popViewControllerAnimated: YES ];
51- } else {
52- [rootViewController dismissViewControllerAnimated: YES completion: nil ];
53- }
54-
55- [SQIPBuyerVerificationSDK.shared verifyWithParameters: params
56- theme: [SQIPCardEntryInternal theme ]
57- viewController: rootViewController
58- success: ^(SQIPBuyerVerifiedDetails *_Nonnull verifiedDetails) {
59- NSDictionary *verificationResult = @{
60- @" nonce" : paymentSourceId,
61- @" token" : verifiedDetails.verificationToken
62- };
63- onBuyerVerificationSuccess (@[ verificationResult ]);
64- [SQIPBuyerInternal shouldContinue ];
65- }
66- failure: ^(NSError *_Nonnull error) {
67- NSString *debugCode = error.userInfo [SQIPErrorDebugCodeKey];
68- NSString *debugMessage = error.userInfo [SQIPErrorDebugMessageKey];
69- if (_mockBuyerVerification) {
70- NSDictionary *verificationResult =
71- @{@" nonce" : paymentSourceId, @" token" : @" mock-token" };
46+ // Capture the success/failure blocks so we can present from the dismissal
47+ // completion handler. We need to wait for any in-progress dismissal to
48+ // finish before handing 3DS_SDK a presenter — otherwise it tries to
49+ // present on a VC whose view is mid-removal from the window hierarchy,
50+ // which surfaces as "view is not in the window hierarchy" under the new
51+ // React Native architecture (RCTFabricModalHostViewController).
52+ void (^presentVerification)(void ) = ^{
53+ UIViewController *presenter = [UiUtilities activeRootViewController ];
54+ [SQIPBuyerVerificationSDK.shared verifyWithParameters: params
55+ theme: [SQIPCardEntryInternal theme ]
56+ viewController: presenter
57+ success: ^(SQIPBuyerVerifiedDetails *_Nonnull verifiedDetails) {
58+ NSDictionary *verificationResult = @{
59+ @" nonce" : paymentSourceId,
60+ @" token" : verifiedDetails.verificationToken
61+ };
7262 onBuyerVerificationSuccess (@[ verificationResult ]);
7363 [SQIPBuyerInternal shouldContinue ];
74- } else {
75- [SQIPBuyerInternal invalidateShouldContinue ];
76- onBuyerVerificationFailure (@[ [ErrorUtilities
77- callbackErrorObject: RNSQIPUsageError
78- message: error.localizedDescription
79- debugCode: debugCode
80- debugMessage: debugMessage] ]);
8164 }
82- }];
65+ failure: ^(NSError *_Nonnull error) {
66+ NSString *debugCode = error.userInfo [SQIPErrorDebugCodeKey];
67+ NSString *debugMessage = error.userInfo [SQIPErrorDebugMessageKey];
68+ if (_mockBuyerVerification) {
69+ NSDictionary *verificationResult =
70+ @{@" nonce" : paymentSourceId, @" token" : @" mock-token" };
71+ onBuyerVerificationSuccess (@[ verificationResult ]);
72+ [SQIPBuyerInternal shouldContinue ];
73+ } else {
74+ [SQIPBuyerInternal invalidateShouldContinue ];
75+ onBuyerVerificationFailure (@[ [ErrorUtilities
76+ callbackErrorObject: RNSQIPUsageError
77+ message: error.localizedDescription
78+ debugCode: debugCode
79+ debugMessage: debugMessage] ]);
80+ }
81+ }];
82+ };
83+
84+ UIViewController *activeViewController =
85+ [UiUtilities activeRootViewController ];
86+
87+ // If a modal (e.g. card entry) is on top, dismiss it first and only
88+ // present verification once dismissal completes — `presentingViewController`
89+ // is the VC the active modal will hand control back to.
90+ if (activeViewController.presentingViewController != nil ) {
91+ [activeViewController.presentingViewController
92+ dismissViewControllerAnimated: YES
93+ completion: presentVerification];
94+ } else {
95+ presentVerification ();
96+ }
8397 });
8498}
8599
0 commit comments