framepayments-react-native 2.1.0 → 2.1.2
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/README.md +101 -74
- package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameCheckoutActivity$Companion.dex +0 -0
- package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameCheckoutActivity$tryShowCheckout$1.dex +0 -0
- package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameCheckoutActivity.dex +0 -0
- package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameFlowActivity$CartItemDto.dex +0 -0
- package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameFlowActivity$Companion.dex +0 -0
- package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameFlowActivity$parseCartItems$type$1.dex +0 -0
- package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameFlowActivity.dex +0 -0
- package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameGooglePayActivity$Companion.dex +0 -0
- package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameGooglePayActivity.dex +0 -0
- package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameOnboardingActivity$Companion.dex +0 -0
- package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameOnboardingActivity$parseCapabilities$type$1.dex +0 -0
- package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameOnboardingActivity.dex +0 -0
- package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/framepayments/reactnativeframe/FrameSDKModule.dex +0 -0
- package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameCheckoutActivity$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameCheckoutActivity$tryShowCheckout$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameCheckoutActivity.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameFlowActivity$CartItemDto.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameFlowActivity$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameFlowActivity$parseCartItems$type$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameFlowActivity.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameGooglePayActivity$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameGooglePayActivity.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameOnboardingActivity$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameOnboardingActivity$parseCapabilities$type$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameOnboardingActivity.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/framepayments/reactnativeframe/FrameSDKModule.class +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
- package/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameCheckoutActivity$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameCheckoutActivity$tryShowCheckout$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameCheckoutActivity.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameFlowActivity$CartItemDto.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameFlowActivity$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameFlowActivity$parseCartItems$type$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameFlowActivity.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameGooglePayActivity$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameGooglePayActivity.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameOnboardingActivity$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameOnboardingActivity$parseCapabilities$type$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameOnboardingActivity.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/framepayments/reactnativeframe/FrameSDKModule.class +0 -0
- package/android/build.gradle +3 -3
- package/android/src/main/java/com/framepayments/reactnativeframe/FrameCheckoutActivity.kt +17 -13
- package/android/src/main/java/com/framepayments/reactnativeframe/FrameFlowActivity.kt +18 -11
- package/android/src/main/java/com/framepayments/reactnativeframe/FrameGooglePayActivity.kt +31 -8
- package/android/src/main/java/com/framepayments/reactnativeframe/FrameSDKModule.kt +37 -36
- package/ios/ApplePayPresenter.swift +53 -28
- package/ios/FrameRNTheme.swift +3 -24
- package/ios/FrameSDKBridge.m +10 -17
- package/ios/FrameSDKBridge.swift +89 -64
- package/lib/errors.d.ts +9 -1
- package/lib/errors.d.ts.map +1 -1
- package/lib/errors.js +9 -1
- package/lib/index.d.ts +4 -5
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -4
- package/lib/native.d.ts +41 -13
- package/lib/native.d.ts.map +1 -1
- package/lib/native.js +64 -23
- package/lib/types.d.ts +18 -45
- package/lib/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/native.test.ts +179 -25
- package/src/errors.ts +9 -1
- package/src/index.ts +2 -7
- package/src/native.ts +83 -32
- package/src/types.ts +19 -58
- /package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_global-synthetics/com/framepayments/reactnativeframe/{FrameSDKModule$$InternalSyntheticLambda$2$984ab30558bc904ed37602fa6e3ebf28f1ed69df6712b31b00c4f26fc26d3b70$0.globals → FrameSDKModule$$InternalSyntheticLambda$2$7347ff5b95d03cf5be9ee5177309c1bf4be5faabda2bbedb79f5f4c91917c2b1$0.globals} +0 -0
- /package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_global-synthetics/com/framepayments/reactnativeframe/{FrameSDKModule$$InternalSyntheticLambda$2$f8d46f7169c404d37a1d505f19439b83090fbed62b5bdaf1e86717fdddebf622$0.globals → FrameSDKModule$$InternalSyntheticLambda$2$7347ff5b95d03cf5be9ee5177309c1bf4be5faabda2bbedb79f5f4c91917c2b1$1.globals} +0 -0
- /package/android/build/.transforms/5a2061641b1fc5518a336681809507bc/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_global-synthetics/com/framepayments/reactnativeframe/{FrameSDKModule$$InternalSyntheticLambda$2$f8d46f7169c404d37a1d505f19439b83090fbed62b5bdaf1e86717fdddebf622$1.globals → FrameSDKModule$$InternalSyntheticLambda$2$9816d2cb3db63bf5efb3411b62dbb57847dd7ef82f88bae5f375baced7880f11$0.globals} +0 -0
|
@@ -27,11 +27,19 @@ class FrameFlowActivity : AppCompatActivity() {
|
|
|
27
27
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
28
28
|
super.onCreate(savedInstanceState)
|
|
29
29
|
setContentView(container)
|
|
30
|
-
val
|
|
30
|
+
val accountId = intent.getStringExtra(EXTRA_ACCOUNT_ID)
|
|
31
31
|
val itemsJson = intent.getStringExtra(EXTRA_ITEMS_JSON)
|
|
32
32
|
val shippingCents = intent.getIntExtra(EXTRA_SHIPPING_CENTS, 0)
|
|
33
33
|
val items: List<FrameCartItem> = parseCartItems(itemsJson) ?: emptyList()
|
|
34
|
-
|
|
34
|
+
|
|
35
|
+
// Bundled cart → checkout always creates a Transfer, which requires an account.
|
|
36
|
+
if (accountId.isNullOrEmpty()) {
|
|
37
|
+
setResult(RESULT_CANCELED)
|
|
38
|
+
finish()
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
showCart(accountId, items, shippingCents)
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
private fun parseCartItems(json: String?): List<FrameCartItem>? {
|
|
@@ -52,22 +60,21 @@ class FrameFlowActivity : AppCompatActivity() {
|
|
|
52
60
|
val imageUrl: String
|
|
53
61
|
)
|
|
54
62
|
|
|
55
|
-
private fun showCart(
|
|
63
|
+
private fun showCart(accountId: String, items: List<FrameCartItem>, shippingCents: Int) {
|
|
56
64
|
container.removeAllViews()
|
|
57
65
|
cartView = FrameCartView(this).apply {
|
|
58
|
-
configure(
|
|
59
|
-
showCheckout(
|
|
66
|
+
configure(accountId, items, shippingCents, { totalCents ->
|
|
67
|
+
showCheckout(accountId, totalCents)
|
|
60
68
|
}, null)
|
|
61
69
|
}
|
|
62
70
|
container.addView(cartView)
|
|
63
71
|
}
|
|
64
72
|
|
|
65
|
-
private fun showCheckout(
|
|
73
|
+
private fun showCheckout(accountId: String, amount: Int) {
|
|
66
74
|
container.removeAllViews()
|
|
67
75
|
checkoutView = FrameCheckoutView(this).apply {
|
|
68
|
-
configure(
|
|
69
|
-
|
|
70
|
-
setResult(RESULT_OK, Intent().putExtra(EXTRA_CHARGE_INTENT_JSON, json))
|
|
76
|
+
configure(accountId, amount) { transferId ->
|
|
77
|
+
setResult(RESULT_OK, Intent().putExtra(EXTRA_TRANSFER_ID, transferId))
|
|
71
78
|
finish()
|
|
72
79
|
}
|
|
73
80
|
}
|
|
@@ -75,10 +82,10 @@ class FrameFlowActivity : AppCompatActivity() {
|
|
|
75
82
|
}
|
|
76
83
|
|
|
77
84
|
companion object {
|
|
78
|
-
const val
|
|
85
|
+
const val EXTRA_ACCOUNT_ID = "account_id"
|
|
79
86
|
const val EXTRA_ITEMS_JSON = "items_json"
|
|
80
87
|
const val EXTRA_SHIPPING_CENTS = "shipping_cents"
|
|
81
|
-
const val
|
|
88
|
+
const val EXTRA_TRANSFER_ID = "transfer_id"
|
|
82
89
|
const val REQUEST_CODE = 9002
|
|
83
90
|
}
|
|
84
91
|
}
|
|
@@ -4,11 +4,9 @@ import android.content.Intent
|
|
|
4
4
|
import android.os.Bundle
|
|
5
5
|
import android.os.Handler
|
|
6
6
|
import android.os.Looper
|
|
7
|
-
import android.view.View
|
|
8
7
|
import android.widget.FrameLayout
|
|
9
8
|
import androidx.appcompat.app.AppCompatActivity
|
|
10
9
|
import com.framepayments.framesdk_ui.buttons.FrameGooglePayButton
|
|
11
|
-
import com.google.gson.Gson
|
|
12
10
|
|
|
13
11
|
/**
|
|
14
12
|
* Hidden host activity for Frame.presentGooglePay(). The Frame Android SDK only
|
|
@@ -39,7 +37,8 @@ class FrameGooglePayActivity : AppCompatActivity() {
|
|
|
39
37
|
setContentView(container)
|
|
40
38
|
|
|
41
39
|
val amountCents = intent.getIntExtra(EXTRA_AMOUNT_CENTS, 0)
|
|
42
|
-
val
|
|
40
|
+
val ownerType = intent.getStringExtra(EXTRA_OWNER_TYPE)
|
|
41
|
+
val ownerId = intent.getStringExtra(EXTRA_OWNER_ID)
|
|
43
42
|
val currencyCode = intent.getStringExtra(EXTRA_CURRENCY) ?: "USD"
|
|
44
43
|
val googlePayMerchantId = intent.getStringExtra(EXTRA_MERCHANT_ID)
|
|
45
44
|
|
|
@@ -47,6 +46,18 @@ class FrameGooglePayActivity : AppCompatActivity() {
|
|
|
47
46
|
deliverFailure("Invalid amountCents")
|
|
48
47
|
return
|
|
49
48
|
}
|
|
49
|
+
if (ownerId.isNullOrEmpty()) {
|
|
50
|
+
deliverFailure("owner.id is required")
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
val owner: FrameGooglePayButton.Owner = when (ownerType) {
|
|
54
|
+
"customer" -> FrameGooglePayButton.Owner.Customer(ownerId)
|
|
55
|
+
"account" -> FrameGooglePayButton.Owner.Account(ownerId)
|
|
56
|
+
else -> {
|
|
57
|
+
deliverFailure("owner.type must be 'customer' or 'account'")
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
}
|
|
50
61
|
|
|
51
62
|
val button = FrameGooglePayButton(this)
|
|
52
63
|
button.layoutParams = FrameLayout.LayoutParams(1, 1) // tiny but measurable so click can fire
|
|
@@ -55,7 +66,7 @@ class FrameGooglePayActivity : AppCompatActivity() {
|
|
|
55
66
|
|
|
56
67
|
button.configure(
|
|
57
68
|
amountCents = amountCents,
|
|
58
|
-
|
|
69
|
+
owner = owner,
|
|
59
70
|
currencyCode = currencyCode,
|
|
60
71
|
googlePayMerchantId = googlePayMerchantId,
|
|
61
72
|
onResult = { result -> handleResult(result) },
|
|
@@ -94,8 +105,14 @@ class FrameGooglePayActivity : AppCompatActivity() {
|
|
|
94
105
|
didDeliverResult = true
|
|
95
106
|
when (result) {
|
|
96
107
|
is FrameGooglePayButton.Result.Success -> {
|
|
97
|
-
|
|
98
|
-
|
|
108
|
+
// `result.id` is a Transfer id (for Owner.Account) or a ChargeIntent id
|
|
109
|
+
// (for Owner.Customer). JS knows which it is because it passed the owner.
|
|
110
|
+
deliverViaCallback(android.app.Activity.RESULT_OK, Intent().putExtra(EXTRA_CHARGE_ID, result.id))
|
|
111
|
+
}
|
|
112
|
+
is FrameGooglePayButton.Result.PaymentMethodCreated -> {
|
|
113
|
+
// RN bridge does not currently expose AddToOwner mode, so this branch
|
|
114
|
+
// shouldn't fire in practice. Surface it as failure instead of silently dropping.
|
|
115
|
+
deliverViaCallback(RESULT_FAILURE, Intent().putExtra(EXTRA_FAILURE_MESSAGE, "Unsupported Google Pay result"))
|
|
99
116
|
}
|
|
100
117
|
is FrameGooglePayButton.Result.Failure -> {
|
|
101
118
|
deliverViaCallback(RESULT_FAILURE, Intent().putExtra(EXTRA_FAILURE_MESSAGE, result.message))
|
|
@@ -133,10 +150,16 @@ class FrameGooglePayActivity : AppCompatActivity() {
|
|
|
133
150
|
|
|
134
151
|
companion object {
|
|
135
152
|
const val EXTRA_AMOUNT_CENTS = "amount_cents"
|
|
136
|
-
const val
|
|
153
|
+
const val EXTRA_OWNER_TYPE = "owner_type"
|
|
154
|
+
const val EXTRA_OWNER_ID = "owner_id"
|
|
137
155
|
const val EXTRA_CURRENCY = "currency"
|
|
138
156
|
const val EXTRA_MERCHANT_ID = "merchant_id"
|
|
139
|
-
|
|
157
|
+
/**
|
|
158
|
+
* The id of the resource created by the wallet flow. Holds a Transfer id when
|
|
159
|
+
* the owner was an account, or a ChargeIntent id when the owner was a customer.
|
|
160
|
+
* JS knows which by inspecting the owner it passed in.
|
|
161
|
+
*/
|
|
162
|
+
const val EXTRA_CHARGE_ID = "charge_id"
|
|
140
163
|
const val EXTRA_FAILURE_MESSAGE = "failure_message"
|
|
141
164
|
|
|
142
165
|
const val REQUEST_CODE = 9003
|
|
@@ -31,7 +31,15 @@ class FrameSDKModule(reactContext: ReactApplicationContext) :
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
@ReactMethod
|
|
34
|
-
fun initialize(
|
|
34
|
+
fun initialize(
|
|
35
|
+
secretKey: String,
|
|
36
|
+
publishableKey: String,
|
|
37
|
+
debugMode: Boolean,
|
|
38
|
+
@Suppress("UNUSED_PARAMETER") theme: com.facebook.react.bridge.ReadableMap?,
|
|
39
|
+
promise: Promise
|
|
40
|
+
) {
|
|
41
|
+
// theme is accepted for cross-platform parity with iOS but is currently a
|
|
42
|
+
// no-op on Android — frame-android does not yet have a matching theme API.
|
|
35
43
|
try {
|
|
36
44
|
val ctx = reactApplicationContext.applicationContext
|
|
37
45
|
FrameNetworking.initializeWithAPIKey(ctx, secretKey, publishableKey, debugMode)
|
|
@@ -42,7 +50,7 @@ class FrameSDKModule(reactContext: ReactApplicationContext) :
|
|
|
42
50
|
}
|
|
43
51
|
|
|
44
52
|
@ReactMethod
|
|
45
|
-
fun presentCheckout(
|
|
53
|
+
fun presentCheckout(accountId: String?, amount: Double, promise: Promise) {
|
|
46
54
|
val activity = reactApplicationContext.currentActivity ?: run {
|
|
47
55
|
promise.reject("NO_ACTIVITY", "No current activity", null)
|
|
48
56
|
return
|
|
@@ -50,7 +58,7 @@ class FrameSDKModule(reactContext: ReactApplicationContext) :
|
|
|
50
58
|
checkoutPromise = promise
|
|
51
59
|
activity.runOnUiThread {
|
|
52
60
|
val intent = Intent(activity, FrameCheckoutActivity::class.java).apply {
|
|
53
|
-
putExtra(FrameCheckoutActivity.
|
|
61
|
+
putExtra(FrameCheckoutActivity.EXTRA_ACCOUNT_ID, accountId)
|
|
54
62
|
putExtra(FrameCheckoutActivity.EXTRA_AMOUNT, amount.toInt())
|
|
55
63
|
}
|
|
56
64
|
activity.startActivityForResult(intent, FrameCheckoutActivity.REQUEST_CODE)
|
|
@@ -59,7 +67,7 @@ class FrameSDKModule(reactContext: ReactApplicationContext) :
|
|
|
59
67
|
|
|
60
68
|
@ReactMethod
|
|
61
69
|
fun presentCart(
|
|
62
|
-
|
|
70
|
+
accountId: String?,
|
|
63
71
|
items: com.facebook.react.bridge.ReadableArray,
|
|
64
72
|
shippingAmountInCents: Double,
|
|
65
73
|
promise: Promise
|
|
@@ -75,7 +83,7 @@ class FrameSDKModule(reactContext: ReactApplicationContext) :
|
|
|
75
83
|
cartPromise = promise
|
|
76
84
|
activity.runOnUiThread {
|
|
77
85
|
val intent = Intent(activity, FrameFlowActivity::class.java).apply {
|
|
78
|
-
putExtra(FrameFlowActivity.
|
|
86
|
+
putExtra(FrameFlowActivity.EXTRA_ACCOUNT_ID, accountId)
|
|
79
87
|
putExtra(FrameFlowActivity.EXTRA_ITEMS_JSON, itemsJson)
|
|
80
88
|
putExtra(FrameFlowActivity.EXTRA_SHIPPING_CENTS, shippingAmountInCents.toInt())
|
|
81
89
|
}
|
|
@@ -86,7 +94,8 @@ class FrameSDKModule(reactContext: ReactApplicationContext) :
|
|
|
86
94
|
@ReactMethod
|
|
87
95
|
fun presentGooglePay(
|
|
88
96
|
amountCents: Double,
|
|
89
|
-
|
|
97
|
+
ownerType: String?,
|
|
98
|
+
ownerId: String?,
|
|
90
99
|
currencyCode: String?,
|
|
91
100
|
googlePayMerchantId: String?,
|
|
92
101
|
promise: Promise
|
|
@@ -100,6 +109,14 @@ class FrameSDKModule(reactContext: ReactApplicationContext) :
|
|
|
100
109
|
promise.reject("INVALID_AMOUNT", "amountCents must be positive", null)
|
|
101
110
|
return
|
|
102
111
|
}
|
|
112
|
+
if (ownerType != "customer" && ownerType != "account") {
|
|
113
|
+
promise.reject("INVALID_OWNER", "owner.type must be 'customer' or 'account'", null)
|
|
114
|
+
return
|
|
115
|
+
}
|
|
116
|
+
if (ownerId.isNullOrEmpty()) {
|
|
117
|
+
promise.reject("INVALID_OWNER", "owner.id is required", null)
|
|
118
|
+
return
|
|
119
|
+
}
|
|
103
120
|
googlePayPromise = promise
|
|
104
121
|
pendingGooglePayCallback = { resultCode, data ->
|
|
105
122
|
handleGooglePayResult(resultCode, data)
|
|
@@ -107,7 +124,8 @@ class FrameSDKModule(reactContext: ReactApplicationContext) :
|
|
|
107
124
|
activity.runOnUiThread {
|
|
108
125
|
val intent = Intent(activity, FrameGooglePayActivity::class.java).apply {
|
|
109
126
|
putExtra(FrameGooglePayActivity.EXTRA_AMOUNT_CENTS, amountInt)
|
|
110
|
-
putExtra(FrameGooglePayActivity.
|
|
127
|
+
putExtra(FrameGooglePayActivity.EXTRA_OWNER_TYPE, ownerType)
|
|
128
|
+
putExtra(FrameGooglePayActivity.EXTRA_OWNER_ID, ownerId)
|
|
111
129
|
putExtra(FrameGooglePayActivity.EXTRA_CURRENCY, currencyCode ?: "USD")
|
|
112
130
|
putExtra(FrameGooglePayActivity.EXTRA_MERCHANT_ID, googlePayMerchantId)
|
|
113
131
|
}
|
|
@@ -174,17 +192,11 @@ class FrameSDKModule(reactContext: ReactApplicationContext) :
|
|
|
174
192
|
val promise = checkoutPromise ?: return
|
|
175
193
|
checkoutPromise = null
|
|
176
194
|
if (resultCode == Activity.RESULT_OK && data != null) {
|
|
177
|
-
val
|
|
178
|
-
if (
|
|
179
|
-
|
|
180
|
-
val obj = JSONObject(json)
|
|
181
|
-
val map = jsonObjectToWritableMap(obj)
|
|
182
|
-
promise.resolve(map)
|
|
183
|
-
} catch (e: Exception) {
|
|
184
|
-
promise.reject("PARSE_ERROR", e.message, e)
|
|
185
|
-
}
|
|
195
|
+
val transferId = data.getStringExtra(FrameCheckoutActivity.EXTRA_TRANSFER_ID)
|
|
196
|
+
if (!transferId.isNullOrEmpty()) {
|
|
197
|
+
promise.resolve(transferId)
|
|
186
198
|
} else {
|
|
187
|
-
promise.reject("NO_RESULT", "No
|
|
199
|
+
promise.reject("NO_RESULT", "No transfer id in result", null)
|
|
188
200
|
}
|
|
189
201
|
} else {
|
|
190
202
|
promise.reject("USER_CANCELED", "User cancelled checkout", null)
|
|
@@ -195,17 +207,11 @@ class FrameSDKModule(reactContext: ReactApplicationContext) :
|
|
|
195
207
|
val promise = cartPromise ?: return
|
|
196
208
|
cartPromise = null
|
|
197
209
|
if (resultCode == Activity.RESULT_OK && data != null) {
|
|
198
|
-
val
|
|
199
|
-
if (
|
|
200
|
-
|
|
201
|
-
val obj = JSONObject(json)
|
|
202
|
-
val map = jsonObjectToWritableMap(obj)
|
|
203
|
-
promise.resolve(map)
|
|
204
|
-
} catch (e: Exception) {
|
|
205
|
-
promise.reject("PARSE_ERROR", e.message, e)
|
|
206
|
-
}
|
|
210
|
+
val transferId = data.getStringExtra(FrameFlowActivity.EXTRA_TRANSFER_ID)
|
|
211
|
+
if (!transferId.isNullOrEmpty()) {
|
|
212
|
+
promise.resolve(transferId)
|
|
207
213
|
} else {
|
|
208
|
-
promise.reject("NO_RESULT", "No
|
|
214
|
+
promise.reject("NO_RESULT", "No transfer id in result", null)
|
|
209
215
|
}
|
|
210
216
|
} else {
|
|
211
217
|
promise.reject("USER_CANCELED", "User cancelled", null)
|
|
@@ -217,16 +223,11 @@ class FrameSDKModule(reactContext: ReactApplicationContext) :
|
|
|
217
223
|
googlePayPromise = null
|
|
218
224
|
when (resultCode) {
|
|
219
225
|
Activity.RESULT_OK -> {
|
|
220
|
-
val
|
|
221
|
-
if (
|
|
222
|
-
|
|
223
|
-
val map = jsonObjectToWritableMap(JSONObject(json))
|
|
224
|
-
promise.resolve(map)
|
|
225
|
-
} catch (e: Exception) {
|
|
226
|
-
promise.reject("PARSE_ERROR", e.message, e)
|
|
227
|
-
}
|
|
226
|
+
val id = data?.getStringExtra(FrameGooglePayActivity.EXTRA_CHARGE_ID)
|
|
227
|
+
if (id.isNullOrEmpty()) {
|
|
228
|
+
promise.reject("NO_RESULT", "Google Pay returned no charge id", null)
|
|
228
229
|
} else {
|
|
229
|
-
promise.
|
|
230
|
+
promise.resolve(id)
|
|
230
231
|
}
|
|
231
232
|
}
|
|
232
233
|
FrameGooglePayActivity.RESULT_FAILURE -> {
|
|
@@ -3,10 +3,14 @@
|
|
|
3
3
|
// FrameReactNative
|
|
4
4
|
//
|
|
5
5
|
// Programmatic Apple Pay presentation for Frame.presentApplePay(). Wraps
|
|
6
|
-
// PKPaymentAuthorizationController + ApplePayAPI + ChargeIntentsAPI
|
|
7
|
-
// so we can detect the user-cancel path
|
|
8
|
-
// didFinish fires for both success and cancel
|
|
9
|
-
// model only delivers success, so we re-implement that flow here
|
|
6
|
+
// PKPaymentAuthorizationController + ApplePayAPI + (ChargeIntentsAPI | TransfersAPI)
|
|
7
|
+
// directly so we can detect the user-cancel path — PKPaymentAuthorizationController's
|
|
8
|
+
// didFinish fires for both success and cancel, and the underlying SDK's view
|
|
9
|
+
// model only delivers success, so we re-implement that flow here.
|
|
10
|
+
//
|
|
11
|
+
// Supports both:
|
|
12
|
+
// - `.customer(id)` owner → creates a `ChargeIntent`; resolves with the ChargeIntent id.
|
|
13
|
+
// - `.account(id)` owner → creates a `Transfer`; resolves with the Transfer id.
|
|
10
14
|
//
|
|
11
15
|
|
|
12
16
|
import Foundation
|
|
@@ -16,9 +20,14 @@ import Frame
|
|
|
16
20
|
@MainActor
|
|
17
21
|
final class ApplePayPresenter: NSObject, PKPaymentAuthorizationControllerDelegate {
|
|
18
22
|
|
|
23
|
+
enum Owner {
|
|
24
|
+
case customer(String)
|
|
25
|
+
case account(String)
|
|
26
|
+
}
|
|
27
|
+
|
|
19
28
|
private let amount: Int
|
|
20
29
|
private let currency: String
|
|
21
|
-
private let owner:
|
|
30
|
+
private let owner: Owner
|
|
22
31
|
private let merchantId: String
|
|
23
32
|
private let resolve: (Any?) -> Void
|
|
24
33
|
private let reject: (String, String, Error?) -> Void
|
|
@@ -36,7 +45,7 @@ final class ApplePayPresenter: NSObject, PKPaymentAuthorizationControllerDelegat
|
|
|
36
45
|
|
|
37
46
|
init(amount: Int,
|
|
38
47
|
currency: String,
|
|
39
|
-
owner:
|
|
48
|
+
owner: Owner,
|
|
40
49
|
merchantId: String,
|
|
41
50
|
resolve: @escaping (Any?) -> Void,
|
|
42
51
|
reject: @escaping (String, String, Error?) -> Void) {
|
|
@@ -80,6 +89,8 @@ final class ApplePayPresenter: NSObject, PKPaymentAuthorizationControllerDelegat
|
|
|
80
89
|
didAuthorizePayment payment: PKPayment
|
|
81
90
|
) async -> PKPaymentAuthorizationResult {
|
|
82
91
|
do {
|
|
92
|
+
// 1. Create the Frame PaymentMethod from the Apple Pay token, scoped to
|
|
93
|
+
// whichever owner the caller asked for.
|
|
83
94
|
let (paymentMethod, methodError): (FrameObjects.PaymentMethod?, NetworkingError?)
|
|
84
95
|
switch owner {
|
|
85
96
|
case .customer(let customerId):
|
|
@@ -97,27 +108,45 @@ final class ApplePayPresenter: NSObject, PKPaymentAuthorizationControllerDelegat
|
|
|
97
108
|
return PKPaymentAuthorizationResult(status: .failure, errors: nil)
|
|
98
109
|
}
|
|
99
110
|
|
|
100
|
-
|
|
111
|
+
// 2. Create the charge. Customer owners produce a ChargeIntent; account
|
|
112
|
+
// owners produce a Transfer. Both surface the resulting id to JS — the
|
|
113
|
+
// caller knows which resource the id refers to based on the owner.
|
|
101
114
|
switch owner {
|
|
102
115
|
case .customer(let customerId):
|
|
103
|
-
request = ChargeIntentsRequests.CreateChargeIntentRequest(
|
|
104
|
-
amount: amount,
|
|
105
|
-
|
|
116
|
+
let request = ChargeIntentsRequests.CreateChargeIntentRequest(
|
|
117
|
+
amount: amount,
|
|
118
|
+
currency: currency,
|
|
119
|
+
customer: customerId,
|
|
120
|
+
paymentMethod: paymentMethodId,
|
|
121
|
+
confirm: true,
|
|
122
|
+
authorizationMode: .automatic
|
|
106
123
|
)
|
|
124
|
+
let (chargeIntent, chargeError) = try await ChargeIntentsAPI.createChargeIntent(request: request)
|
|
125
|
+
|
|
126
|
+
if let chargeIntent {
|
|
127
|
+
deliverSuccess(id: chargeIntent.id)
|
|
128
|
+
return PKPaymentAuthorizationResult(status: .success, errors: nil)
|
|
129
|
+
} else {
|
|
130
|
+
deliverFailure(code: "PAYMENT_FAILED", error: chargeError)
|
|
131
|
+
return PKPaymentAuthorizationResult(status: .failure, errors: nil)
|
|
132
|
+
}
|
|
133
|
+
|
|
107
134
|
case .account(let accountId):
|
|
108
|
-
request =
|
|
109
|
-
amount: amount,
|
|
110
|
-
|
|
135
|
+
let request = TransferRequests.CreateTransferRequest(
|
|
136
|
+
amount: amount,
|
|
137
|
+
accountId: accountId,
|
|
138
|
+
currency: currency,
|
|
139
|
+
sourcePaymentMethodId: paymentMethodId
|
|
111
140
|
)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
141
|
+
let (transfer, transferError) = try await TransfersAPI.createTransfer(request: request)
|
|
142
|
+
|
|
143
|
+
if let transfer {
|
|
144
|
+
deliverSuccess(id: transfer.id)
|
|
145
|
+
return PKPaymentAuthorizationResult(status: .success, errors: nil)
|
|
146
|
+
} else {
|
|
147
|
+
deliverFailure(code: "PAYMENT_FAILED", error: transferError)
|
|
148
|
+
return PKPaymentAuthorizationResult(status: .failure, errors: nil)
|
|
149
|
+
}
|
|
121
150
|
}
|
|
122
151
|
} catch {
|
|
123
152
|
deliverFailure(code: "PAYMENT_FAILED", error: error)
|
|
@@ -136,14 +165,10 @@ final class ApplePayPresenter: NSObject, PKPaymentAuthorizationControllerDelegat
|
|
|
136
165
|
|
|
137
166
|
// MARK: - Result delivery
|
|
138
167
|
|
|
139
|
-
private func deliverSuccess(
|
|
168
|
+
private func deliverSuccess(id: String) {
|
|
140
169
|
guard !didDeliverResult else { return }
|
|
141
170
|
didDeliverResult = true
|
|
142
|
-
|
|
143
|
-
resolve(dict)
|
|
144
|
-
} else {
|
|
145
|
-
reject("ENCODE_ERROR", "Failed to encode charge intent", nil)
|
|
146
|
-
}
|
|
171
|
+
resolve(id)
|
|
147
172
|
}
|
|
148
173
|
|
|
149
174
|
private func deliverFailure(code: String, error: Error?) {
|
package/ios/FrameRNTheme.swift
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
// FrameRNTheme.swift
|
|
3
3
|
// FrameReactNative
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
5
|
+
// Parses JS theme dictionaries into Frame-iOS's FrameTheme. The parsed
|
|
6
|
+
// theme is handed to FrameNetworking.shared.configureTheme(_:); the SDK
|
|
7
|
+
// owns storage and applies it via its FrameThemeKey environment default.
|
|
7
8
|
//
|
|
8
9
|
|
|
9
10
|
import Foundation
|
|
@@ -11,12 +12,6 @@ import SwiftUI
|
|
|
11
12
|
import Frame
|
|
12
13
|
|
|
13
14
|
enum FrameRNTheme {
|
|
14
|
-
// Main-thread only: written by FrameSDKBridge.setTheme (dispatched to main),
|
|
15
|
-
// read by present* methods (already on main).
|
|
16
|
-
static var current: FrameTheme? = nil
|
|
17
|
-
|
|
18
|
-
static func resolved() -> FrameTheme { current ?? .default }
|
|
19
|
-
|
|
20
15
|
static func parse(_ dict: [String: Any]) -> FrameTheme {
|
|
21
16
|
var theme = FrameTheme.default
|
|
22
17
|
|
|
@@ -75,22 +70,6 @@ enum FrameRNTheme {
|
|
|
75
70
|
}
|
|
76
71
|
}
|
|
77
72
|
|
|
78
|
-
// Applies the supplied FrameTheme to a single root view. Captured at present
|
|
79
|
-
// time so each UIHostingController has a stable, concrete rootView type.
|
|
80
|
-
struct ThemedRoot<Content: View>: View {
|
|
81
|
-
let theme: FrameTheme
|
|
82
|
-
let content: Content
|
|
83
|
-
|
|
84
|
-
init(_ content: Content, theme: FrameTheme) {
|
|
85
|
-
self.content = content
|
|
86
|
-
self.theme = theme
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
var body: some View {
|
|
90
|
-
content.frameTheme(theme)
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
73
|
extension Color {
|
|
95
74
|
// Accepts "#RGB", "#RRGGBB", "#RRGGBBAA" with or without the leading '#'.
|
|
96
75
|
init?(rnHex hex: String) {
|
package/ios/FrameSDKBridge.m
CHANGED
|
@@ -28,19 +28,16 @@
|
|
|
28
28
|
RCT_EXTERN_METHOD(initialize:(NSString *)secretKey
|
|
29
29
|
publishableKey:(NSString *)publishableKey
|
|
30
30
|
debugMode:(BOOL)debugMode
|
|
31
|
+
theme:(NSDictionary *)theme
|
|
31
32
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
32
33
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
33
34
|
|
|
34
|
-
RCT_EXTERN_METHOD(
|
|
35
|
-
resolver:(RCTPromiseResolveBlock)resolve
|
|
36
|
-
rejecter:(RCTPromiseRejectBlock)reject)
|
|
37
|
-
|
|
38
|
-
RCT_EXTERN_METHOD(presentCheckout:(id)customerId
|
|
35
|
+
RCT_EXTERN_METHOD(presentCheckout:(id)accountId
|
|
39
36
|
amount:(nonnull NSNumber *)amount
|
|
40
37
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
41
38
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
42
39
|
|
|
43
|
-
RCT_EXTERN_METHOD(presentCart:(id)
|
|
40
|
+
RCT_EXTERN_METHOD(presentCart:(id)accountId
|
|
44
41
|
items:(NSArray *)items
|
|
45
42
|
shippingAmountInCents:(nonnull NSNumber *)shippingAmountInCents
|
|
46
43
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
@@ -71,34 +68,30 @@ RCT_EXTERN_METHOD(presentApplePay:(NSString *)ownerType
|
|
|
71
68
|
return YES;
|
|
72
69
|
}
|
|
73
70
|
|
|
74
|
-
- (void)initialize:(NSString *)secretKey publishableKey:(NSString *)publishableKey debugMode:(BOOL)debugMode resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
|
|
75
|
-
[[[ObjCFrameSDKBridge alloc] init] initialize:secretKey publishableKey:publishableKey debugMode:debugMode resolver:resolve rejecter:reject];
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
- (void)setTheme:(NSDictionary *)theme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
|
|
79
|
-
[[[ObjCFrameSDKBridge alloc] init] setTheme:theme resolver:resolve rejecter:reject];
|
|
71
|
+
- (void)initialize:(NSString *)secretKey publishableKey:(NSString *)publishableKey debugMode:(BOOL)debugMode theme:(NSDictionary *)theme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
|
|
72
|
+
[[[ObjCFrameSDKBridge alloc] init] initialize:secretKey publishableKey:publishableKey debugMode:debugMode theme:theme resolver:resolve rejecter:reject];
|
|
80
73
|
}
|
|
81
74
|
|
|
82
|
-
- (void)presentCheckout:(id)
|
|
75
|
+
- (void)presentCheckout:(id)accountId amount:(NSNumber *)amount resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
|
|
83
76
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
84
77
|
UIViewController *topVC = FrameGetTopViewController();
|
|
85
78
|
if (!topVC) {
|
|
86
79
|
reject(@"NO_ROOT_VC", @"Could not find root view controller to present checkout", nil);
|
|
87
80
|
return;
|
|
88
81
|
}
|
|
89
|
-
NSString *
|
|
90
|
-
[[[ObjCFrameSDKBridge alloc] init] presentCheckoutFrom:topVC
|
|
82
|
+
NSString *aId = [accountId isKindOfClass:[NSString class]] ? (NSString *)accountId : nil;
|
|
83
|
+
[[[ObjCFrameSDKBridge alloc] init] presentCheckoutFrom:topVC accountId:aId amount:amount.intValue resolver:resolve rejecter:reject];
|
|
91
84
|
});
|
|
92
85
|
}
|
|
93
86
|
|
|
94
|
-
- (void)presentCart:(id)
|
|
87
|
+
- (void)presentCart:(id)accountId items:(NSArray *)items shippingAmountInCents:(NSNumber *)shippingAmountInCents resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
|
|
95
88
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
96
89
|
UIViewController *topVC = FrameGetTopViewController();
|
|
97
90
|
if (!topVC) {
|
|
98
91
|
reject(@"NO_ROOT_VC", @"Could not find root view controller to present cart", nil);
|
|
99
92
|
return;
|
|
100
93
|
}
|
|
101
|
-
[[[ObjCFrameSDKBridge alloc] init] presentCartFrom:topVC
|
|
94
|
+
[[[ObjCFrameSDKBridge alloc] init] presentCartFrom:topVC accountId:accountId items:items shippingAmountInCents:shippingAmountInCents.integerValue resolver:resolve rejecter:reject];
|
|
102
95
|
});
|
|
103
96
|
}
|
|
104
97
|
|