BTThreeDSecureV2Provider.m 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #import "BTThreeDSecureV2Provider.h"
  2. #import "BTConfiguration+ThreeDSecure.h"
  3. #import "BTPaymentFlowDriver+ThreeDSecure_Internal.h"
  4. #import "BTThreeDSecureAuthenticateJWT.h"
  5. #if __has_include("BTAPIClient_Internal.h")
  6. #import "BTAPIClient_Internal.h"
  7. #else
  8. #import <BraintreeCore/BTAPIClient_Internal.h>
  9. #endif
  10. #import <CardinalMobile/CardinalMobile.h>
  11. @interface BTThreeDSecureV2Provider() <CardinalValidationDelegate>
  12. @property (strong, nonatomic) CardinalSession *cardinalSession;
  13. @property (strong, nonatomic) BTThreeDSecureLookup *lookupResult;
  14. @property (strong, nonatomic) BTAPIClient *apiClient;
  15. @property (copy, nonatomic) BTThreeDSecureV2ProviderSuccessHandler successHandler;
  16. @property (copy, nonatomic) BTThreeDSecureV2ProviderFailureHandler failureHandler;
  17. @end
  18. @implementation BTThreeDSecureV2Provider
  19. + (instancetype)initializeProviderWithConfiguration:(BTConfiguration *)configuration
  20. apiClient:(BTAPIClient *)apiClient
  21. request:(BTThreeDSecureRequest *)request
  22. completion:(BTThreeDSecureV2ProviderInitializeCompletionHandler)completionHandler {
  23. BTThreeDSecureV2Provider *instance = [self new];
  24. instance.apiClient = apiClient;
  25. instance.cardinalSession = [CardinalSession new];
  26. CardinalSessionConfiguration *cardinalConfiguration = [CardinalSessionConfiguration new];
  27. if (request.uiCustomization) {
  28. cardinalConfiguration.uiCustomization = request.uiCustomization;
  29. }
  30. CardinalSessionEnvironment cardinalEnvironment = CardinalSessionEnvironmentStaging;
  31. if ([[configuration.json[@"environment"] asString] isEqualToString:@"production"]) {
  32. cardinalEnvironment = CardinalSessionEnvironmentProduction;
  33. }
  34. cardinalConfiguration.deploymentEnvironment = cardinalEnvironment;
  35. [instance.cardinalSession configure:cardinalConfiguration];
  36. [instance.cardinalSession setupWithJWT:configuration.cardinalAuthenticationJWT
  37. didComplete:^(__unused NSString * _Nonnull consumerSessionId) {
  38. [instance.apiClient sendAnalyticsEvent:@"ios.three-d-secure.cardinal-sdk.init.setup-completed"];
  39. completionHandler(@{@"dfReferenceId": consumerSessionId});
  40. } didValidate:^(__unused CardinalResponse * _Nonnull validateResponse) {
  41. [instance.apiClient sendAnalyticsEvent:@"ios.three-d-secure.cardinal-sdk.init.setup-failed"];
  42. completionHandler(@{});
  43. }];
  44. return instance;
  45. }
  46. - (void)processLookupResult:(BTThreeDSecureLookup *)lookupResult
  47. success:(BTThreeDSecureV2ProviderSuccessHandler)successHandler
  48. failure:(BTThreeDSecureV2ProviderFailureHandler)failureHandler {
  49. self.lookupResult = lookupResult;
  50. self.successHandler = successHandler;
  51. self.failureHandler = failureHandler;
  52. [self.cardinalSession continueWithTransactionId:lookupResult.transactionId
  53. payload:lookupResult.PAReq
  54. didValidateDelegate:self];
  55. }
  56. - (void)callFailureHandlerWithErrorDomain:(NSErrorDomain)errorDomain
  57. errorCode:(NSInteger)errorCode
  58. errorUserInfo:(NSDictionary *)errorUserInfo
  59. failureHandler:(BTThreeDSecureV2ProviderFailureHandler)failureHandler {
  60. NSError *error = [NSError errorWithDomain:errorDomain
  61. code:errorCode
  62. userInfo:errorUserInfo];
  63. failureHandler(error);
  64. }
  65. #pragma mark - Cardinal Delegate
  66. - (void)cardinalSession:(__unused CardinalSession *)session stepUpDidValidateWithResponse:(CardinalResponse *)validateResponse serverJWT:(__unused NSString *)serverJWT {
  67. [self.apiClient sendAnalyticsEvent:[NSString stringWithFormat:@"ios.three-d-secure.verification-flow.cardinal-sdk.action-code.%@", [self analyticsStringForActionCode:validateResponse.actionCode]]];
  68. switch (validateResponse.actionCode) {
  69. case CardinalResponseActionCodeSuccess:
  70. case CardinalResponseActionCodeNoAction:
  71. case CardinalResponseActionCodeFailure: {
  72. [BTThreeDSecureAuthenticateJWT authenticateJWT:serverJWT
  73. withAPIClient:self.apiClient
  74. forLookupResult:self.lookupResult
  75. success:self.successHandler
  76. failure:self.failureHandler];
  77. break;
  78. }
  79. case CardinalResponseActionCodeError:
  80. case CardinalResponseActionCodeTimeout: {
  81. NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithCapacity:1];
  82. if (validateResponse.errorDescription) {
  83. userInfo[NSLocalizedDescriptionKey] = validateResponse.errorDescription;
  84. }
  85. BTThreeDSecureFlowErrorType errorCode = BTThreeDSecureFlowErrorTypeUnknown;
  86. if (validateResponse.errorNumber == 1050) {
  87. errorCode = BTThreeDSecureFlowErrorTypeFailedAuthentication;
  88. }
  89. [self callFailureHandlerWithErrorDomain:BTThreeDSecureFlowErrorDomain
  90. errorCode:errorCode
  91. errorUserInfo:userInfo
  92. failureHandler:self.failureHandler];
  93. break;
  94. }
  95. case CardinalResponseActionCodeCancel: {
  96. [self callFailureHandlerWithErrorDomain:BTPaymentFlowDriverErrorDomain
  97. errorCode:BTPaymentFlowDriverErrorTypeCanceled
  98. errorUserInfo:nil
  99. failureHandler:self.failureHandler];
  100. break;
  101. }
  102. }
  103. self.lookupResult = nil;
  104. self.successHandler = nil;
  105. self.failureHandler = nil;
  106. }
  107. - (NSString *)analyticsStringForActionCode:(CardinalResponseActionCode)actionCode {
  108. switch (actionCode) {
  109. case CardinalResponseActionCodeSuccess:
  110. return @"completed";
  111. case CardinalResponseActionCodeNoAction:
  112. return @"noaction";
  113. case CardinalResponseActionCodeFailure:
  114. return @"failure";
  115. case CardinalResponseActionCodeError:
  116. return @"failed";
  117. case CardinalResponseActionCodeCancel:
  118. return @"canceled";
  119. case CardinalResponseActionCodeTimeout:
  120. return @"timeout";
  121. }
  122. }
  123. @end