@primer-io/react-native 2.26.3 → 2.28.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/.project +6 -0
- package/android/.settings/org.eclipse.buildship.core.prefs +5 -5
- package/android/build.gradle +1 -3
- package/android/src/main/AndroidManifest.xml +1 -4
- package/android/src/main/java/com/primerioreactnative/PrimerRN.kt +3 -3
- package/android/src/main/java/com/primerioreactnative/PrimerRNEventListener.kt +4 -3
- package/android/src/main/java/com/primerioreactnative/PrimerRNHeadlessUniversalCheckout.kt +2 -2
- package/android/src/main/java/com/primerioreactnative/PrimerRNHeadlessUniversalCheckoutListener.kt +46 -9
- package/android/src/main/java/com/primerioreactnative/ReactNativePackage.kt +4 -0
- package/android/src/main/java/com/primerioreactnative/components/manager/ach/AchMandateManager.kt +70 -0
- package/android/src/main/java/com/primerioreactnative/components/manager/ach/PrimerRNHeadlessUniversalCheckoutStripeAchUserDetailsComponent.kt +283 -0
- package/android/src/main/java/com/primerioreactnative/components/manager/banks/PrimerRNHeadlessUniversalCheckoutBanksComponent.kt +7 -37
- package/android/src/main/java/com/primerioreactnative/components/manager/klarna/PrimerRNHeadlessUniversalCheckoutKlarnaComponent.kt +5 -31
- package/android/src/main/java/com/primerioreactnative/datamodels/PrimerCheckoutAdditionalInfoRN.kt +17 -4
- package/android/src/main/java/com/primerioreactnative/datamodels/PrimerClientSessionRN.kt +9 -0
- package/android/src/main/java/com/primerioreactnative/datamodels/PrimerSettingsRN.kt +53 -36
- package/android/src/main/java/com/primerioreactnative/datamodels/ach/AchUserDetailsCollectableDataRN.kt +22 -0
- package/android/src/main/java/com/primerioreactnative/datamodels/ach/AchUserDetailsStepRN.kt +22 -0
- package/android/src/main/java/com/primerioreactnative/datamodels/extensions/ach/AchUserDetailsCollectableData.kt +11 -0
- package/android/src/main/java/com/primerioreactnative/datamodels/extensions/ach/AchUserDetailsStep.kt +14 -0
- package/android/src/main/java/com/primerioreactnative/extensions/JSONExtensions.kt +41 -0
- package/android/src/main/java/com/primerioreactnative/extensions/PrimerCheckoutAdditionalInfo.kt +4 -0
- package/android/src/main/java/com/primerioreactnative/extensions/PrimerOrder.kt +5 -1
- package/android/src/main/java/com/primerioreactnative/extensions/PrimerPaymentMethodOptionsRN.kt +48 -15
- package/ios/Sources/DataModels/Ach Component/RNTAchUserDetailsCollectableData.swift +54 -0
- package/ios/Sources/DataModels/Ach Component/RNTAchUserDetailsStep.swift +40 -0
- package/ios/Sources/DataModels/PrimerCheckoutAdditionalInfoRN.swift +61 -0
- package/ios/Sources/DataModels/PrimerSettings+Extensions.swift +58 -4
- package/ios/Sources/Headless Universal Checkout/Managers/Ach/PrimerRNHeadlessUniversalCheckoutStripeAchUserDetailsComponent.m +28 -0
- package/ios/Sources/Headless Universal Checkout/Managers/Ach/PrimerRNHeadlessUniversalCheckoutStripeAchUserDetailsComponent.swift +233 -0
- package/ios/Sources/Headless Universal Checkout/Managers/Ach/RNTAchMandateManager.m +16 -0
- package/ios/Sources/Headless Universal Checkout/Managers/Ach/RNTAchMandateManager.swift +53 -0
- package/ios/Sources/Headless Universal Checkout/Managers/Klarna/PrimerRNHeadlessUniversalCheckoutKlarnaComponent.swift +2 -2
- package/ios/Sources/Headless Universal Checkout/RNTPrimerHeadlessUniversalCheckout.swift +55 -7
- package/ios/Sources/version.swift +1 -1
- package/lib/commonjs/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.js +106 -0
- package/lib/commonjs/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.js.map +1 -0
- package/lib/commonjs/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.js +38 -0
- package/lib/commonjs/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.js.map +1 -0
- package/lib/commonjs/index.js +70 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/models/ach/AchCollectableData.js +6 -0
- package/lib/commonjs/models/ach/AchCollectableData.js.map +1 -0
- package/lib/commonjs/models/ach/AchSteps.js +6 -0
- package/lib/commonjs/models/ach/AchSteps.js.map +1 -0
- package/lib/module/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.js +99 -0
- package/lib/module/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.js.map +1 -0
- package/lib/module/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.js +31 -0
- package/lib/module/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.js.map +1 -0
- package/lib/module/index.js +8 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/models/ach/AchCollectableData.js +2 -0
- package/lib/module/models/ach/AchCollectableData.js.map +1 -0
- package/lib/module/models/ach/AchSteps.js +2 -0
- package/lib/module/models/ach/AchSteps.js.map +1 -0
- package/lib/typescript/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.d.ts +53 -0
- package/lib/typescript/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.d.ts.map +1 -0
- package/lib/typescript/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.d.ts +12 -0
- package/lib/typescript/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +8 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/models/PrimerCheckoutAdditionalInfo.d.ts +10 -0
- package/lib/typescript/models/PrimerCheckoutAdditionalInfo.d.ts.map +1 -1
- package/lib/typescript/models/PrimerClientSession.d.ts +7 -0
- package/lib/typescript/models/PrimerClientSession.d.ts.map +1 -1
- package/lib/typescript/models/PrimerSettings.d.ts +40 -1
- package/lib/typescript/models/PrimerSettings.d.ts.map +1 -1
- package/lib/typescript/models/ach/AchCollectableData.d.ts +25 -0
- package/lib/typescript/models/ach/AchCollectableData.d.ts.map +1 -0
- package/lib/typescript/models/ach/AchSteps.d.ts +28 -0
- package/lib/typescript/models/ach/AchSteps.d.ts.map +1 -0
- package/package.json +1 -1
- package/primer-io-react-native.podspec +1 -1
- package/src/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.ts +158 -0
- package/src/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.ts +32 -0
- package/src/index.tsx +8 -0
- package/src/models/PrimerCheckoutAdditionalInfo.ts +19 -5
- package/src/models/PrimerClientSession.ts +9 -1
- package/src/models/PrimerSettings.ts +46 -1
- package/src/models/ach/AchCollectableData.ts +29 -0
- package/src/models/ach/AchSteps.ts +29 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RNTAchUserDetailsStep.swift
|
|
3
|
+
// Pods
|
|
4
|
+
//
|
|
5
|
+
// Created by Flaviu Dunca on 12.06.2024.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import PrimerSDK
|
|
10
|
+
|
|
11
|
+
protocol AchUserDetailsStepRN {
|
|
12
|
+
var stepName: String { get }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
class UserDetailsCollectedRN: AchUserDetailsStepRN, Encodable {
|
|
16
|
+
let stepName: String = "userDetailsCollected"
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
class UserDetailsRetrievedRN: AchUserDetailsStepRN, Encodable {
|
|
20
|
+
let stepName: String = "userDetailsRetrieved"
|
|
21
|
+
let firstName: String
|
|
22
|
+
let lastName: String
|
|
23
|
+
let emailAddress: String
|
|
24
|
+
|
|
25
|
+
init(firstName: String, lastName: String, emailAddress: String) {
|
|
26
|
+
self.firstName = firstName
|
|
27
|
+
self.lastName = lastName
|
|
28
|
+
self.emailAddress = emailAddress
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
extension ACHUserDetailsStep {
|
|
33
|
+
func toUserDetailsCollectedRN() -> UserDetailsCollectedRN {
|
|
34
|
+
return UserDetailsCollectedRN()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
func toUserDetailsRetrievedRN(firstName: String, lastName: String, emailAddress: String) -> UserDetailsRetrievedRN {
|
|
38
|
+
return UserDetailsRetrievedRN(firstName: firstName, lastName: lastName, emailAddress: emailAddress)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
//
|
|
2
|
+
// PrimerCheckoutAdditionalInfoRN.swift
|
|
3
|
+
// primer-io-react-native
|
|
4
|
+
//
|
|
5
|
+
// Created by Flaviu Dunca on 17.06.2024.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import PrimerSDK
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
protocol PrimerCheckoutAdditionalInfoRN: Encodable {
|
|
13
|
+
var additionalInfoName: String { get }
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
class MultibancoCheckoutAdditionalInfoRN: PrimerCheckoutAdditionalInfoRN {
|
|
17
|
+
let expiresAt: String?
|
|
18
|
+
let reference: String?
|
|
19
|
+
let entity: String?
|
|
20
|
+
let additionalInfoName: String = "MultibancoCheckoutAdditionalInfo"
|
|
21
|
+
|
|
22
|
+
init(expiresAt: String?, reference: String?, entity: String?) {
|
|
23
|
+
self.expiresAt = expiresAt
|
|
24
|
+
self.reference = reference
|
|
25
|
+
self.entity = entity
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
protocol PrimerCheckoutQRCodeInfoRN: PrimerCheckoutAdditionalInfoRN {}
|
|
30
|
+
|
|
31
|
+
class PromptPayCheckoutAdditionalInfoRN: PrimerCheckoutQRCodeInfoRN {
|
|
32
|
+
let expiresAt: String
|
|
33
|
+
let qrCodeUrl: String?
|
|
34
|
+
let qrCodeBase64: String?
|
|
35
|
+
var additionalInfoName: String = "PromptPayCheckoutAdditionalInfo"
|
|
36
|
+
|
|
37
|
+
init(expiresAt: String, qrCodeUrl: String?, qrCodeBase64: String?) {
|
|
38
|
+
self.expiresAt = expiresAt
|
|
39
|
+
self.qrCodeUrl = qrCodeUrl
|
|
40
|
+
self.qrCodeBase64 = qrCodeBase64
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
protocol PrimerCheckoutVoucherInfoRN: PrimerCheckoutAdditionalInfoRN {}
|
|
45
|
+
|
|
46
|
+
class XenditCheckoutVoucherAdditionalInfoRN: PrimerCheckoutVoucherInfoRN {
|
|
47
|
+
let expiresAt: String
|
|
48
|
+
let couponCode: String
|
|
49
|
+
let retailerName: String?
|
|
50
|
+
var additionalInfoName: String = "XenditCheckoutVoucherAdditionalInfo"
|
|
51
|
+
|
|
52
|
+
init(expiresAt: String, couponCode: String, retailerName: String?) {
|
|
53
|
+
self.expiresAt = expiresAt
|
|
54
|
+
self.couponCode = couponCode
|
|
55
|
+
self.retailerName = retailerName
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
class AchAdditionalInfoDisplayMandateRN: PrimerCheckoutAdditionalInfoRN {
|
|
60
|
+
var additionalInfoName: String = "DisplayStripeAchMandateAdditionalInfo"
|
|
61
|
+
}
|
|
@@ -34,20 +34,51 @@ extension PrimerSettings {
|
|
|
34
34
|
|
|
35
35
|
var applePayOptions: PrimerApplePayOptions?
|
|
36
36
|
if let rnApplePayOptions = ((settingsJson["paymentMethodOptions"] as? [String: Any])?["applePayOptions"] as? [String: Any]),
|
|
37
|
-
|
|
38
|
-
let rnApplePayMerchantName = rnApplePayOptions["merchantName"] as? String
|
|
37
|
+
let rnApplePayMerchantIdentifier = rnApplePayOptions["merchantIdentifier"] as? String
|
|
39
38
|
{
|
|
39
|
+
let rnApplePayMerchantName = rnApplePayOptions["merchantName"] as? String
|
|
40
40
|
let rnApplePayIsCaptureBillingAddressEnabled = (rnApplePayOptions["isCaptureBillingAddressEnabled"] as? Bool) ?? false
|
|
41
41
|
let rnApplePayShowApplePayForUnsupportedDevice = (rnApplePayOptions["showApplePayForUnsupportedDevice"] as? Bool) ?? true
|
|
42
42
|
let rnApplePayCheckProvidedNetworks = (rnApplePayOptions["checkProvidedNetworks"] as? Bool) ?? true
|
|
43
43
|
|
|
44
|
+
var shippingOptions: PrimerApplePayOptions.ShippingOptions? = nil
|
|
45
|
+
if let rnShippingOptions = rnApplePayOptions["shippingOptions"] as? [String: Any] {
|
|
46
|
+
let isCaptureShippingAddressEnabled = rnShippingOptions["isCaptureShippingAddressEnabled"] as? Bool ?? false
|
|
47
|
+
let requireShippingMethod = rnShippingOptions["requireShippingMethod"] as? Bool ?? false
|
|
48
|
+
|
|
49
|
+
var additionalShippingContactFields: [PrimerApplePayOptions.ShippingOptions.AdditionalShippingContactField]? = nil
|
|
50
|
+
if let additionalFieldsStrings = rnShippingOptions["additionalShippingContactFields"] as? [String] {
|
|
51
|
+
additionalShippingContactFields = additionalFieldsStrings.compactMap { fieldStr in
|
|
52
|
+
switch fieldStr {
|
|
53
|
+
case "name":
|
|
54
|
+
return .name
|
|
55
|
+
case "emailAddress":
|
|
56
|
+
return .emailAddress
|
|
57
|
+
case "phoneNumber":
|
|
58
|
+
return .phoneNumber
|
|
59
|
+
default:
|
|
60
|
+
return nil // Ignore unknown values or handle accordingly
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
shippingOptions = PrimerApplePayOptions.ShippingOptions(
|
|
66
|
+
isCaptureShippingAddressEnabled: isCaptureShippingAddressEnabled,
|
|
67
|
+
additionalShippingContactFields: additionalShippingContactFields,
|
|
68
|
+
requireShippingMethod: requireShippingMethod
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
44
72
|
applePayOptions = PrimerApplePayOptions(
|
|
45
73
|
merchantIdentifier: rnApplePayMerchantIdentifier,
|
|
46
74
|
merchantName: rnApplePayMerchantName,
|
|
47
75
|
isCaptureBillingAddressEnabled: rnApplePayIsCaptureBillingAddressEnabled,
|
|
48
76
|
showApplePayForUnsupportedDevice: rnApplePayShowApplePayForUnsupportedDevice,
|
|
49
|
-
checkProvidedNetworks: rnApplePayCheckProvidedNetworks
|
|
77
|
+
checkProvidedNetworks: rnApplePayCheckProvidedNetworks,
|
|
78
|
+
shippingOptions: shippingOptions
|
|
79
|
+
)
|
|
50
80
|
}
|
|
81
|
+
|
|
51
82
|
|
|
52
83
|
var klarnaOptions: PrimerKlarnaOptions?
|
|
53
84
|
if let rnKlarnaRecurringPaymentDescription = ((settingsJson["paymentMethodOptions"] as? [String: Any])?["klarnaOptions"] as? [String: Any])?["recurringPaymentDescription"] as? String {
|
|
@@ -85,12 +116,35 @@ extension PrimerSettings {
|
|
|
85
116
|
if let rnThreeDsAppRequestorUrlStr = (((settingsJson["paymentMethodOptions"] as? [String: Any])?["threeDsOptions"] as? [String: Any])?["iOS"] as? [String: Any])?["threeDsAppRequestorUrl"] as? String {
|
|
86
117
|
threeDsOptions = PrimerThreeDsOptions(threeDsAppRequestorUrl: rnThreeDsAppRequestorUrlStr)
|
|
87
118
|
}
|
|
119
|
+
|
|
120
|
+
var stripeOptions: PrimerStripeOptions?
|
|
121
|
+
if let stripeOptionsMap = ((settingsJson["paymentMethodOptions"] as? [String: Any])?["stripeOptions"] as? [String: Any]) {
|
|
122
|
+
if let publishableKey = stripeOptionsMap["publishableKey"] as? String {
|
|
123
|
+
var mandateData: PrimerStripeOptions.MandateData?
|
|
124
|
+
if let mandateDataMap = stripeOptionsMap["mandateData"] as? [String: String] {
|
|
125
|
+
if let fullMandateText = mandateDataMap["fullMandateText"] {
|
|
126
|
+
mandateData = .fullMandate(text: fullMandateText)
|
|
127
|
+
} else if let merchantName = mandateDataMap["merchantName"] {
|
|
128
|
+
mandateData = .templateMandate(merchantName: merchantName)
|
|
129
|
+
} else {
|
|
130
|
+
PrimerLogging.shared.logger.warn(message: "Found mandate data but no resource key or merchant name - check your stripe config")
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
PrimerLogging.shared.logger.warn(message: "Found stripe options but no mandate data - check your stripe config")
|
|
134
|
+
}
|
|
135
|
+
stripeOptions = .init(
|
|
136
|
+
publishableKey: publishableKey,
|
|
137
|
+
mandateData: mandateData
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
88
141
|
|
|
89
142
|
let paymentMethodOptions = PrimerPaymentMethodOptions(
|
|
90
143
|
urlScheme: rnUrlScheme,
|
|
91
144
|
applePayOptions: applePayOptions,
|
|
92
145
|
klarnaOptions: klarnaOptions,
|
|
93
|
-
threeDsOptions: threeDsOptions
|
|
146
|
+
threeDsOptions: threeDsOptions,
|
|
147
|
+
stripeOptions: stripeOptions)
|
|
94
148
|
|
|
95
149
|
self.init(
|
|
96
150
|
paymentHandling: paymentHandling,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//
|
|
2
|
+
// PrimerRNHeadlessUniversalCheckoutStripeAchUserDetailsComponent.m
|
|
3
|
+
// primer-io-react-native
|
|
4
|
+
//
|
|
5
|
+
// Created by Flaviu Dunca on 14.06.2024.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#import <Foundation/Foundation.h>
|
|
9
|
+
#import <React/RCTBridgeModule.h>
|
|
10
|
+
#import <React/RCTEventEmitter.h>
|
|
11
|
+
|
|
12
|
+
@interface RCT_EXTERN_MODULE(RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent, RCTEventEmitter)
|
|
13
|
+
|
|
14
|
+
RCT_EXTERN_METHOD(configure:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
15
|
+
|
|
16
|
+
RCT_EXTERN_METHOD(onSetFirstName:(NSString *)firstName resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
17
|
+
|
|
18
|
+
RCT_EXTERN_METHOD(onSetLastName:(NSString *)lastName resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
19
|
+
|
|
20
|
+
RCT_EXTERN_METHOD(onSetEmailAddress:(NSString *)emailAddress resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
21
|
+
|
|
22
|
+
RCT_EXTERN_METHOD(start:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
23
|
+
|
|
24
|
+
RCT_EXTERN_METHOD(submit:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
25
|
+
|
|
26
|
+
RCT_EXTERN_METHOD(cleanUp:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
27
|
+
|
|
28
|
+
@end
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
//
|
|
2
|
+
// PrimerRNHeadlessUniversalCheckoutStripeAchUserDetailsComponent.swift
|
|
3
|
+
// Pods
|
|
4
|
+
//
|
|
5
|
+
// Created by Flaviu Dunca on 12.06.2024.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import UIKit
|
|
10
|
+
import PrimerSDK
|
|
11
|
+
|
|
12
|
+
@objc(RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent)
|
|
13
|
+
class RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent: RCTEventEmitter {
|
|
14
|
+
|
|
15
|
+
#if canImport(PrimerStripeSDK)
|
|
16
|
+
private var achManager: PrimerHeadlessUniversalCheckout.AchManager = PrimerHeadlessUniversalCheckout.AchManager()
|
|
17
|
+
#endif
|
|
18
|
+
var stripeAchUserDetailsComponent: (any StripeAchUserDetailsComponent)?
|
|
19
|
+
var clientToken: String?
|
|
20
|
+
|
|
21
|
+
override class func requiresMainQueueSetup() -> Bool {
|
|
22
|
+
return true
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
override init() {
|
|
26
|
+
super.init()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
override func supportedEvents() -> [String] {
|
|
30
|
+
return PrimerHeadlessUniversalCheckoutComponentEvent.allCases.compactMap({ $0.stringValue })
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// MARK: - API
|
|
34
|
+
|
|
35
|
+
@objc
|
|
36
|
+
public func configure(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
37
|
+
print("configure")
|
|
38
|
+
|
|
39
|
+
do {
|
|
40
|
+
#if canImport(PrimerStripeSDK)
|
|
41
|
+
guard let stripeAchUserDetailsComponent: any StripeAchUserDetailsComponent = try? achManager.provide(paymentMethodType: "STRIPE_ACH") else {
|
|
42
|
+
let err = RNTNativeError(
|
|
43
|
+
errorId: "native-ios",
|
|
44
|
+
errorDescription: "Failed to find asset of STRIPE_ACH for this session",
|
|
45
|
+
recoverySuggestion: nil)
|
|
46
|
+
throw err
|
|
47
|
+
}
|
|
48
|
+
self.stripeAchUserDetailsComponent = stripeAchUserDetailsComponent
|
|
49
|
+
RNTAchMandateManager.mandateDelegate = achManager.mandateDelegate
|
|
50
|
+
stripeAchUserDetailsComponent.stepDelegate = self
|
|
51
|
+
stripeAchUserDetailsComponent.errorDelegate = self
|
|
52
|
+
stripeAchUserDetailsComponent.validationDelegate = self
|
|
53
|
+
#else
|
|
54
|
+
let err = RNTNativeError(
|
|
55
|
+
errorId: "native-ios",
|
|
56
|
+
errorDescription: "PrimerStripeSDK missing",
|
|
57
|
+
recoverySuggestion: "Check if PrimerStripeSDK is included in your Podfile")
|
|
58
|
+
|
|
59
|
+
throw err
|
|
60
|
+
#endif
|
|
61
|
+
|
|
62
|
+
resolver(nil)
|
|
63
|
+
} catch {
|
|
64
|
+
rejecter(error.rnError["errorId"]!, error.rnError["description"], error)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@objc
|
|
69
|
+
public func cleanUp(
|
|
70
|
+
_ resolver: RCTPromiseResolveBlock,
|
|
71
|
+
rejecter: RCTPromiseRejectBlock
|
|
72
|
+
) {
|
|
73
|
+
RNTAchMandateManager.mandateDelegate = nil
|
|
74
|
+
stripeAchUserDetailsComponent = nil
|
|
75
|
+
resolver(nil)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@objc
|
|
79
|
+
public func start(
|
|
80
|
+
_ resolver: RCTPromiseResolveBlock,
|
|
81
|
+
rejecter: RCTPromiseRejectBlock
|
|
82
|
+
) {
|
|
83
|
+
print("Start Stripe ACH process")
|
|
84
|
+
|
|
85
|
+
guard let stripeAchUserDetailsComponent = self.stripeAchUserDetailsComponent else {
|
|
86
|
+
rejecter("UNINITIALIZED_ERROR", "Stripe ACH user details component is uninitialized", nil)
|
|
87
|
+
return
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
stripeAchUserDetailsComponent.start()
|
|
91
|
+
resolver(nil)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@objc
|
|
95
|
+
public func submit(
|
|
96
|
+
_ resolver: RCTPromiseResolveBlock,
|
|
97
|
+
rejecter: RCTPromiseRejectBlock
|
|
98
|
+
) {
|
|
99
|
+
guard let stripeAchUserDetailsComponent = self.stripeAchUserDetailsComponent else {
|
|
100
|
+
rejecter("UNINITIALIZED_ERROR", "Stripe ACH user details component is uninitialized", nil)
|
|
101
|
+
return
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
stripeAchUserDetailsComponent.submit()
|
|
105
|
+
resolver(nil)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@objc
|
|
109
|
+
public func onSetFirstName(
|
|
110
|
+
_ firstName: String,
|
|
111
|
+
resolver: RCTPromiseResolveBlock,
|
|
112
|
+
rejecter: RCTPromiseRejectBlock
|
|
113
|
+
) {
|
|
114
|
+
guard let stripeAchUserDetailsComponent = self.stripeAchUserDetailsComponent else {
|
|
115
|
+
rejecter("UNINITIALIZED_ERROR", "Stripe ACH user details component is uninitialized", nil)
|
|
116
|
+
return
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
DispatchQueue.main.async {
|
|
120
|
+
stripeAchUserDetailsComponent.updateCollectedData(collectableData: ACHUserDetailsCollectableData.firstName(firstName))
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
resolver(nil)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@objc
|
|
127
|
+
public func onSetLastName(
|
|
128
|
+
_ lastName: String,
|
|
129
|
+
resolver: RCTPromiseResolveBlock,
|
|
130
|
+
rejecter: RCTPromiseRejectBlock
|
|
131
|
+
) {
|
|
132
|
+
guard let stripeAchUserDetailsComponent = self.stripeAchUserDetailsComponent else {
|
|
133
|
+
rejecter("UNINITIALIZED_ERROR", "Stripe ACH user details component is uninitialized", nil)
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
DispatchQueue.main.async {
|
|
138
|
+
stripeAchUserDetailsComponent.updateCollectedData(collectableData: ACHUserDetailsCollectableData.lastName(lastName))
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
resolver(nil)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@objc
|
|
145
|
+
public func onSetEmailAddress(
|
|
146
|
+
_ emailAddress: String,
|
|
147
|
+
resolver: RCTPromiseResolveBlock,
|
|
148
|
+
rejecter: RCTPromiseRejectBlock
|
|
149
|
+
) {
|
|
150
|
+
guard let stripeAchUserDetailsComponent = self.stripeAchUserDetailsComponent else {
|
|
151
|
+
rejecter("UNINITIALIZED_ERROR", "Stripe ACH user details component is uninitialized", nil)
|
|
152
|
+
return
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
DispatchQueue.main.async {
|
|
156
|
+
stripeAchUserDetailsComponent.updateCollectedData(collectableData: ACHUserDetailsCollectableData.emailAddress(emailAddress))
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
resolver(nil)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
extension RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent: PrimerHeadlessSteppableDelegate {
|
|
164
|
+
func didReceiveStep(step: PrimerSDK.PrimerHeadlessStep) {
|
|
165
|
+
guard let step = step as? ACHUserDetailsStep else { return }
|
|
166
|
+
|
|
167
|
+
switch step {
|
|
168
|
+
case .retrievedUserDetails(let details):
|
|
169
|
+
let json = try? step.toUserDetailsRetrievedRN(firstName: details.firstName, lastName: details.lastName, emailAddress: details.emailAddress).toJsonObject()
|
|
170
|
+
|
|
171
|
+
sendEvent(
|
|
172
|
+
withName: PrimerHeadlessUniversalCheckoutComponentEvent.onStep.stringValue,
|
|
173
|
+
body: json
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
case .didCollectUserDetails:
|
|
177
|
+
let json = try? step.toUserDetailsCollectedRN().toJsonObject()
|
|
178
|
+
|
|
179
|
+
sendEvent(
|
|
180
|
+
withName: PrimerHeadlessUniversalCheckoutComponentEvent.onStep.stringValue,
|
|
181
|
+
body: json
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
default:
|
|
185
|
+
break
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
extension RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent: PrimerHeadlessValidatableDelegate {
|
|
191
|
+
func didUpdate(validationStatus: PrimerSDK.PrimerValidationStatus, for data: PrimerSDK.PrimerCollectableData?) {
|
|
192
|
+
guard let data = data as? ACHUserDetailsCollectableData else { return }
|
|
193
|
+
|
|
194
|
+
var errorJsonObject: Any?
|
|
195
|
+
let eventName: String
|
|
196
|
+
|
|
197
|
+
switch validationStatus {
|
|
198
|
+
case .valid:
|
|
199
|
+
eventName = PrimerHeadlessUniversalCheckoutComponentEvent.onValid.stringValue
|
|
200
|
+
case .validating:
|
|
201
|
+
eventName = PrimerHeadlessUniversalCheckoutComponentEvent.onValidating.stringValue
|
|
202
|
+
case .invalid(let errors):
|
|
203
|
+
errorJsonObject = try? ["errors": errors.map { $0.toPrimerValidationErrorRN() }].toJsonObject()
|
|
204
|
+
eventName = PrimerHeadlessUniversalCheckoutComponentEvent.onInvalid.stringValue
|
|
205
|
+
case .error(let error):
|
|
206
|
+
errorJsonObject = try? ["errors": [error.toPrimerErrorRN()]].toJsonObject()
|
|
207
|
+
eventName = PrimerHeadlessUniversalCheckoutComponentEvent.onValidationError.stringValue
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
var dataJsonObject: Any?
|
|
211
|
+
switch data {
|
|
212
|
+
case .firstName(let value):
|
|
213
|
+
dataJsonObject = try? ["data": data.toFirstNameRN(value: value)].toJsonObject()
|
|
214
|
+
case .lastName(let value):
|
|
215
|
+
dataJsonObject = try? ["data": data.toLastNameRN(value: value)].toJsonObject()
|
|
216
|
+
case .emailAddress(let value):
|
|
217
|
+
dataJsonObject = try? ["data": data.toEmailAddressRN(value: value)].toJsonObject()
|
|
218
|
+
}
|
|
219
|
+
let allData = ((dataJsonObject as? [String: Any]) ?? [:]).merging((errorJsonObject as? [String: Any]) ?? [:]) { (_, new) in new }
|
|
220
|
+
sendEvent(withName: eventName, body: allData)
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
extension RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent: PrimerHeadlessErrorableDelegate {
|
|
225
|
+
func didReceiveError(error: PrimerSDK.PrimerError) {
|
|
226
|
+
let rnError = error.toPrimerErrorRN()
|
|
227
|
+
let serializedData = try? ["errors": [rnError]].toJsonObject()
|
|
228
|
+
|
|
229
|
+
self.sendEvent(
|
|
230
|
+
withName: PrimerHeadlessUniversalCheckoutComponentEvent.onError.stringValue,
|
|
231
|
+
body: serializedData)
|
|
232
|
+
}
|
|
233
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RNTAchMandateManager.m
|
|
3
|
+
// primer-io-react-native
|
|
4
|
+
//
|
|
5
|
+
// Created by Flaviu Dunca on 18.06.2024.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#import <React/RCTBridgeModule.h>
|
|
9
|
+
|
|
10
|
+
@interface RCT_EXTERN_MODULE(RNTAchMandateManager, NSObject)
|
|
11
|
+
|
|
12
|
+
RCT_EXTERN_METHOD(acceptMandate:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
13
|
+
|
|
14
|
+
RCT_EXTERN_METHOD(declineMandate:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
15
|
+
|
|
16
|
+
@end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RNTAchMandateManager.swift
|
|
3
|
+
// primer-io-react-native
|
|
4
|
+
//
|
|
5
|
+
// Created by Flaviu Dunca on 18.06.2024.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import React
|
|
10
|
+
import PrimerSDK
|
|
11
|
+
|
|
12
|
+
@objc(RNTAchMandateManager)
|
|
13
|
+
class RNTAchMandateManager: NSObject, RCTBridgeModule {
|
|
14
|
+
private let errorMessage = "Mandate delegate is not defined"
|
|
15
|
+
|
|
16
|
+
static func moduleName() -> String! {
|
|
17
|
+
return "RNTAchMandateManager"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
func methodQueue() -> DispatchQueue {
|
|
21
|
+
return DispatchQueue.main
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@objc static func requiresMainQueueSetup() -> Bool {
|
|
25
|
+
return true
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static var mandateDelegate: ACHMandateDelegate? = nil
|
|
29
|
+
|
|
30
|
+
@objc
|
|
31
|
+
func acceptMandate(
|
|
32
|
+
_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock
|
|
33
|
+
) {
|
|
34
|
+
if let delegate = RNTAchMandateManager.mandateDelegate {
|
|
35
|
+
delegate.acceptMandate()
|
|
36
|
+
resolver(nil)
|
|
37
|
+
} else {
|
|
38
|
+
rejecter("native-ios", errorMessage, nil)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@objc
|
|
43
|
+
func declineMandate(
|
|
44
|
+
_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock
|
|
45
|
+
) {
|
|
46
|
+
if let delegate = RNTAchMandateManager.mandateDelegate {
|
|
47
|
+
delegate.declineMandate()
|
|
48
|
+
resolver(nil)
|
|
49
|
+
} else {
|
|
50
|
+
rejecter("native-ios", errorMessage, nil)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -241,7 +241,7 @@ extension RNTPrimerHeadlessUniversalCheckoutKlarnaComponent: PrimerHeadlessValid
|
|
|
241
241
|
eventName = PrimerHeadlessUniversalCheckoutComponentEvent.onValidating.stringValue
|
|
242
242
|
case .invalid(let errors):
|
|
243
243
|
let rnErrors = errors.map { $0.toPrimerValidationErrorRN() }
|
|
244
|
-
let serializedData = try? ["errors": rnErrors].toJsonObject()
|
|
244
|
+
let serializedData = try? ["errors": rnErrors].toJsonObject() // TODO TWS iOS: include 'data'
|
|
245
245
|
|
|
246
246
|
self.sendEvent(
|
|
247
247
|
withName: PrimerHeadlessUniversalCheckoutComponentEvent.onInvalid.stringValue,
|
|
@@ -249,7 +249,7 @@ extension RNTPrimerHeadlessUniversalCheckoutKlarnaComponent: PrimerHeadlessValid
|
|
|
249
249
|
return
|
|
250
250
|
case .error(let error):
|
|
251
251
|
let rnError = error.toPrimerErrorRN()
|
|
252
|
-
let serializedData = try? ["errors": [rnError]].toJsonObject()
|
|
252
|
+
let serializedData = try? ["errors": [rnError]].toJsonObject() // TODO TWS iOS: include 'data'
|
|
253
253
|
|
|
254
254
|
self.sendEvent(
|
|
255
255
|
withName: PrimerHeadlessUniversalCheckoutComponentEvent.onValidationError.stringValue,
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import Foundation
|
|
9
9
|
import PrimerSDK
|
|
10
|
+
import React
|
|
10
11
|
|
|
11
12
|
@objc
|
|
12
13
|
enum PrimerHeadlessUniversalCheckoutEvents: Int, CaseIterable {
|
|
@@ -75,8 +76,6 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
|
|
|
75
76
|
|
|
76
77
|
override init() {
|
|
77
78
|
super.init()
|
|
78
|
-
PrimerHeadlessUniversalCheckout.current.delegate = self
|
|
79
|
-
PrimerHeadlessUniversalCheckout.current.uiDelegate = self
|
|
80
79
|
}
|
|
81
80
|
|
|
82
81
|
override func supportedEvents() -> [String]! {
|
|
@@ -91,6 +90,9 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
|
|
|
91
90
|
resolver: @escaping RCTPromiseResolveBlock,
|
|
92
91
|
rejecter: @escaping RCTPromiseRejectBlock)
|
|
93
92
|
{
|
|
93
|
+
PrimerHeadlessUniversalCheckout.current.delegate = self
|
|
94
|
+
PrimerHeadlessUniversalCheckout.current.uiDelegate = self
|
|
95
|
+
|
|
94
96
|
do {
|
|
95
97
|
var tmpSettings: PrimerSettings?
|
|
96
98
|
if let settingsStr = settingsStr {
|
|
@@ -346,11 +348,57 @@ extension RNTPrimerHeadlessUniversalCheckout: PrimerHeadlessUniversalCheckoutDel
|
|
|
346
348
|
DispatchQueue.main.async {
|
|
347
349
|
if self.implementedRNCallbacks?.isOnCheckoutAdditionalInfoImplemented == true {
|
|
348
350
|
do {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
351
|
+
switch additionalInfo {
|
|
352
|
+
case let info as ACHBankAccountCollectorAdditionalInfo:
|
|
353
|
+
// Handled internally, nothing for merchant to handle
|
|
354
|
+
let keyWindow = UIApplication
|
|
355
|
+
.shared
|
|
356
|
+
.connectedScenes
|
|
357
|
+
.flatMap { ($0 as? UIWindowScene)?.windows ?? [] }
|
|
358
|
+
.last { $0.isKeyWindow }
|
|
359
|
+
DispatchQueue.main.async {
|
|
360
|
+
if let rootViewController = keyWindow?.rootViewController {
|
|
361
|
+
rootViewController.present(info.collectorViewController, animated: true, completion: nil)
|
|
362
|
+
} else {
|
|
363
|
+
let checkoutData = PrimerCheckoutData(payment: nil, additionalInfo: additionalInfo)
|
|
364
|
+
self.handleRNBridgeError(
|
|
365
|
+
RNTNativeError(
|
|
366
|
+
errorId: "native-ios",
|
|
367
|
+
errorDescription: "Failed to retrieve root view controller, cannot present Stripe view controller",
|
|
368
|
+
recoverySuggestion: nil
|
|
369
|
+
),
|
|
370
|
+
checkoutData: checkoutData,
|
|
371
|
+
stopOnDebug: true
|
|
372
|
+
)
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return
|
|
376
|
+
case _ as ACHMandateAdditionalInfo:
|
|
377
|
+
self.sendEvent(
|
|
378
|
+
withName: rnCallbackName,
|
|
379
|
+
body: try AchAdditionalInfoDisplayMandateRN().toJsonObject()
|
|
380
|
+
)
|
|
381
|
+
case let info as MultibancoCheckoutAdditionalInfo:
|
|
382
|
+
self.sendEvent(
|
|
383
|
+
withName: rnCallbackName,
|
|
384
|
+
body: try MultibancoCheckoutAdditionalInfoRN(expiresAt: info.expiresAt, reference: info.reference, entity: info.entity).toJsonObject()
|
|
385
|
+
)
|
|
386
|
+
case let info as PromptPayCheckoutAdditionalInfo:
|
|
387
|
+
self.sendEvent(
|
|
388
|
+
withName: rnCallbackName,
|
|
389
|
+
body: try PromptPayCheckoutAdditionalInfoRN(expiresAt: info.expiresAt, qrCodeUrl: info.qrCodeUrl, qrCodeBase64: info.qrCodeBase64).toJsonObject()
|
|
390
|
+
)
|
|
391
|
+
case let info as XenditCheckoutVoucherAdditionalInfo:
|
|
392
|
+
self.sendEvent(
|
|
393
|
+
withName: rnCallbackName,
|
|
394
|
+
body: try XenditCheckoutVoucherAdditionalInfoRN(expiresAt: info.expiresAt, couponCode: info.couponCode, retailerName: info.retailerName).toJsonObject()
|
|
395
|
+
)
|
|
396
|
+
default:
|
|
397
|
+
self.sendEvent(
|
|
398
|
+
withName: rnCallbackName,
|
|
399
|
+
body: try additionalInfo?.toJsonObject()
|
|
400
|
+
)
|
|
401
|
+
}
|
|
354
402
|
} catch {
|
|
355
403
|
let checkoutData = PrimerCheckoutData(payment: nil, additionalInfo: additionalInfo)
|
|
356
404
|
self.handleRNBridgeError(error, checkoutData: checkoutData, stopOnDebug: true)
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// swiftlint:disable:next identifier_name
|
|
2
|
-
public let PrimerReactNativeSDKVersion = "2.
|
|
2
|
+
public let PrimerReactNativeSDKVersion = "2.27.0"
|