@juspay-tech/react-native-hyperswitch-paypal 1.0.0
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/LICENSE +20 -0
- package/README.md +33 -0
- package/ReactNativeHyperswitchPaypal.podspec +27 -0
- package/android/build.gradle +69 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +17 -0
- package/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/PayPalPendingResult.kt +31 -0
- package/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/PayPalRedirectActivity.kt +165 -0
- package/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/PaypalButtonView.kt +56 -0
- package/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/PaypalButtonViewManager.kt +56 -0
- package/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/ReactNativeHyperswitchPaypalModule.kt +101 -0
- package/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/ReactNativeHyperswitchPaypalPackage.kt +17 -0
- package/ios/PaypalButtonView.swift +118 -0
- package/ios/PaypalButtonViewManager.swift +13 -0
- package/ios/ReactNativeHyperswitchPaypal-Bridging-Header.h +2 -0
- package/ios/ReactNativeHyperswitchPaypal.mm +17 -0
- package/ios/ReactNativeHyperswitchPaypal.swift +92 -0
- package/lib/module/PaypalButtonNativeComponent.android.js +5 -0
- package/lib/module/PaypalButtonNativeComponent.android.js.map +1 -0
- package/lib/module/index.js +18 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/PaypalButtonNativeComponent.android.d.ts +9 -0
- package/lib/typescript/src/PaypalButtonNativeComponent.android.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +16 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/package.json +154 -0
- package/react-native.config.js +11 -0
- package/src/PaypalButtonNativeComponent.android.ts +9 -0
- package/src/index.tsx +32 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hyperswitch
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# @juspay-tech/react-native-hyperswitch-paypal
|
|
2
|
+
|
|
3
|
+
react native hyperswitch paypal
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install @juspay-tech/react-native-hyperswitch-paypal
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
import { multiply } from '@juspay-tech/react-native-hyperswitch-paypal';
|
|
16
|
+
|
|
17
|
+
// ...
|
|
18
|
+
|
|
19
|
+
const result = await multiply(3, 7);
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
## Contributing
|
|
24
|
+
|
|
25
|
+
See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
|
|
26
|
+
|
|
27
|
+
## License
|
|
28
|
+
|
|
29
|
+
MIT
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = "ReactNativeHyperswitchPaypal"
|
|
7
|
+
s.version = package["version"]
|
|
8
|
+
s.summary = package["description"]
|
|
9
|
+
s.homepage = package["homepage"]
|
|
10
|
+
s.license = package["license"]
|
|
11
|
+
s.authors = package["author"]
|
|
12
|
+
|
|
13
|
+
s.platforms = { :ios => min_ios_version_supported }
|
|
14
|
+
s.source = { :git => "https://github.com/juspay/react-native-hyperswitch.git", :tag => "#{s.version}" }
|
|
15
|
+
|
|
16
|
+
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
17
|
+
|
|
18
|
+
# Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
|
|
19
|
+
# See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
|
|
20
|
+
if respond_to?(:install_modules_dependencies, true)
|
|
21
|
+
install_modules_dependencies(s)
|
|
22
|
+
else
|
|
23
|
+
s.dependency "React-Core"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
s.dependency "PayPal", "~> 2.0"
|
|
27
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
ext.getExtOrDefault = {name ->
|
|
3
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['ReactNativeHyperswitchPaypal_' + name]
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
repositories {
|
|
7
|
+
google()
|
|
8
|
+
mavenCentral()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
dependencies {
|
|
12
|
+
classpath "com.android.tools.build:gradle:8.7.2"
|
|
13
|
+
// noinspection DifferentKotlinGradleVersion
|
|
14
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
apply plugin: "com.android.library"
|
|
20
|
+
apply plugin: "kotlin-android"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def getExtOrIntegerDefault(name) {
|
|
24
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["ReactNativeHyperswitchPaypal_" + name]).toInteger()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
android {
|
|
28
|
+
namespace "com.juspaytech.reactnativehyperswitchpaypal"
|
|
29
|
+
|
|
30
|
+
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
31
|
+
|
|
32
|
+
defaultConfig {
|
|
33
|
+
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
34
|
+
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
buildTypes {
|
|
38
|
+
release {
|
|
39
|
+
minifyEnabled false
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
lintOptions {
|
|
44
|
+
disable "GradleCompatible"
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
compileOptions {
|
|
48
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
49
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
kotlinOptions {
|
|
53
|
+
jvmTarget = '17'
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
repositories {
|
|
58
|
+
mavenCentral()
|
|
59
|
+
google()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
def kotlin_version = getExtOrDefault("kotlinVersion")
|
|
63
|
+
|
|
64
|
+
dependencies {
|
|
65
|
+
implementation "com.facebook.react:react-android"
|
|
66
|
+
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
67
|
+
implementation "com.paypal.android:paypal-web-payments:2.3.0"
|
|
68
|
+
implementation "com.paypal.android:payment-buttons:2.3.0"
|
|
69
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
2
|
+
|
|
3
|
+
<application>
|
|
4
|
+
<activity
|
|
5
|
+
android:name=".PayPalRedirectActivity"
|
|
6
|
+
android:exported="true"
|
|
7
|
+
android:launchMode="singleTop"
|
|
8
|
+
android:theme="@android:style/Theme.Translucent.NoTitleBar">
|
|
9
|
+
<intent-filter>
|
|
10
|
+
<action android:name="android.intent.action.VIEW" />
|
|
11
|
+
<category android:name="android.intent.category.DEFAULT" />
|
|
12
|
+
<category android:name="android.intent.category.BROWSABLE" />
|
|
13
|
+
<data android:scheme="${applicationId}.paypal" />
|
|
14
|
+
</intent-filter>
|
|
15
|
+
</activity>
|
|
16
|
+
</application>
|
|
17
|
+
</manifest>
|
package/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/PayPalPendingResult.kt
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
package com.juspaytech.reactnativehyperswitchpaypal
|
|
2
|
+
|
|
3
|
+
object PayPalPendingResult {
|
|
4
|
+
@Volatile
|
|
5
|
+
private var resultCallback: PayPalResultCallback? = null
|
|
6
|
+
|
|
7
|
+
interface PayPalResultCallback {
|
|
8
|
+
fun onSuccess(orderId: String, payerId: String)
|
|
9
|
+
fun onCancelled()
|
|
10
|
+
fun onFailure(errorMessage: String, errorCode: String?)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
fun setCallback(callback: PayPalResultCallback?) {
|
|
14
|
+
this.resultCallback = callback
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
fun notifySuccess(orderId: String, payerId: String) {
|
|
18
|
+
resultCallback?.onSuccess(orderId, payerId)
|
|
19
|
+
resultCallback = null
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
fun notifyCancelled() {
|
|
23
|
+
resultCallback?.onCancelled()
|
|
24
|
+
resultCallback = null
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
fun notifyFailure(errorMessage: String, errorCode: String?) {
|
|
28
|
+
resultCallback?.onFailure(errorMessage, errorCode)
|
|
29
|
+
resultCallback = null
|
|
30
|
+
}
|
|
31
|
+
}
|
package/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/PayPalRedirectActivity.kt
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
package com.juspaytech.reactnativehyperswitchpaypal
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.content.Intent
|
|
5
|
+
import android.graphics.Color
|
|
6
|
+
import android.os.Bundle
|
|
7
|
+
import android.os.Handler
|
|
8
|
+
import android.os.Looper
|
|
9
|
+
import android.util.Log
|
|
10
|
+
import android.view.WindowManager
|
|
11
|
+
import com.paypal.android.corepayments.CoreConfig
|
|
12
|
+
import com.paypal.android.corepayments.Environment
|
|
13
|
+
import com.paypal.android.paypalwebpayments.PayPalPresentAuthChallengeResult
|
|
14
|
+
import com.paypal.android.paypalwebpayments.PayPalWebCheckoutClient
|
|
15
|
+
import com.paypal.android.paypalwebpayments.PayPalWebCheckoutFinishStartResult
|
|
16
|
+
import com.paypal.android.paypalwebpayments.PayPalWebCheckoutFundingSource
|
|
17
|
+
import com.paypal.android.paypalwebpayments.PayPalWebCheckoutRequest
|
|
18
|
+
|
|
19
|
+
class PayPalRedirectActivity : Activity() {
|
|
20
|
+
|
|
21
|
+
private var payPalClient: PayPalWebCheckoutClient? = null
|
|
22
|
+
private var callbackInvoked = false
|
|
23
|
+
private var browserLaunched = false
|
|
24
|
+
|
|
25
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
26
|
+
// Skip enter animation
|
|
27
|
+
overridePendingTransition(0, 0)
|
|
28
|
+
|
|
29
|
+
// Make window completely invisible
|
|
30
|
+
window.setFlags(
|
|
31
|
+
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
|
|
32
|
+
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
|
|
33
|
+
)
|
|
34
|
+
window.statusBarColor = Color.TRANSPARENT
|
|
35
|
+
window.navigationBarColor = Color.TRANSPARENT
|
|
36
|
+
|
|
37
|
+
super.onCreate(savedInstanceState)
|
|
38
|
+
|
|
39
|
+
val params = intent?.extras ?: run {
|
|
40
|
+
Log.e(TAG, "No parameters provided")
|
|
41
|
+
finish()
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
val clientId = params.getString("clientId") ?: run {
|
|
46
|
+
notifyFailure("Missing clientId", null)
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
val orderId = params.getString("orderId") ?: run {
|
|
50
|
+
notifyFailure("Missing orderId", null)
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
val environmentStr = params.getString("environment", "SANDBOX")
|
|
54
|
+
val returnUrl = params.getString("returnUrl", "${packageName}.paypal")
|
|
55
|
+
val fundingSourceStr = params.getString("fundingSource", "PAYPAL")
|
|
56
|
+
|
|
57
|
+
val environment = if (environmentStr == "PRODUCTION") Environment.LIVE else Environment.SANDBOX
|
|
58
|
+
val fundingSource = when (fundingSourceStr) {
|
|
59
|
+
"PAY_LATER" -> PayPalWebCheckoutFundingSource.PAY_LATER
|
|
60
|
+
"PAYPAL_CREDIT" -> PayPalWebCheckoutFundingSource.PAYPAL_CREDIT
|
|
61
|
+
else -> PayPalWebCheckoutFundingSource.PAYPAL
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
val config = CoreConfig(clientId, environment = environment)
|
|
65
|
+
payPalClient = PayPalWebCheckoutClient(this, config, returnUrl)
|
|
66
|
+
|
|
67
|
+
val request = PayPalWebCheckoutRequest(orderId, fundingSource = fundingSource)
|
|
68
|
+
|
|
69
|
+
payPalClient?.start(this, request) { startResult ->
|
|
70
|
+
when (startResult) {
|
|
71
|
+
is PayPalPresentAuthChallengeResult.Success -> {
|
|
72
|
+
browserLaunched = true
|
|
73
|
+
}
|
|
74
|
+
is PayPalPresentAuthChallengeResult.Failure -> {
|
|
75
|
+
Log.e(TAG, "PayPal start failed: ${startResult.error.errorDescription}")
|
|
76
|
+
notifyFailure(
|
|
77
|
+
startResult.error.errorDescription ?: "Failed to start PayPal",
|
|
78
|
+
startResult.error.code?.toString()
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
override fun finish() {
|
|
86
|
+
super.finish()
|
|
87
|
+
// Skip exit animation
|
|
88
|
+
overridePendingTransition(0, 0)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
override fun onNewIntent(intent: Intent?) {
|
|
92
|
+
super.onNewIntent(intent)
|
|
93
|
+
|
|
94
|
+
if (callbackInvoked) return
|
|
95
|
+
|
|
96
|
+
intent?.let {
|
|
97
|
+
val result = payPalClient?.finishStart(it)
|
|
98
|
+
handleFinishResult(result)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
override fun onResume() {
|
|
103
|
+
super.onResume()
|
|
104
|
+
|
|
105
|
+
// If browser was launched but no deep link received (callbackInvoked is false),
|
|
106
|
+
// user cancelled by closing the browser
|
|
107
|
+
if (browserLaunched && !callbackInvoked) {
|
|
108
|
+
// Small delay to ensure onNewIntent didn't just fire
|
|
109
|
+
Handler(Looper.getMainLooper()).postDelayed({
|
|
110
|
+
if (!callbackInvoked) {
|
|
111
|
+
notifyCancelled()
|
|
112
|
+
}
|
|
113
|
+
}, 300)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private fun handleFinishResult(result: PayPalWebCheckoutFinishStartResult?) {
|
|
118
|
+
when (result) {
|
|
119
|
+
is PayPalWebCheckoutFinishStartResult.Success -> {
|
|
120
|
+
notifySuccess(result.orderId ?: "", result.payerId ?: "")
|
|
121
|
+
}
|
|
122
|
+
is PayPalWebCheckoutFinishStartResult.Failure -> {
|
|
123
|
+
Log.e(TAG, "PayPal failure - error: ${result.error.errorDescription}")
|
|
124
|
+
notifyFailure(
|
|
125
|
+
result.error.errorDescription ?: result.error.message ?: "Unknown PayPal error",
|
|
126
|
+
result.error.code?.toString()
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
is PayPalWebCheckoutFinishStartResult.Canceled -> {
|
|
130
|
+
notifyCancelled()
|
|
131
|
+
}
|
|
132
|
+
PayPalWebCheckoutFinishStartResult.NoResult -> {
|
|
133
|
+
Log.d(TAG, "NoResult from finishStart")
|
|
134
|
+
}
|
|
135
|
+
null -> {
|
|
136
|
+
Log.d(TAG, "finishStart returned null")
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
private fun notifySuccess(orderId: String, payerId: String) {
|
|
142
|
+
if (callbackInvoked) return
|
|
143
|
+
callbackInvoked = true
|
|
144
|
+
PayPalPendingResult.notifySuccess(orderId, payerId)
|
|
145
|
+
finish()
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private fun notifyCancelled() {
|
|
149
|
+
if (callbackInvoked) return
|
|
150
|
+
callbackInvoked = true
|
|
151
|
+
PayPalPendingResult.notifyCancelled()
|
|
152
|
+
finish()
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private fun notifyFailure(errorMessage: String, errorCode: String?) {
|
|
156
|
+
if (callbackInvoked) return
|
|
157
|
+
callbackInvoked = true
|
|
158
|
+
PayPalPendingResult.notifyFailure(errorMessage, errorCode)
|
|
159
|
+
finish()
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
companion object {
|
|
163
|
+
private const val TAG = "PayPalRedirect"
|
|
164
|
+
}
|
|
165
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
package com.juspaytech.reactnativehyperswitchpaypal
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint
|
|
4
|
+
import android.util.Log
|
|
5
|
+
import android.view.View
|
|
6
|
+
import android.widget.FrameLayout
|
|
7
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
8
|
+
import com.paypal.android.paymentbuttons.PayPalButton
|
|
9
|
+
import com.paypal.android.paymentbuttons.PayPalButtonColor
|
|
10
|
+
import com.paypal.android.paymentbuttons.PayPalButtonLabel
|
|
11
|
+
|
|
12
|
+
@SuppressLint("ViewConstructor")
|
|
13
|
+
class PaypalButtonView(private val context: ThemedReactContext) : FrameLayout(context) {
|
|
14
|
+
|
|
15
|
+
var buttonColor: PayPalButtonColor = PayPalButtonColor.GOLD
|
|
16
|
+
var buttonLabel: PayPalButtonLabel = PayPalButtonLabel.PAYPAL
|
|
17
|
+
var customCornerRadius: Float = 10.0F
|
|
18
|
+
private var button: PayPalButton? = null
|
|
19
|
+
|
|
20
|
+
fun addButton() {
|
|
21
|
+
if (button != null) {
|
|
22
|
+
removeView(button)
|
|
23
|
+
}
|
|
24
|
+
button = initializePayPalButton()
|
|
25
|
+
addView(button)
|
|
26
|
+
viewTreeObserver.addOnGlobalLayoutListener { requestLayout() }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private fun initializePayPalButton(): PayPalButton {
|
|
30
|
+
val payPalButton = PayPalButton(context)
|
|
31
|
+
|
|
32
|
+
payPalButton.color = buttonColor
|
|
33
|
+
payPalButton.label = buttonLabel
|
|
34
|
+
payPalButton.customCornerRadius = customCornerRadius
|
|
35
|
+
payPalButton.setOnClickListener {
|
|
36
|
+
(this.parent as? View)?.performClick() ?: run {
|
|
37
|
+
Log.e("PaypalButtonView", "Unable to find parent of PaypalButtonView.")
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return payPalButton
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
override fun requestLayout() {
|
|
45
|
+
super.requestLayout()
|
|
46
|
+
post(mLayoutRunnable)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private val mLayoutRunnable = Runnable {
|
|
50
|
+
measure(
|
|
51
|
+
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
|
|
52
|
+
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
|
|
53
|
+
)
|
|
54
|
+
layout(left, top, right, bottom)
|
|
55
|
+
}
|
|
56
|
+
}
|
package/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/PaypalButtonViewManager.kt
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
package com.juspaytech.reactnativehyperswitchpaypal
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
4
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
5
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
6
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
7
|
+
import com.paypal.android.paymentbuttons.PayPalButtonColor
|
|
8
|
+
import com.paypal.android.paymentbuttons.PayPalButtonLabel
|
|
9
|
+
|
|
10
|
+
@ReactModule(name = PaypalButtonViewManager.NAME)
|
|
11
|
+
class PaypalButtonViewManager : SimpleViewManager<PaypalButtonView>() {
|
|
12
|
+
|
|
13
|
+
override fun getName(): String {
|
|
14
|
+
return NAME
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
public override fun createViewInstance(context: ThemedReactContext): PaypalButtonView {
|
|
18
|
+
return PaypalButtonView(context)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public override fun onAfterUpdateTransaction(view: PaypalButtonView) {
|
|
22
|
+
super.onAfterUpdateTransaction(view)
|
|
23
|
+
view.addButton()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@ReactProp(name = "buttonColor")
|
|
27
|
+
fun setButtonColor(view: PaypalButtonView, value: String?) {
|
|
28
|
+
view.buttonColor = when (value) {
|
|
29
|
+
"GOLD" -> PayPalButtonColor.GOLD
|
|
30
|
+
"BLUE" -> PayPalButtonColor.BLUE
|
|
31
|
+
"SILVER" -> PayPalButtonColor.SILVER
|
|
32
|
+
"WHITE" -> PayPalButtonColor.WHITE
|
|
33
|
+
"BLACK" -> PayPalButtonColor.BLACK
|
|
34
|
+
else -> PayPalButtonColor.GOLD
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@ReactProp(name = "buttonLabel")
|
|
39
|
+
fun setButtonLabel(view: PaypalButtonView, value: String?) {
|
|
40
|
+
view.buttonLabel = when (value) {
|
|
41
|
+
"CHECKOUT" -> PayPalButtonLabel.CHECKOUT
|
|
42
|
+
"BUY_NOW" -> PayPalButtonLabel.BUY_NOW
|
|
43
|
+
"PAY" -> PayPalButtonLabel.PAY
|
|
44
|
+
else -> PayPalButtonLabel.PAYPAL
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@ReactProp(name = "borderRadius", defaultDouble = 0.0)
|
|
49
|
+
fun setBorderRadius(view: PaypalButtonView, value: Double) {
|
|
50
|
+
view.customCornerRadius = value.toFloat()
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
companion object {
|
|
54
|
+
const val NAME = "PaypalButton"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
package com.juspaytech.reactnativehyperswitchpaypal
|
|
2
|
+
|
|
3
|
+
import android.content.Intent
|
|
4
|
+
import android.os.Handler
|
|
5
|
+
import android.os.Looper
|
|
6
|
+
import android.util.Log
|
|
7
|
+
import com.facebook.react.bridge.Callback
|
|
8
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
9
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
10
|
+
import com.facebook.react.bridge.ReactMethod
|
|
11
|
+
import com.facebook.react.bridge.WritableNativeMap
|
|
12
|
+
import org.json.JSONObject
|
|
13
|
+
|
|
14
|
+
class ReactNativeHyperswitchPaypalModule(reactContext: ReactApplicationContext) :
|
|
15
|
+
ReactContextBaseJavaModule(reactContext),
|
|
16
|
+
PayPalPendingResult.PayPalResultCallback {
|
|
17
|
+
|
|
18
|
+
private var currentCallback: Callback? = null
|
|
19
|
+
private val mainHandler = Handler(Looper.getMainLooper())
|
|
20
|
+
|
|
21
|
+
override fun getName(): String = NAME
|
|
22
|
+
|
|
23
|
+
@ReactMethod
|
|
24
|
+
fun launchPayPal(requestObj: String, callback: Callback) {
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
val json = JSONObject(requestObj)
|
|
28
|
+
val clientId = json.getString("clientId")
|
|
29
|
+
val environment = json.optString("environment", "SANDBOX")
|
|
30
|
+
val orderId = json.getString("orderId")
|
|
31
|
+
val returnUrl = json.optString("returnUrl", "").ifEmpty {
|
|
32
|
+
"${reactApplicationContext.packageName}.paypal"
|
|
33
|
+
}
|
|
34
|
+
val fundingSource = json.optString("fundingSource", "PAYPAL")
|
|
35
|
+
|
|
36
|
+
currentCallback = callback
|
|
37
|
+
|
|
38
|
+
// Register for result callback
|
|
39
|
+
PayPalPendingResult.setCallback(this)
|
|
40
|
+
|
|
41
|
+
// Launch PayPalRedirectActivity with parameters
|
|
42
|
+
val intent = Intent(reactApplicationContext, PayPalRedirectActivity::class.java).apply {
|
|
43
|
+
putExtra("clientId", clientId)
|
|
44
|
+
putExtra("environment", environment)
|
|
45
|
+
putExtra("orderId", orderId)
|
|
46
|
+
putExtra("returnUrl", returnUrl)
|
|
47
|
+
putExtra("fundingSource", fundingSource)
|
|
48
|
+
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
49
|
+
}
|
|
50
|
+
reactApplicationContext.startActivity(intent)
|
|
51
|
+
|
|
52
|
+
} catch (e: Exception) {
|
|
53
|
+
Log.e(TAG, "Exception in launchPayPal: ${e.message}", e)
|
|
54
|
+
invokeCallbackWithError(e.message ?: "Failed to launch PayPal checkout")
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Called from PayPalRedirectActivity on success
|
|
59
|
+
override fun onSuccess(orderId: String, payerId: String) {
|
|
60
|
+
mainHandler.post {
|
|
61
|
+
val map = WritableNativeMap()
|
|
62
|
+
map.putString("status", "success")
|
|
63
|
+
map.putString("orderId", orderId)
|
|
64
|
+
map.putString("payerId", payerId)
|
|
65
|
+
currentCallback?.invoke(map)
|
|
66
|
+
currentCallback = null
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Called from PayPalRedirectActivity on cancel
|
|
71
|
+
override fun onCancelled() {
|
|
72
|
+
mainHandler.post {
|
|
73
|
+
val map = WritableNativeMap()
|
|
74
|
+
map.putString("status", "cancelled")
|
|
75
|
+
currentCallback?.invoke(map)
|
|
76
|
+
currentCallback = null
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Called from PayPalRedirectActivity on failure
|
|
81
|
+
override fun onFailure(errorMessage: String, errorCode: String?) {
|
|
82
|
+
mainHandler.post {
|
|
83
|
+
Log.e(TAG, "PayPal failure: $errorMessage")
|
|
84
|
+
invokeCallbackWithError(errorMessage)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private fun invokeCallbackWithError(errorMessage: String) {
|
|
89
|
+
Log.e(TAG, "PayPal error: $errorMessage")
|
|
90
|
+
val map = WritableNativeMap()
|
|
91
|
+
map.putString("status", "failed")
|
|
92
|
+
map.putString("error_message", errorMessage)
|
|
93
|
+
currentCallback?.invoke(map)
|
|
94
|
+
currentCallback = null
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
companion object {
|
|
98
|
+
const val NAME = "HyperswitchPaypal"
|
|
99
|
+
private const val TAG = "HyperswitchPaypal"
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
package com.juspaytech.reactnativehyperswitchpaypal
|
|
2
|
+
|
|
3
|
+
import android.util.Log
|
|
4
|
+
import com.facebook.react.ReactPackage
|
|
5
|
+
import com.facebook.react.bridge.NativeModule
|
|
6
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
7
|
+
import com.facebook.react.uimanager.ViewManager
|
|
8
|
+
|
|
9
|
+
class ReactNativeHyperswitchPaypalPackage : ReactPackage {
|
|
10
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
|
11
|
+
return listOf(ReactNativeHyperswitchPaypalModule(reactContext))
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
15
|
+
return listOf(PaypalButtonViewManager())
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import UIKit
|
|
2
|
+
import PayPal
|
|
3
|
+
|
|
4
|
+
class PaypalButtonView: UIView {
|
|
5
|
+
|
|
6
|
+
private var payPalButton: PayPalButton?
|
|
7
|
+
private var containerView: UIView?
|
|
8
|
+
|
|
9
|
+
@objc dynamic var buttonColor: String = "gold" {
|
|
10
|
+
didSet { updateButton() }
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@objc dynamic var buttonLabel: String = "paypal" {
|
|
14
|
+
didSet { updateButton() }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@objc dynamic var borderRadius: Double = 0 {
|
|
18
|
+
didSet { updateButton() }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
override init(frame: CGRect) {
|
|
22
|
+
super.init(frame: frame)
|
|
23
|
+
setupButton()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
required init?(coder: NSCoder) {
|
|
27
|
+
super.init(coder: coder)
|
|
28
|
+
setupButton()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private func setupButton() {
|
|
32
|
+
if let existingButton = payPalButton {
|
|
33
|
+
existingButton.removeFromSuperview()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let color = mapColor(buttonColor)
|
|
37
|
+
let label = mapLabel(buttonLabel)
|
|
38
|
+
let edges = mapEdges(borderRadius)
|
|
39
|
+
|
|
40
|
+
let button = PayPalButton(
|
|
41
|
+
color: color,
|
|
42
|
+
edges: edges,
|
|
43
|
+
size: .collapsed,
|
|
44
|
+
label: label
|
|
45
|
+
)
|
|
46
|
+
button.translatesAutoresizingMaskIntoConstraints = false
|
|
47
|
+
button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
|
|
48
|
+
|
|
49
|
+
payPalButton = button
|
|
50
|
+
|
|
51
|
+
let container = UIView()
|
|
52
|
+
container.translatesAutoresizingMaskIntoConstraints = false
|
|
53
|
+
container.addSubview(button)
|
|
54
|
+
|
|
55
|
+
NSLayoutConstraint.activate([
|
|
56
|
+
button.topAnchor.constraint(equalTo: container.topAnchor),
|
|
57
|
+
button.bottomAnchor.constraint(equalTo: container.bottomAnchor),
|
|
58
|
+
button.leadingAnchor.constraint(equalTo: container.leadingAnchor),
|
|
59
|
+
button.trailingAnchor.constraint(equalTo: container.trailingAnchor),
|
|
60
|
+
])
|
|
61
|
+
|
|
62
|
+
addSubview(container)
|
|
63
|
+
containerView = container
|
|
64
|
+
|
|
65
|
+
NSLayoutConstraint.activate([
|
|
66
|
+
container.topAnchor.constraint(equalTo: topAnchor),
|
|
67
|
+
container.bottomAnchor.constraint(equalTo: bottomAnchor),
|
|
68
|
+
container.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
69
|
+
container.trailingAnchor.constraint(equalTo: trailingAnchor),
|
|
70
|
+
])
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private func updateButton() {
|
|
74
|
+
setupButton()
|
|
75
|
+
setNeedsLayout()
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private func mapColor(_ value: String) -> PayPalButton.Color {
|
|
79
|
+
switch value.lowercased() {
|
|
80
|
+
case "blue": return .blue
|
|
81
|
+
case "silver": return .silver
|
|
82
|
+
case "white": return .white
|
|
83
|
+
case "black": return .black
|
|
84
|
+
default: return .gold
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private func mapLabel(_ value: String) -> PayPalButton.Label? {
|
|
89
|
+
switch value.lowercased() {
|
|
90
|
+
case "checkout": return .checkout
|
|
91
|
+
case "buynow": return .buyNow
|
|
92
|
+
case "pay": return .payWith
|
|
93
|
+
default: return nil
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
private func mapEdges(_ radius: Double) -> PaymentButtonEdges {
|
|
98
|
+
if radius <= 0 {
|
|
99
|
+
return .hardEdges
|
|
100
|
+
} else {
|
|
101
|
+
return .custom(CGFloat(radius))
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@objc private func buttonTapped() {
|
|
106
|
+
guard let reactView = superview else { return }
|
|
107
|
+
reactView.reactSubviews().first?.perform(#selector(UIView.didMoveToWindow))
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
override var intrinsicContentSize: CGSize {
|
|
111
|
+
return CGSize(width: UIView.noIntrinsicMetric, height: 48)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
override func layoutSubviews() {
|
|
115
|
+
super.layoutSubviews()
|
|
116
|
+
payPalButton?.layoutSubviews()
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import PayPal
|
|
2
|
+
|
|
3
|
+
@objc(PaypalButton)
|
|
4
|
+
class PaypalButtonViewManager: RCTViewManager {
|
|
5
|
+
|
|
6
|
+
override func view() -> PaypalButtonView {
|
|
7
|
+
return PaypalButtonView()
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@objc override static func requiresMainQueueSetup() -> Bool {
|
|
11
|
+
return true
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
#import <React/RCTViewManager.h>
|
|
3
|
+
|
|
4
|
+
@interface RCT_EXTERN_MODULE(HyperswitchPaypal, NSObject)
|
|
5
|
+
|
|
6
|
+
RCT_EXTERN_METHOD(launchPayPal:(NSString *)requestObj
|
|
7
|
+
callback:(RCTResponseSenderBlock)callback)
|
|
8
|
+
|
|
9
|
+
@end
|
|
10
|
+
|
|
11
|
+
@interface RCT_EXTERN_MODULE(PaypalButton, RCTViewManager)
|
|
12
|
+
|
|
13
|
+
RCT_EXPORT_VIEW_PROPERTY(buttonColor, NSString)
|
|
14
|
+
RCT_EXPORT_VIEW_PROPERTY(buttonLabel, NSString)
|
|
15
|
+
RCT_EXPORT_VIEW_PROPERTY(borderRadius, double)
|
|
16
|
+
|
|
17
|
+
@end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import PayPal
|
|
2
|
+
|
|
3
|
+
@objc(HyperswitchPaypal)
|
|
4
|
+
class ReactNativeHyperswitchPaypal: NSObject {
|
|
5
|
+
|
|
6
|
+
private static let TAG = "HyperswitchPaypal"
|
|
7
|
+
|
|
8
|
+
@objc
|
|
9
|
+
static func requiresMainQueueSetup() -> Bool {
|
|
10
|
+
return true
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@objc(launchPayPal:callback:)
|
|
14
|
+
func launchPayPal(_ requestObj: String, callback: @escaping RCTResponseSenderBlock) {
|
|
15
|
+
|
|
16
|
+
guard let data = requestObj.data(using: .utf8),
|
|
17
|
+
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
|
|
18
|
+
let error: [String: Any] = [
|
|
19
|
+
"status": "failed",
|
|
20
|
+
"error_message": "Failed to parse request JSON"
|
|
21
|
+
]
|
|
22
|
+
callback([error])
|
|
23
|
+
return
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
guard let clientId = json["clientId"] as? String else {
|
|
27
|
+
let error: [String: Any] = [
|
|
28
|
+
"status": "failed",
|
|
29
|
+
"error_message": "Missing clientId"
|
|
30
|
+
]
|
|
31
|
+
callback([error])
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
guard let orderId = json["orderId"] as? String else {
|
|
36
|
+
let error: [String: Any] = [
|
|
37
|
+
"status": "failed",
|
|
38
|
+
"error_message": "Missing orderId"
|
|
39
|
+
]
|
|
40
|
+
callback([error])
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let environmentStr = json["environment"] as? String ?? "SANDBOX"
|
|
45
|
+
let fundingSourceStr = json["fundingSource"] as? String ?? "PAYPAL"
|
|
46
|
+
|
|
47
|
+
let environment: Environment = environmentStr == "PRODUCTION" ? .live : .sandbox
|
|
48
|
+
|
|
49
|
+
let fundingSource: PayPalWebCheckoutFundingSource
|
|
50
|
+
switch fundingSourceStr {
|
|
51
|
+
case "PAY_LATER":
|
|
52
|
+
fundingSource = .paylater
|
|
53
|
+
case "PAYPAL_CREDIT":
|
|
54
|
+
fundingSource = .paypalCredit
|
|
55
|
+
default:
|
|
56
|
+
fundingSource = .paypal
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
let config = CoreConfig(clientID: clientId, environment: environment)
|
|
61
|
+
let payPalClient = PayPalWebCheckoutClient(config: config)
|
|
62
|
+
let request = PayPalWebCheckoutRequest(orderID: orderId, fundingSource: fundingSource)
|
|
63
|
+
|
|
64
|
+
DispatchQueue.main.async {
|
|
65
|
+
payPalClient.start(request: request) { result in
|
|
66
|
+
switch result {
|
|
67
|
+
case .success(let paypalResult):
|
|
68
|
+
let successMap: [String: Any] = [
|
|
69
|
+
"status": "success",
|
|
70
|
+
"orderId": paypalResult.orderID,
|
|
71
|
+
"payerId": paypalResult.payerID
|
|
72
|
+
]
|
|
73
|
+
callback([successMap])
|
|
74
|
+
|
|
75
|
+
case .failure(let error):
|
|
76
|
+
if PayPalError.isCheckoutCanceled(error) {
|
|
77
|
+
let cancelMap: [String: Any] = [
|
|
78
|
+
"status": "cancelled"
|
|
79
|
+
]
|
|
80
|
+
callback([cancelMap])
|
|
81
|
+
} else {
|
|
82
|
+
let errorMap: [String: Any] = [
|
|
83
|
+
"status": "failed",
|
|
84
|
+
"error_message": error.localizedDescription
|
|
85
|
+
]
|
|
86
|
+
callback([errorMap])
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["requireNativeComponent"],"sourceRoot":"../../src","sources":["PaypalButtonNativeComponent.android.ts"],"mappings":";;AAAA,SAASA,sBAAsB,QAAwB,cAAc;AAQrE,eAAeA,sBAAsB,CAAc,cAAc,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { NativeModules } from 'react-native';
|
|
4
|
+
const {
|
|
5
|
+
HyperswitchPaypal
|
|
6
|
+
} = NativeModules;
|
|
7
|
+
export const isAvailable = !!HyperswitchPaypal;
|
|
8
|
+
export function launchPayPal(requestObj, callback) {
|
|
9
|
+
if (!HyperswitchPaypal) {
|
|
10
|
+
callback({
|
|
11
|
+
status: 'failed',
|
|
12
|
+
error_message: 'PayPal module not available'
|
|
13
|
+
});
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
return HyperswitchPaypal.launchPayPal(requestObj, callback);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["NativeModules","HyperswitchPaypal","isAvailable","launchPayPal","requestObj","callback","status","error_message"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,aAAa,QAAQ,cAAc;AAE5C,MAAM;EAAEC;AAAkB,CAAC,GAAGD,aAAa;AAE3C,OAAO,MAAME,WAAW,GAAG,CAAC,CAACD,iBAAiB;AAiB9C,OAAO,SAASE,YAAYA,CAC1BC,UAAkB,EAClBC,QAAwC,EAClC;EAEN,IAAI,CAACJ,iBAAiB,EAAE;IACtBI,QAAQ,CAAC;MAAEC,MAAM,EAAE,QAAQ;MAAEC,aAAa,EAAE;IAA8B,CAAC,CAAC;IAC5E;EACF;EACA,OAAON,iBAAiB,CAACE,YAAY,CAACC,UAAU,EAAEC,QAAQ,CAAC;AAC7D","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ViewProps } from 'react-native';
|
|
2
|
+
interface NativeProps extends ViewProps {
|
|
3
|
+
buttonColor?: string;
|
|
4
|
+
buttonLabel?: string;
|
|
5
|
+
borderRadius?: number;
|
|
6
|
+
}
|
|
7
|
+
declare const _default: import("react-native").HostComponent<NativeProps>;
|
|
8
|
+
export default _default;
|
|
9
|
+
//# sourceMappingURL=PaypalButtonNativeComponent.android.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PaypalButtonNativeComponent.android.d.ts","sourceRoot":"","sources":["../../../src/PaypalButtonNativeComponent.android.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAEtE,UAAU,WAAY,SAAQ,SAAS;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;;AAED,wBAAmE"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const isAvailable: boolean;
|
|
2
|
+
export type PayPalResult = {
|
|
3
|
+
status: string;
|
|
4
|
+
orderId?: string;
|
|
5
|
+
payerId?: string;
|
|
6
|
+
error_message?: string;
|
|
7
|
+
};
|
|
8
|
+
export type PayPalRequest = {
|
|
9
|
+
clientId: string;
|
|
10
|
+
environment?: 'SANDBOX' | 'PRODUCTION';
|
|
11
|
+
orderId: string;
|
|
12
|
+
returnUrl?: string;
|
|
13
|
+
fundingSource?: 'PAYPAL' | 'PAY_LATER' | 'PAYPAL_CREDIT';
|
|
14
|
+
};
|
|
15
|
+
export declare function launchPayPal(requestObj: string, callback: (result: PayPalResult) => void): void;
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,SAAsB,CAAC;AAE/C,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,eAAe,CAAC;CAC1D,CAAC;AAEF,wBAAgB,YAAY,CAC1B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,GACvC,IAAI,CAON"}
|
package/package.json
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@juspay-tech/react-native-hyperswitch-paypal",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "react native hyperswitch paypal",
|
|
5
|
+
"source": "./src/index.tsx",
|
|
6
|
+
"main": "./lib/module/index.js",
|
|
7
|
+
"types": "./lib/typescript/src/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/typescript/src/index.d.ts",
|
|
11
|
+
"default": "./lib/module/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./package.json": "./package.json"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"src",
|
|
17
|
+
"lib",
|
|
18
|
+
"android",
|
|
19
|
+
"ios",
|
|
20
|
+
"cpp",
|
|
21
|
+
"*.podspec",
|
|
22
|
+
"react-native.config.js",
|
|
23
|
+
"!ios/build",
|
|
24
|
+
"!android/build",
|
|
25
|
+
"!android/gradle",
|
|
26
|
+
"!android/gradlew",
|
|
27
|
+
"!android/gradlew.bat",
|
|
28
|
+
"!android/local.properties",
|
|
29
|
+
"!**/__tests__",
|
|
30
|
+
"!**/__fixtures__",
|
|
31
|
+
"!**/__mocks__",
|
|
32
|
+
"!**/.*"
|
|
33
|
+
],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"example": "yarn workspace @juspay-tech/react-native-hyperswitch-paypal-example",
|
|
36
|
+
"test": "jest",
|
|
37
|
+
"typecheck": "tsc",
|
|
38
|
+
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
39
|
+
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
|
|
40
|
+
"prepare": "bob build",
|
|
41
|
+
"release": "release-it"
|
|
42
|
+
},
|
|
43
|
+
"keywords": [
|
|
44
|
+
"react-native",
|
|
45
|
+
"ios",
|
|
46
|
+
"android"
|
|
47
|
+
],
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "git+https://github.com/juspay/react-native-hyperswitch.git"
|
|
51
|
+
},
|
|
52
|
+
"author": "Hyperswitch <chirag.kv@juspay.in> (https://github.com/ChiragKV-Juspay)",
|
|
53
|
+
"license": "MIT",
|
|
54
|
+
"bugs": {
|
|
55
|
+
"url": "https://github.com/juspay/react-native-hyperswitch/issues"
|
|
56
|
+
},
|
|
57
|
+
"homepage": "https://github.com/juspay/react-native-hyperswitch#readme",
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"registry": "https://registry.npmjs.org/"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@commitlint/config-conventional": "^19.6.0",
|
|
63
|
+
"@eslint/compat": "^1.2.7",
|
|
64
|
+
"@eslint/eslintrc": "^3.3.0",
|
|
65
|
+
"@eslint/js": "^9.22.0",
|
|
66
|
+
"@evilmartians/lefthook": "^1.5.0",
|
|
67
|
+
"@react-native/eslint-config": "^0.78.0",
|
|
68
|
+
"@release-it/conventional-changelog": "^9.0.2",
|
|
69
|
+
"@types/jest": "^29.5.5",
|
|
70
|
+
"@types/react": "^19.0.0",
|
|
71
|
+
"commitlint": "^19.6.1",
|
|
72
|
+
"del-cli": "^5.1.0",
|
|
73
|
+
"eslint": "^9.22.0",
|
|
74
|
+
"eslint-config-prettier": "^10.1.1",
|
|
75
|
+
"eslint-plugin-prettier": "^5.2.3",
|
|
76
|
+
"jest": "^29.7.0",
|
|
77
|
+
"prettier": "^3.0.3",
|
|
78
|
+
"react": "19.0.0",
|
|
79
|
+
"react-native": "0.78.2",
|
|
80
|
+
"react-native-builder-bob": "^0.40.18",
|
|
81
|
+
"release-it": "^17.10.0",
|
|
82
|
+
"turbo": "^1.10.7",
|
|
83
|
+
"typescript": "^5.2.2"
|
|
84
|
+
},
|
|
85
|
+
"peerDependencies": {
|
|
86
|
+
"react": "*",
|
|
87
|
+
"react-native": "*"
|
|
88
|
+
},
|
|
89
|
+
"workspaces": [
|
|
90
|
+
"example"
|
|
91
|
+
],
|
|
92
|
+
"packageManager": "yarn@3.6.1",
|
|
93
|
+
"jest": {
|
|
94
|
+
"preset": "react-native",
|
|
95
|
+
"modulePathIgnorePatterns": [
|
|
96
|
+
"<rootDir>/example/node_modules",
|
|
97
|
+
"<rootDir>/lib/"
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
"commitlint": {
|
|
101
|
+
"extends": [
|
|
102
|
+
"@commitlint/config-conventional"
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
"release-it": {
|
|
106
|
+
"git": {
|
|
107
|
+
"commitMessage": "chore: release ${version}",
|
|
108
|
+
"tagName": "v${version}"
|
|
109
|
+
},
|
|
110
|
+
"npm": {
|
|
111
|
+
"publish": true
|
|
112
|
+
},
|
|
113
|
+
"github": {
|
|
114
|
+
"release": true
|
|
115
|
+
},
|
|
116
|
+
"plugins": {
|
|
117
|
+
"@release-it/conventional-changelog": {
|
|
118
|
+
"preset": {
|
|
119
|
+
"name": "angular"
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
"prettier": {
|
|
125
|
+
"quoteProps": "consistent",
|
|
126
|
+
"singleQuote": true,
|
|
127
|
+
"tabWidth": 2,
|
|
128
|
+
"trailingComma": "es5",
|
|
129
|
+
"useTabs": false
|
|
130
|
+
},
|
|
131
|
+
"react-native-builder-bob": {
|
|
132
|
+
"source": "src",
|
|
133
|
+
"output": "lib",
|
|
134
|
+
"targets": [
|
|
135
|
+
[
|
|
136
|
+
"module",
|
|
137
|
+
{
|
|
138
|
+
"esm": true
|
|
139
|
+
}
|
|
140
|
+
],
|
|
141
|
+
[
|
|
142
|
+
"typescript",
|
|
143
|
+
{
|
|
144
|
+
"project": "tsconfig.build.json"
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
]
|
|
148
|
+
},
|
|
149
|
+
"create-react-native-library": {
|
|
150
|
+
"type": "legacy-module",
|
|
151
|
+
"languages": "kotlin-swift",
|
|
152
|
+
"version": "0.49.8"
|
|
153
|
+
}
|
|
154
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
dependency: {
|
|
3
|
+
platforms: {
|
|
4
|
+
android: {
|
|
5
|
+
sourceDir: './android',
|
|
6
|
+
packageImportPath: 'import com.juspaytech.reactnativehyperswitchpaypal.ReactNativeHyperswitchPaypalPackage;',
|
|
7
|
+
packageInstance: 'new ReactNativeHyperswitchPaypalPackage()',
|
|
8
|
+
},
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { requireNativeComponent, type ViewProps } from 'react-native';
|
|
2
|
+
|
|
3
|
+
interface NativeProps extends ViewProps {
|
|
4
|
+
buttonColor?: string;
|
|
5
|
+
buttonLabel?: string;
|
|
6
|
+
borderRadius?: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default requireNativeComponent<NativeProps>('PaypalButton');
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { NativeModules } from 'react-native';
|
|
2
|
+
|
|
3
|
+
const { HyperswitchPaypal } = NativeModules;
|
|
4
|
+
|
|
5
|
+
export const isAvailable = !!HyperswitchPaypal;
|
|
6
|
+
|
|
7
|
+
export type PayPalResult = {
|
|
8
|
+
status: string;
|
|
9
|
+
orderId?: string;
|
|
10
|
+
payerId?: string;
|
|
11
|
+
error_message?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type PayPalRequest = {
|
|
15
|
+
clientId: string;
|
|
16
|
+
environment?: 'SANDBOX' | 'PRODUCTION';
|
|
17
|
+
orderId: string;
|
|
18
|
+
returnUrl?: string;
|
|
19
|
+
fundingSource?: 'PAYPAL' | 'PAY_LATER' | 'PAYPAL_CREDIT';
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export function launchPayPal(
|
|
23
|
+
requestObj: string,
|
|
24
|
+
callback: (result: PayPalResult) => void
|
|
25
|
+
): void {
|
|
26
|
+
|
|
27
|
+
if (!HyperswitchPaypal) {
|
|
28
|
+
callback({ status: 'failed', error_message: 'PayPal module not available' });
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
return HyperswitchPaypal.launchPayPal(requestObj, callback);
|
|
32
|
+
}
|