@primer-io/react-native 0.6.4 → 0.6.8

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.
Files changed (48) hide show
  1. package/README.md +4 -6
  2. package/android/.gradle/7.0.2/dependencies-accessors/dependencies-accessors.lock +0 -0
  3. package/android/.gradle/7.0.2/dependencies-accessors/gc.properties +0 -0
  4. package/android/.gradle/7.0.2/executionHistory/executionHistory.lock +0 -0
  5. package/android/.gradle/7.0.2/fileChanges/last-build.bin +0 -0
  6. package/android/.gradle/7.0.2/fileHashes/fileHashes.lock +0 -0
  7. package/android/.gradle/7.0.2/gc.properties +0 -0
  8. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  9. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  10. package/android/.gradle/checksums/checksums.lock +0 -0
  11. package/android/.gradle/checksums/md5-checksums.bin +0 -0
  12. package/android/.gradle/checksums/sha1-checksums.bin +0 -0
  13. package/android/.gradle/vcs-1/gc.properties +0 -0
  14. package/android/build.gradle +1 -1
  15. package/android/src/main/java/com/primerioreactnative/PrimerRN.kt +34 -61
  16. package/android/src/main/java/com/primerioreactnative/PrimerRNEventListener.kt +21 -3
  17. package/android/src/main/java/com/primerioreactnative/datamodels/PrimerRequestRN.kt +2 -1
  18. package/android/src/main/java/com/primerioreactnative/datamodels/PrimerSettingsRN.kt +85 -12
  19. package/android/src/main/java/com/primerioreactnative/datamodels/PrimerThemeRN.kt +6 -14
  20. package/ios/DataModels/PrimerErrorRN.swift +4 -0
  21. package/ios/DataModels/PrimerRequestRN.swift +2 -1
  22. package/ios/DataModels/PrimerSettingsRN.swift +33 -5
  23. package/ios/PrimerRN+PrimerDelegate.swift +27 -2
  24. package/ios/PrimerRN.swift +11 -5
  25. package/ios/ReactNative.m +2 -0
  26. package/ios/ReactNative.xcodeproj/project.pbxproj +0 -44
  27. package/lib/commonjs/Primer.js +52 -4
  28. package/lib/commonjs/Primer.js.map +1 -1
  29. package/lib/commonjs/models/action-request.js +2 -0
  30. package/lib/commonjs/models/action-request.js.map +1 -0
  31. package/lib/module/Primer.js +52 -4
  32. package/lib/module/Primer.js.map +1 -1
  33. package/lib/module/models/action-request.js +2 -0
  34. package/lib/module/models/action-request.js.map +1 -0
  35. package/lib/typescript/models/action-request.d.ts +10 -0
  36. package/lib/typescript/models/primer-callbacks.d.ts +2 -0
  37. package/lib/typescript/models/primer-config.d.ts +1 -0
  38. package/lib/typescript/models/primer-request.d.ts +13 -2
  39. package/lib/typescript/models/primer-settings.d.ts +8 -6
  40. package/package.json +1 -1
  41. package/primer-io-react-native.podspec +1 -1
  42. package/src/Primer.ts +32 -3
  43. package/src/models/action-request.ts +12 -0
  44. package/src/models/primer-callbacks.ts +6 -0
  45. package/src/models/primer-config.ts +3 -0
  46. package/src/models/primer-request.ts +18 -2
  47. package/src/models/primer-settings.ts +8 -6
  48. package/ios/Podfile.lock +0 -3
package/README.md CHANGED
@@ -43,15 +43,13 @@ import { Primer } from '@primer-io/react-native';
43
43
  const token: string = await fetchClientToken();
44
44
 
45
45
  // configure listeners and settings.
46
- const onTokenizeSuccess = (t, handler) => {
47
- setPaymentInstrument(t);
48
- handler.resumeWithSuccess(); // call this to resume the checkout flow.
46
+ const onTokenizeSuccess = async (t, handler) => {
47
+ const payment = await createPayment(t);
48
+ handler.handleSuccess(); // resume the checkout flow with success message.
49
49
  };
50
50
 
51
- const settings = { order: { amount: 50, currency: 'GBP' } };
52
-
53
51
  // show Universal Checkout with client token and config.
54
- Primer.showUniversalCheckout(token, { onTokenizeSuccess, settings });
52
+ Primer.showUniversalCheckout(token, { onTokenizeSuccess });
55
53
  ```
56
54
 
57
55
  For more info & help troubleshooting, check out our 🔥 [docs](https://www.notion.so/primerio/Quick-Start-6c5eb61e5bbe426ca66244259e06048e)
File without changes
@@ -0,0 +1,2 @@
1
+ #Thu Dec 02 15:56:45 GMT 2021
2
+ gradle.version=7.0.2
File without changes
@@ -128,5 +128,5 @@ dependencies {
128
128
  api 'com.facebook.react:react-native:+'
129
129
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
130
130
  implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.2"
131
- implementation 'io.primer:android:1.0.0-beta.30'
131
+ implementation 'io.primer:android:1.4.0'
132
132
  }
@@ -8,6 +8,7 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule
8
8
  import com.facebook.react.bridge.ReactMethod
9
9
  import com.primerioreactnative.datamodels.*
10
10
  import io.primer.android.Primer
11
+ import io.primer.android.model.dto.*
11
12
  import kotlinx.serialization.decodeFromString
12
13
  import kotlinx.serialization.encodeToString
13
14
  import kotlinx.serialization.json.Json
@@ -87,6 +88,11 @@ class PrimerRN(reactContext: ReactApplicationContext) : ReactContextBaseJavaModu
87
88
  mListener.configureOnTokenizeSuccess(callback)
88
89
  }
89
90
 
91
+ @ReactMethod
92
+ fun configureOnResumeSuccess(callback: Callback) {
93
+ mListener.configureOnResumeSuccess(callback)
94
+ }
95
+
90
96
  @ReactMethod
91
97
  fun configureOnVaultSuccess(callback: Callback) {
92
98
  mListener.configureOnVaultSuccess(callback)
@@ -113,9 +119,28 @@ class PrimerRN(reactContext: ReactApplicationContext) : ReactContextBaseJavaModu
113
119
  }
114
120
 
115
121
  private fun startSdk(token: String) {
116
- val context = currentActivity as Context
117
- val theme = this.theme.primerTheme
118
- Primer.initialize(context, token, theme = theme)
122
+ val theme = theme.format()
123
+ val settings = settings.format()
124
+ val config = PrimerConfig(theme, settings)
125
+
126
+ // todo: refactor with next version
127
+ mListener.completion = { error, clientToken ->
128
+ currentActivity?.let {
129
+ it.runOnUiThread {
130
+ if (error != null) {
131
+ mListener.resumeHandler?.handleError(Error(error))
132
+ } else {
133
+ if (clientToken == null) {
134
+ mListener.resumeHandler?.handleSuccess()
135
+ } else {
136
+ mListener.resumeHandler?.handleNewClientToken(clientToken)
137
+ }
138
+ }
139
+ }
140
+ }
141
+ }
142
+
143
+ Primer.instance.configure(config, mListener)
119
144
  sdkWasInitialised = true
120
145
  }
121
146
 
@@ -125,28 +150,12 @@ class PrimerRN(reactContext: ReactApplicationContext) : ReactContextBaseJavaModu
125
150
 
126
151
  if (!sdkWasInitialised) startSdk(token)
127
152
 
128
- Primer.getSavedPaymentMethods { data ->
129
- try {
130
- val paymentMethods = data.map { PrimerPaymentInstrumentTokenRN.fromPaymentMethodToken(it) }
131
- val request = json.encodeToString(paymentMethods)
132
- mListener.onSavedPaymentInstrumentsFetchedQueue?.addRequestAndPoll(request)
133
- } catch (e: Exception) {
134
- Log.e("PrimerRN", "fetch saved payment methods error: $e")
135
- val exception = PrimerErrorRN(
136
- ErrorTypeRN.ParseJsonFailed,
137
- "failed to parse fetched payment methods.",
138
- )
139
- val encoded = json.encodeToString(exception)
140
- mListener.onPrimerErrorQueue?.addRequestAndPoll(encoded)
141
- haltExecution = true
142
- }
143
- }
153
+ Primer.instance.fetchSavedPaymentInstruments(token)
144
154
  }
145
155
 
146
156
  @ReactMethod
147
157
  fun initialize(token: String) {
148
158
  try {
149
-
150
159
  if (haltExecution) {
151
160
  haltExecution = false
152
161
  return
@@ -154,50 +163,13 @@ class PrimerRN(reactContext: ReactApplicationContext) : ReactContextBaseJavaModu
154
163
 
155
164
  Log.d("PrimerRN", "init with client token: $token")
156
165
 
157
- val theme = this.theme.primerTheme
158
-
159
- val context = currentActivity as Context
160
-
161
166
  startSdk(token)
162
167
 
163
- val paymentMethods = intent.toPaymentMethods(settings)
164
- Primer.loadPaymentMethods(paymentMethods)
165
-
166
- mListener.completion = { error ->
167
- currentActivity?.let {
168
- it.runOnUiThread {
169
- if (error) {
170
- Primer.showError()
171
- } else {
172
- Primer.showSuccess()
173
- }
174
- }
175
- }
176
- }
168
+ val context = currentActivity as Context
177
169
 
178
170
  when (intent.vault) {
179
- false -> Primer.showCheckout(
180
- context,
181
- mListener,
182
- isStandalonePaymentMethod = paymentMethods.size < 2,
183
- doNotShowUi = !(settings.options?.isLoadingScreenEnabled ?: true),
184
- preferWebView = true,
185
- currency = settings.order?.currency,
186
- amount = settings.order?.amount,
187
- clearAllListeners = true,
188
- webBrowserRedirectScheme = settings.options?.android?.redirectScheme,
189
- )
190
- true -> Primer.showVault(
191
- context,
192
- mListener,
193
- isStandalonePaymentMethod = paymentMethods.size < 2,
194
- doNotShowUi = !(settings.options?.isLoadingScreenEnabled ?: true),
195
- preferWebView = true,
196
- currency = settings.order?.currency,
197
- amount = settings.order?.amount,
198
- clearAllListeners = true,
199
- webBrowserRedirectScheme = settings.options?.android?.redirectScheme,
200
- )
171
+ false -> Primer.instance.showUniversalCheckout(context, token)
172
+ true -> Primer.instance.showVaultManager(context, token)
201
173
  }
202
174
  } catch (e: Exception) {
203
175
  Log.e("PrimerRN", "init error: $e")
@@ -213,8 +185,9 @@ class PrimerRN(reactContext: ReactApplicationContext) : ReactContextBaseJavaModu
213
185
  @ReactMethod
214
186
  fun resume(request: String) {
215
187
  try {
188
+ Log.d("PrimerRN", "resume: $request")
216
189
  val data = json.decodeFromString<PrimerResumeRequest>(request)
217
- mListener.completion?.invoke(data.error)
190
+ mListener.completion?.invoke(data.error, data.token)
218
191
  } catch (e: Exception) {
219
192
  Log.e("PrimerRN", "configure settings error: $e")
220
193
  val exception = PrimerErrorRN(
@@ -7,7 +7,7 @@ import com.primerioreactnative.datamodels.PrimerErrorRN
7
7
  import com.primerioreactnative.datamodels.PrimerPaymentInstrumentTokenRN
8
8
  import com.primerioreactnative.utils.PrimerEventQueueRN
9
9
  import io.primer.android.CheckoutEventListener
10
- import io.primer.android.Primer
10
+ import io.primer.android.completion.ResumeHandler
11
11
  import io.primer.android.events.CheckoutEvent
12
12
  import kotlinx.serialization.encodeToString
13
13
  import kotlinx.serialization.json.Json
@@ -15,18 +15,26 @@ import kotlinx.serialization.json.Json
15
15
  class PrimerRNEventListener : CheckoutEventListener {
16
16
 
17
17
  private var onTokenizeSuccessQueue: PrimerEventQueueRN? = null
18
+ private var onResumeSuccessQueue: PrimerEventQueueRN? = null
18
19
  private var onVaultSuccessQueue: PrimerEventQueueRN? = null
19
20
  private var onDismissQueue: PrimerEventQueueRN? = null
20
21
  var onPrimerErrorQueue: PrimerEventQueueRN? = null
21
22
  var onSavedPaymentInstrumentsFetchedQueue: PrimerEventQueueRN? = null
22
23
 
23
- var completion: ((error: Boolean) -> Unit)? = null
24
+ var completion: ((error: String?, token: String?) -> Unit)? = null
25
+
26
+ var resumeHandler: ResumeHandler? = null
24
27
 
25
28
  fun configureOnTokenizeSuccess(callback: Callback) {
26
29
  onTokenizeSuccessQueue = PrimerEventQueueRN()
27
30
  onTokenizeSuccessQueue?.poll(callback)
28
31
  }
29
32
 
33
+ fun configureOnResumeSuccess(callback: Callback) {
34
+ onResumeSuccessQueue = PrimerEventQueueRN()
35
+ onResumeSuccessQueue?.poll(callback)
36
+ }
37
+
30
38
  fun configureOnVaultSuccess(callback: Callback) {
31
39
  onVaultSuccessQueue = PrimerEventQueueRN()
32
40
  onVaultSuccessQueue?.poll(callback)
@@ -58,14 +66,24 @@ class PrimerRNEventListener : CheckoutEventListener {
58
66
  val token = PrimerPaymentInstrumentTokenRN.fromPaymentMethodToken(e.data)
59
67
  val request = Json.encodeToString(token)
60
68
  onTokenizeSuccessQueue?.addRequestAndPoll(request)
69
+ resumeHandler = e.resumeHandler
61
70
  }
62
71
  is CheckoutEvent.TokenSelected -> {
63
72
  val token = PrimerPaymentInstrumentTokenRN.fromPaymentMethodToken(e.data)
64
73
  val request = Json.encodeToString(token)
65
74
  onTokenizeSuccessQueue?.addRequestAndPoll(request)
66
75
  }
76
+ is CheckoutEvent.ResumeSuccess -> {
77
+ val token = e.resumeToken
78
+ onResumeSuccessQueue?.addRequestAndPoll(token)
79
+ resumeHandler = e.resumeHandler
80
+ }
81
+ is CheckoutEvent.SavedPaymentInstrumentsFetched -> {
82
+ val list = e.data.map { PrimerPaymentInstrumentTokenRN.fromPaymentMethodToken(it) }
83
+ val request = Json.encodeToString(list)
84
+ onSavedPaymentInstrumentsFetchedQueue?.addRequestAndPoll(request)
85
+ }
67
86
  is CheckoutEvent.Exit -> {
68
- println("🔥 exit event ${e.data}")
69
87
  onDismissQueue?.addRequestAndPoll("dismiss")
70
88
  onDismissQueue = null
71
89
  }
@@ -4,5 +4,6 @@ import kotlinx.serialization.*
4
4
 
5
5
  @Serializable
6
6
  data class PrimerResumeRequest(
7
- val error: Boolean,
7
+ val error: String? = null,
8
+ val token: String? = null,
8
9
  )
@@ -1,14 +1,24 @@
1
1
  package com.primerioreactnative.datamodels
2
2
 
3
+ import io.primer.android.model.PrimerDebugOptions
4
+ import io.primer.android.model.dto.*
3
5
  import kotlinx.serialization.Serializable
4
6
 
5
7
  @Serializable
6
8
  class PrimerSettingsRN(
7
9
  val order: OrderRN? = null,
8
10
  val business: BusinessRN? = null,
9
- val customer: CustomerRN? = null,
10
- val options: OptionsRN? = null,
11
- )
11
+ private val customer: CustomerRN? = null,
12
+ private val options: OptionsRN? = null,
13
+ ) {
14
+ fun format(): PrimerSettings {
15
+ val order = order?.format() ?: Order()
16
+ val customer = customer?.format() ?: Customer()
17
+ val business = business?.format() ?: Business()
18
+ val options = options?.format() ?: Options()
19
+ return PrimerSettings(order, customer, business, options)
20
+ }
21
+ }
12
22
 
13
23
  @Serializable
14
24
  data class OrderRN(
@@ -17,7 +27,16 @@ data class OrderRN(
17
27
  val countryCode: String? = null,
18
28
  val items: List<OrderItemRN>? = null,
19
29
  val shipping: PrimerAddressRN? = null,
20
- )
30
+ ) {
31
+ fun format(): Order {
32
+ return Order(
33
+ amount = amount,
34
+ currency = currency,
35
+ countryCode = countryCode?.let { CountryCode.valueOf(it) },
36
+
37
+ )
38
+ }
39
+ }
21
40
 
22
41
  @Serializable
23
42
  data class OrderItemRN(
@@ -34,7 +53,18 @@ data class BusinessRN(
34
53
  val email: String? = null,
35
54
  val phone: String? = null,
36
55
  val address: PrimerAddressRN? = null,
37
- )
56
+ ) {
57
+
58
+ fun format(): Business {
59
+ return Business(
60
+ name = name,
61
+ registrationNumber = registrationNumber,
62
+ email = email,
63
+ phone = phone,
64
+ address = address?.format(),
65
+ )
66
+ }
67
+ }
38
68
 
39
69
  @Serializable
40
70
  data class CustomerRN(
@@ -44,16 +74,39 @@ data class CustomerRN(
44
74
  val email: String? = null,
45
75
  val phone: String? = null,
46
76
  val billing: PrimerAddressRN? = null,
47
- )
77
+ ) {
78
+ fun format(): Customer {
79
+ return Customer(
80
+ id = id,
81
+ firstName = firstName,
82
+ lastName = lastName,
83
+ email = email,
84
+ homePhone = phone,
85
+ billingAddress = billing?.format(),
86
+ )
87
+ }
88
+ }
48
89
 
49
90
  @Serializable
50
91
  data class OptionsRN(
51
92
  val isResultScreenEnabled: Boolean? = null,
52
93
  val isLoadingScreenEnabled: Boolean? = null,
53
94
  val isFullScreenEnabled: Boolean? = null,
95
+ val isThreeDsEnabled: Boolean? = null,
54
96
  val locale: String? = null,
55
97
  val android: AndroidOptionsRN? = null,
56
- )
98
+ ) {
99
+ fun format(): Options {
100
+ return Options(
101
+ showUI = isLoadingScreenEnabled ?: true,
102
+ redirectScheme = android?.redirectScheme,
103
+ is3DSOnVaultingEnabled = isThreeDsEnabled ?: false,
104
+ debugOptions = PrimerDebugOptions(
105
+ is3DSSanityCheckEnabled = true, // false on emulator
106
+ ),
107
+ )
108
+ }
109
+ }
57
110
 
58
111
  @Serializable
59
112
  data class AndroidOptionsRN(
@@ -62,10 +115,30 @@ data class AndroidOptionsRN(
62
115
 
63
116
  @Serializable
64
117
  data class PrimerAddressRN(
65
- val line1: String,
118
+ val line1: String?,
66
119
  val line2: String? = null,
67
- val postalCode: String,
120
+ val postalCode: String?,
68
121
  val state: String? = null,
69
- val city: String,
70
- val country: String,
71
- )
122
+ val city: String?,
123
+ val country: String?,
124
+ ) {
125
+
126
+ fun format(): Address? {
127
+ if (
128
+ line1 == null ||
129
+ postalCode == null ||
130
+ city == null ||
131
+ country == null
132
+ ) {
133
+ return null
134
+ }
135
+
136
+ return Address(
137
+ line1 = line1,
138
+ line2 = line2,
139
+ city = city,
140
+ countryCode = CountryCode.valueOf(country),
141
+ postalCode = postalCode,
142
+ )
143
+ }
144
+ }
@@ -1,6 +1,7 @@
1
1
  package com.primerioreactnative.datamodels
2
2
 
3
- import io.primer.android.UniversalCheckoutTheme
3
+ import io.primer.android.InputThemeData
4
+ import io.primer.android.PrimerTheme
4
5
  import kotlinx.serialization.Serializable
5
6
 
6
7
  @Serializable
@@ -8,20 +9,11 @@ class PrimerThemeRN(
8
9
  private val colors: ColorThemeRN? = null,
9
10
  val darkModeColors: ColorThemeRN? = null,
10
11
  ) {
11
- val primerTheme: UniversalCheckoutTheme
12
- get() {
13
- return UniversalCheckoutTheme.create(
14
- textDefaultColor = colors?.text?.hex,
15
- textDangerColor = colors?.error?.hex,
16
- textMutedColor = colors?.disabled?.hex,
17
- backgroundColor = colors?.background?.hex,
18
- buttonPrimaryColor = colors?.mainColor?.hex,
19
- buttonPrimaryColorDisabled = colors?.disabled?.hex,
20
- primaryColor = colors?.mainColor?.hex,
21
- inputBackgroundColor = colors?.background?.hex,
22
- buttonDefaultBorderColor = colors?.borders?.hex,
12
+ fun format(): PrimerTheme {
13
+ return PrimerTheme.build(
14
+ input = InputThemeData()
23
15
  )
24
- }
16
+ }
25
17
  }
26
18
 
27
19
  @Serializable
@@ -13,3 +13,7 @@ enum ErrorTypeRN: String, Error, Encodable {
13
13
  case clientTokenNotConfigured
14
14
  case flowParsingFailed
15
15
  }
16
+
17
+ struct ErrorRN: Error {
18
+ let message: String
19
+ }
@@ -5,7 +5,8 @@ struct PrimerInitRequest: Decodable {
5
5
  }
6
6
 
7
7
  struct PrimerResumeRequest: Decodable {
8
- let error: Bool;
8
+ let error: String?
9
+ let token: String?
9
10
  }
10
11
 
11
12
  struct PrimerRequestMetadata: Decodable {
@@ -9,6 +9,18 @@ struct PrimerSettingsRN: Decodable {
9
9
 
10
10
  extension PrimerSettingsRN {
11
11
  func asPrimerSettings() -> PrimerSettings {
12
+ var address: Address?
13
+ if let billingAddress = customer?.billing {
14
+ address = Address(
15
+ addressLine1: billingAddress.line1,
16
+ addressLine2: billingAddress.line2,
17
+ city: billingAddress.city,
18
+ state: billingAddress.state,
19
+ countryCode: billingAddress.country?.rawValue,
20
+ postalCode: billingAddress.postalCode
21
+ )
22
+ }
23
+
12
24
  return PrimerSettings(
13
25
  merchantIdentifier: options?.ios?.merchantIdentifier,
14
26
  customerId: customer?.id,
@@ -22,14 +34,26 @@ extension PrimerSettingsRN {
22
34
  hasDisabledSuccessScreen: !(options?.isResultScreenEnabled ?? true),
23
35
  businessDetails: business?.primerFormat,
24
36
  orderItems: order?.itemsFormatted ?? [],
25
- isInitialLoadingHidden: !(options?.isLoadingScreenEnabled ?? true)
37
+ isInitialLoadingHidden: !(options?.isLoadingScreenEnabled ?? true),
38
+ orderId: order?.id,
39
+ customer: Customer(
40
+ firstName: customer?.firstName,
41
+ lastName: customer?.lastName,
42
+ email: customer?.email,
43
+ homePhoneNumber: nil,
44
+ mobilePhoneNumber: customer?.phone,
45
+ workPhoneNumber: nil,
46
+ billingAddress: address
47
+ )
26
48
  )
27
49
  }
28
50
  }
29
51
 
30
52
  fileprivate struct OrderRN: Decodable {
53
+ let id: String?
31
54
  let amount: Int?
32
55
  let currency: Currency?
56
+ // FIXME: Move countryCode only within Address (RN & Android)
33
57
  let countryCode: CountryCode?
34
58
  let items: [OrderItemRN]?
35
59
  let shipping: AddressRN?
@@ -70,11 +94,15 @@ fileprivate struct BusinessRN: Decodable {
70
94
  let registrationNumber: String?
71
95
  let email: String?
72
96
  let phone: String?
73
- let address: AddressRN
97
+ let address: AddressRN?
74
98
  }
75
99
 
76
100
  fileprivate extension BusinessRN {
77
- var primerFormat: BusinessDetails {
101
+ var primerFormat: BusinessDetails? {
102
+ guard let address = address else {
103
+ return nil
104
+ }
105
+
78
106
  return BusinessDetails(
79
107
  name: name,
80
108
  address: address.primerFormat
@@ -97,7 +125,7 @@ fileprivate struct AddressRN: Decodable {
97
125
  let postalCode: String?
98
126
  let city: String?
99
127
  let state: String?
100
- let country: String?
128
+ let country: CountryCode?
101
129
  }
102
130
 
103
131
  fileprivate extension AddressRN {
@@ -107,7 +135,7 @@ fileprivate extension AddressRN {
107
135
  addressLine2: line2,
108
136
  city: city,
109
137
  state: state,
110
- countryCode: country,
138
+ countryCode: country?.rawValue,
111
139
  postalCode: postalCode
112
140
  )
113
141
  }
@@ -17,7 +17,10 @@ extension PrimerRN: PrimerDelegate {
17
17
  completion(clientToken, nil)
18
18
  }
19
19
 
20
- func onTokenizeSuccess(_ paymentMethodToken: PaymentMethodToken, _ completion: @escaping (Error?) -> Void) {
20
+ func onTokenizeSuccess(
21
+ _ paymentMethodToken: PaymentMethodToken,
22
+ resumeHandler: ResumeHandlerProtocol
23
+ ) {
21
24
  do {
22
25
  let json = try encoder.encode(paymentMethodToken)
23
26
  let data = String(data: json, encoding: .utf8)!
@@ -25,7 +28,29 @@ extension PrimerRN: PrimerDelegate {
25
28
  } catch {
26
29
  checkoutFailed(with: ErrorTypeRN.ParseJsonFailed)
27
30
  }
28
- onResumeFlowCallback = completion
31
+ onResumeFlowCallback = { error, clientToken in
32
+ if let error = error {
33
+ resumeHandler.handle(error: error)
34
+ } else if let clientToken = clientToken {
35
+ resumeHandler.handle(newClientToken: clientToken)
36
+ } else {
37
+ resumeHandler.handleSuccess()
38
+ }
39
+ }
40
+ }
41
+
42
+ func onResumeSuccess(_ clientToken: String, resumeHandler: ResumeHandlerProtocol) {
43
+ self.onResumeSuccessCallback?([clientToken])
44
+
45
+ onResumeFlowCallback = { error, clientToken in
46
+ if let error = error {
47
+ resumeHandler.handle(error: error)
48
+ } else if let clientToken = clientToken {
49
+ resumeHandler.handle(newClientToken: clientToken)
50
+ } else {
51
+ resumeHandler.handleSuccess()
52
+ }
53
+ }
29
54
  }
30
55
 
31
56
  func tokenAddedToVault(_ token: PaymentMethodToken) {
@@ -1,7 +1,7 @@
1
1
  import UIKit
2
2
  import PrimerSDK
3
3
 
4
- typealias BasicCompletionBlock = ((Error?) -> Void)
4
+ typealias BasicCompletionBlock = ((Error?, String?) -> Void)
5
5
 
6
6
  @objc(PrimerRN)
7
7
  class PrimerRN: NSObject {
@@ -17,6 +17,7 @@ class PrimerRN: NSObject {
17
17
  var theme: PrimerThemeRN?
18
18
  var flow: PrimerSessionFlow?
19
19
  var onTokenizeSuccessCallback: RCTResponseSenderBlock?
20
+ var onResumeSuccessCallback: RCTResponseSenderBlock?
20
21
  var onVaultSuccessCallback: RCTResponseSenderBlock?
21
22
  var onDismissCallback: RCTResponseSenderBlock?
22
23
  var onPrimerErrorCallback: RCTResponseSenderBlock?
@@ -60,6 +61,10 @@ class PrimerRN: NSObject {
60
61
  self.onTokenizeSuccessCallback = callback
61
62
  }
62
63
 
64
+ @objc func configureOnResumeSuccess(_ callback: @escaping RCTResponseSenderBlock) {
65
+ self.onResumeSuccessCallback = callback
66
+ }
67
+
63
68
  @objc func configureOnVaultSuccess(_ callback: @escaping RCTResponseSenderBlock) {
64
69
  self.onVaultSuccessCallback = callback
65
70
  }
@@ -122,7 +127,6 @@ class PrimerRN: NSObject {
122
127
  Primer.shared.delegate = self
123
128
  Primer.shared.configure(settings: settings, theme: theme)
124
129
  Primer.shared.showCheckout(viewController, flow: flow)
125
-
126
130
  } catch {
127
131
  self?.checkoutFailed(with: error)
128
132
  }
@@ -135,10 +139,12 @@ class PrimerRN: NSObject {
135
139
  let json = request.data(using: .utf8)!
136
140
  let request = try JSONDecoder().decode(PrimerResumeRequest.self, from: json)
137
141
 
138
- if (request.error) {
139
- self?.onResumeFlowCallback?(ErrorTypeRN.ParseJsonFailed)
142
+ if let error = request.error {
143
+ self?.onResumeFlowCallback?(ErrorRN(message: error), nil)
144
+ } else if let clientToken = request.token {
145
+ self?.onResumeFlowCallback?(nil, clientToken)
140
146
  } else {
141
- self?.onResumeFlowCallback?(nil)
147
+ self?.onResumeFlowCallback?(nil, nil)
142
148
  }
143
149
  self?.onResumeFlowCallback = nil
144
150
  } catch {
package/ios/ReactNative.m CHANGED
@@ -11,6 +11,8 @@ RCT_EXTERN_METHOD(configureIntent: (NSString *)request)
11
11
 
12
12
  RCT_EXTERN_METHOD(configureOnTokenizeSuccess: (RCTResponseSenderBlock)callback)
13
13
 
14
+ RCT_EXTERN_METHOD(configureOnResumeSuccess: (RCTResponseSenderBlock)callback)
15
+
14
16
  RCT_EXTERN_METHOD(configureOnVaultSuccess: (RCTResponseSenderBlock)callback)
15
17
 
16
18
  RCT_EXTERN_METHOD(configureOnDismiss: (RCTResponseSenderBlock)callback)