react-amwal-pay 0.1.14 → 0.1.16
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 +48 -6
- package/android/gradle.properties +1 -1
- package/ios/ReactAmwalPay.swift +139 -6
- package/lib/module/AmwalPaySDK.js.map +1 -1
- package/lib/module/NativeReactAmwalPay.js +6 -1
- package/lib/module/NativeReactAmwalPay.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/network/NetworkClient.js.map +1 -1
- package/lib/module/utils/SecureHashUtil.js +4 -4
- package/lib/module/utils/SecureHashUtil.js.map +1 -1
- package/lib/module/utils/UuidUtil.js +2 -1
- package/lib/module/utils/UuidUtil.js.map +1 -1
- package/lib/typescript/src/AmwalPaySDK.d.ts.map +1 -1
- package/lib/typescript/src/NativeReactAmwalPay.d.ts +41 -0
- package/lib/typescript/src/NativeReactAmwalPay.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/network/NetworkClient.d.ts.map +1 -1
- package/lib/typescript/src/utils/SecureHashUtil.d.ts.map +1 -1
- package/lib/typescript/src/utils/UuidUtil.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/AmwalPaySDK.ts +30 -11
- package/src/NativeReactAmwalPay.ts +43 -3
- package/src/index.tsx +7 -6
- package/src/network/NetworkClient.ts +87 -84
- package/src/utils/SecureHashUtil.ts +52 -45
- package/src/utils/UuidUtil.ts +9 -6
package/README.md
CHANGED
|
@@ -54,7 +54,7 @@ Add the following configuration to your `ios/Podfile` inside the `post_install`
|
|
|
54
54
|
```ruby
|
|
55
55
|
post_install do |installer|
|
|
56
56
|
react_native_post_install(installer, config[:reactNativePath])
|
|
57
|
-
|
|
57
|
+
|
|
58
58
|
# Set "Build Libraries for Distribution" to NO for amwalsdk
|
|
59
59
|
installer.pods_project.targets.each do |target|
|
|
60
60
|
if target.name == 'amwalsdk'
|
|
@@ -112,6 +112,7 @@ No additional Android configuration is required. The SDK uses React Native's aut
|
|
|
112
112
|
minSdkVersion = 24
|
|
113
113
|
```
|
|
114
114
|
|
|
115
|
+
|
|
115
116
|
### Step 5: Clean and Rebuild
|
|
116
117
|
|
|
117
118
|
After installation, clean and rebuild your project:
|
|
@@ -170,7 +171,10 @@ const config: AmwalPayConfig = {
|
|
|
170
171
|
merchantReference: 'optional-merchant-reference', // optional: merchant reference for transaction tracking
|
|
171
172
|
additionValues: { // optional: custom key-value pairs for SDK configuration
|
|
172
173
|
merchantIdentifier: 'merchant.applepay.amwalpay', // for Apple Pay configuration
|
|
173
|
-
|
|
174
|
+
useBottomSheetDesign: 'true', // use bottom sheet design (v2)
|
|
175
|
+
primaryColor: '#FF5733', // custom primary color
|
|
176
|
+
secondaryColor: '#33FF57', // custom secondary color
|
|
177
|
+
ignoreReceipt: 'false' // show receipt after transaction
|
|
174
178
|
},
|
|
175
179
|
onCustomerId(customerId) {
|
|
176
180
|
console.log('Customer ID:', customerId);
|
|
@@ -236,7 +240,32 @@ The SDK supports `additionValues` parameter for passing custom key-value pairs t
|
|
|
236
240
|
The SDK automatically provides default values:
|
|
237
241
|
- `merchantIdentifier`: "merchant.applepay.amwalpay" (used for Apple Pay configuration)
|
|
238
242
|
|
|
239
|
-
###
|
|
243
|
+
### Available Configuration Options
|
|
244
|
+
|
|
245
|
+
You can customize the SDK behavior using the following `additionValues` keys:
|
|
246
|
+
|
|
247
|
+
#### UI Customization
|
|
248
|
+
- **`useBottomSheetDesign`**: `'true'` | `'false'` (default: `'false'`)
|
|
249
|
+
- Controls the payment screen design
|
|
250
|
+
- `'true'`: Uses the newer bottom sheet design (v2)
|
|
251
|
+
- `'false'`: Uses the original full-screen design
|
|
252
|
+
|
|
253
|
+
- **`primaryColor`**: Hex color string (e.g., `'#FF5733'`)
|
|
254
|
+
- Sets the primary theme color for the SDK UI
|
|
255
|
+
|
|
256
|
+
- **`secondaryColor`**: Hex color string (e.g., `'#33FF57'`)
|
|
257
|
+
- Sets the secondary theme color for the SDK UI
|
|
258
|
+
|
|
259
|
+
#### Payment Flow
|
|
260
|
+
- **`ignoreReceipt`**: `'true'` | `'false'` (default: `'false'`)
|
|
261
|
+
- Controls whether to show the receipt screen after transaction
|
|
262
|
+
- `'true'`: Skips the receipt display
|
|
263
|
+
- `'false'`: Shows the receipt screen
|
|
264
|
+
|
|
265
|
+
- **`merchantIdentifier`**: String (default: `'merchant.applepay.amwalpay'`)
|
|
266
|
+
- Apple Pay merchant identifier for iOS
|
|
267
|
+
|
|
268
|
+
### Usage Examples
|
|
240
269
|
|
|
241
270
|
```js
|
|
242
271
|
// Using default additionValues (automatically applied)
|
|
@@ -245,18 +274,31 @@ const config = {
|
|
|
245
274
|
// additionValues will automatically include merchantIdentifier
|
|
246
275
|
};
|
|
247
276
|
|
|
248
|
-
// Using custom additionValues
|
|
277
|
+
// Using custom additionValues with UI customization
|
|
249
278
|
const customConfig = {
|
|
250
279
|
// ... other configuration
|
|
251
280
|
additionValues: {
|
|
252
|
-
|
|
253
|
-
|
|
281
|
+
useBottomSheetDesign: 'true',
|
|
282
|
+
primaryColor: '#FF5733',
|
|
283
|
+
secondaryColor: '#33FF57',
|
|
284
|
+
ignoreReceipt: 'false',
|
|
285
|
+
merchantIdentifier: 'merchant.custom.identifier'
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
// Minimal configuration with bottom sheet design
|
|
290
|
+
const minimalConfig = {
|
|
291
|
+
// ... other configuration
|
|
292
|
+
additionValues: {
|
|
293
|
+
useBottomSheetDesign: 'true'
|
|
254
294
|
}
|
|
255
295
|
};
|
|
256
296
|
```
|
|
257
297
|
|
|
258
298
|
Custom `additionValues` will be merged with defaults, with custom values taking precedence.
|
|
259
299
|
|
|
300
|
+
**Note:** All boolean values should be passed as strings (`'true'` or `'false'`).
|
|
301
|
+
|
|
260
302
|
## Configuration
|
|
261
303
|
|
|
262
304
|
The `AmwalPayConfig` interface includes the following properties:
|
package/ios/ReactAmwalPay.swift
CHANGED
|
@@ -3,6 +3,70 @@ import amwalsdk
|
|
|
3
3
|
import React
|
|
4
4
|
import UIKit
|
|
5
5
|
|
|
6
|
+
// MARK: - Container view controller that keeps SDK alive during 3DS presentation
|
|
7
|
+
/// This container wraps the SDK view controller as a child
|
|
8
|
+
/// When 3DS opens its WebView, it can present on top without dismissing the SDK
|
|
9
|
+
class ShareableContainerViewController: UIViewController {
|
|
10
|
+
private let sdkViewController: UIViewController
|
|
11
|
+
|
|
12
|
+
init(sdkViewController: UIViewController) {
|
|
13
|
+
self.sdkViewController = sdkViewController
|
|
14
|
+
super.init(nibName: nil, bundle: nil)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
required init?(coder: NSCoder) {
|
|
18
|
+
fatalError("init(coder:) has not been implemented")
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
override func viewDidLoad() {
|
|
22
|
+
super.viewDidLoad()
|
|
23
|
+
|
|
24
|
+
// Add SDK view controller as child - this keeps it alive during 3DS presentation
|
|
25
|
+
addChild(sdkViewController)
|
|
26
|
+
view.addSubview(sdkViewController.view)
|
|
27
|
+
sdkViewController.view.frame = view.bounds
|
|
28
|
+
sdkViewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
|
29
|
+
sdkViewController.didMove(toParent: self)
|
|
30
|
+
|
|
31
|
+
view.backgroundColor = .clear
|
|
32
|
+
sdkViewController.view.backgroundColor = .clear
|
|
33
|
+
|
|
34
|
+
// Enable presentation context to handle 3DS WebView presentation
|
|
35
|
+
// This is critical: allows 3DS WebView to present on top without dismissing the SDK
|
|
36
|
+
definesPresentationContext = true
|
|
37
|
+
providesPresentationContextTransitionStyle = true
|
|
38
|
+
|
|
39
|
+
// Ensure the SDK view controller also allows nested presentations
|
|
40
|
+
// This prevents it from being dismissed when 3DS presents its WebView
|
|
41
|
+
sdkViewController.definesPresentationContext = true
|
|
42
|
+
sdkViewController.providesPresentationContextTransitionStyle = true
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
override func viewDidAppear(_ animated: Bool) {
|
|
46
|
+
super.viewDidAppear(animated)
|
|
47
|
+
// Ensure container is ready for nested presentations
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private func topmostPresentedViewController() -> UIViewController {
|
|
51
|
+
var topController: UIViewController = self
|
|
52
|
+
while let presented = topController.presentedViewController {
|
|
53
|
+
topController = presented
|
|
54
|
+
}
|
|
55
|
+
return topController
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
override func present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
|
|
59
|
+
// If already presenting, present from the topmost controller
|
|
60
|
+
// This allows 3DS WebView to present on top without dismissing the SDK
|
|
61
|
+
if let presented = presentedViewController {
|
|
62
|
+
let topmost = topmostPresentedViewController()
|
|
63
|
+
topmost.present(viewControllerToPresent, animated: flag, completion: completion)
|
|
64
|
+
} else {
|
|
65
|
+
super.present(viewControllerToPresent, animated: flag, completion: completion)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
6
70
|
// MARK: - Fix UIViewController presentation for share sheets
|
|
7
71
|
public extension UIViewController {
|
|
8
72
|
static let swizzlePresentOnce: Void = {
|
|
@@ -28,8 +92,18 @@ public extension UIViewController {
|
|
|
28
92
|
}
|
|
29
93
|
}
|
|
30
94
|
|
|
31
|
-
//
|
|
32
|
-
|
|
95
|
+
// Special handling for ShareableContainerViewController and its children
|
|
96
|
+
// If presenting from a child of ShareableContainerViewController, forward to container
|
|
97
|
+
if let container = findShareableContainer() {
|
|
98
|
+
if container != self {
|
|
99
|
+
// We're a child of the container, forward to container
|
|
100
|
+
container.swizzled_present(viewControllerToPresent, animated: flag, completion: completion)
|
|
101
|
+
return
|
|
102
|
+
}
|
|
103
|
+
// We ARE the container - allow nested presentations
|
|
104
|
+
// Don't auto-dismiss, just present on top
|
|
105
|
+
} else if self.presentedViewController != nil && !self.definesPresentationContext {
|
|
106
|
+
// Not a container, and already presenting - auto-dismiss
|
|
33
107
|
print("⚠️ Already presenting, dismissing first...")
|
|
34
108
|
self.dismiss(animated: false) { [weak self] in
|
|
35
109
|
self?.swizzled_present(viewControllerToPresent, animated: flag, completion: completion)
|
|
@@ -41,6 +115,21 @@ public extension UIViewController {
|
|
|
41
115
|
self.swizzled_present(viewControllerToPresent, animated: flag, completion: completion)
|
|
42
116
|
}
|
|
43
117
|
|
|
118
|
+
// Helper to find ShareableContainerViewController in parent hierarchy
|
|
119
|
+
private func findShareableContainer() -> ShareableContainerViewController? {
|
|
120
|
+
var current: UIViewController? = self
|
|
121
|
+
while let parent = current?.parent {
|
|
122
|
+
if let container = parent as? ShareableContainerViewController {
|
|
123
|
+
return container
|
|
124
|
+
}
|
|
125
|
+
current = parent
|
|
126
|
+
}
|
|
127
|
+
if let container = self as? ShareableContainerViewController {
|
|
128
|
+
return container
|
|
129
|
+
}
|
|
130
|
+
return nil
|
|
131
|
+
}
|
|
132
|
+
|
|
44
133
|
static func getTopMostViewController() -> UIViewController? {
|
|
45
134
|
var topController: UIViewController?
|
|
46
135
|
|
|
@@ -65,6 +154,7 @@ public extension UIViewController {
|
|
|
65
154
|
@objc(ReactAmwalPay)
|
|
66
155
|
open class ReactAmwalPay: RCTEventEmitter {
|
|
67
156
|
private var hasListeners = false
|
|
157
|
+
private var sdkWindow: UIWindow? // Separate window for SDK to avoid modal dismissal issues
|
|
68
158
|
|
|
69
159
|
// Initialize swizzling when the class is first loaded
|
|
70
160
|
private static let initializeSwizzling: Void = {
|
|
@@ -197,6 +287,11 @@ open class ReactAmwalPay: RCTEventEmitter {
|
|
|
197
287
|
print("🟠 Response type: \(type(of: response))")
|
|
198
288
|
print("🟠 Response value: \(response ?? "nil")")
|
|
199
289
|
|
|
290
|
+
// Dismiss SDK window when payment completes
|
|
291
|
+
DispatchQueue.main.async {
|
|
292
|
+
self?.dismissSDKWindow()
|
|
293
|
+
}
|
|
294
|
+
|
|
200
295
|
// The SDK returns a JSON string, we need to parse it
|
|
201
296
|
if let responseString = response as? String,
|
|
202
297
|
let data = responseString.data(using: .utf8),
|
|
@@ -222,11 +317,41 @@ open class ReactAmwalPay: RCTEventEmitter {
|
|
|
222
317
|
}
|
|
223
318
|
)
|
|
224
319
|
|
|
225
|
-
|
|
226
|
-
|
|
320
|
+
// Ensure transparency
|
|
321
|
+
sdkVC.view.backgroundColor = .clear
|
|
322
|
+
sdkVC.view.isOpaque = false
|
|
323
|
+
|
|
324
|
+
// Wrap SDK view controller in container
|
|
325
|
+
let containerVC = ShareableContainerViewController(sdkViewController: sdkVC)
|
|
326
|
+
containerVC.view.backgroundColor = .clear
|
|
327
|
+
|
|
328
|
+
print("🟠 SDK ViewController wrapped in container")
|
|
329
|
+
print("🟠 Creating separate window for SDK...")
|
|
227
330
|
|
|
228
|
-
//
|
|
229
|
-
|
|
331
|
+
// Create a separate window for the SDK
|
|
332
|
+
// This prevents modal presentation issues - SDK lives in its own window
|
|
333
|
+
// 3DS can present on top without affecting the SDK
|
|
334
|
+
if #available(iOS 13.0, *) {
|
|
335
|
+
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
|
|
336
|
+
self.sdkWindow = UIWindow(windowScene: windowScene)
|
|
337
|
+
}
|
|
338
|
+
} else {
|
|
339
|
+
self.sdkWindow = UIWindow(frame: UIScreen.main.bounds)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
guard let sdkWindow = self.sdkWindow else {
|
|
343
|
+
print("🟠 Failed to create SDK window, falling back to modal presentation")
|
|
344
|
+
rootVC.present(containerVC, animated: true)
|
|
345
|
+
return
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
sdkWindow.rootViewController = containerVC
|
|
349
|
+
sdkWindow.windowLevel = .normal + 1 // Above main window
|
|
350
|
+
sdkWindow.backgroundColor = .clear
|
|
351
|
+
sdkWindow.isOpaque = false
|
|
352
|
+
sdkWindow.makeKeyAndVisible()
|
|
353
|
+
|
|
354
|
+
print("🟠 SDK window created and made visible")
|
|
230
355
|
} catch {
|
|
231
356
|
print("Presentation failed: \(error.localizedDescription)")
|
|
232
357
|
let errorData: [String: Any] = [
|
|
@@ -260,4 +385,12 @@ open class ReactAmwalPay: RCTEventEmitter {
|
|
|
260
385
|
public override static func requiresMainQueueSetup() -> Bool {
|
|
261
386
|
return true
|
|
262
387
|
}
|
|
388
|
+
|
|
389
|
+
// Dismiss SDK window when payment completes
|
|
390
|
+
private func dismissSDKWindow() {
|
|
391
|
+
print("🟠 Dismissing SDK window...")
|
|
392
|
+
sdkWindow?.isHidden = true
|
|
393
|
+
sdkWindow?.rootViewController = nil
|
|
394
|
+
sdkWindow = nil
|
|
395
|
+
}
|
|
263
396
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["initiate","onCustomerId","onResponse","NetworkClient","AmwalPaySDK","onResponseSubscription","onCustomerIdSubscription","constructor","getInstance","instance","startPayment","config","setupEventListeners","networkClient","console","log","environment","sessionToken","fetchSessionToken","merchantId","customerId","secureHash","completeConfig","JSON","stringify","error","dispose","removeEventListeners","response","remove"],"sourceRoot":"../../src","sources":["AmwalPaySDK.ts"],"mappings":";;AAAA,
|
|
1
|
+
{"version":3,"names":["initiate","onCustomerId","onResponse","NetworkClient","AmwalPaySDK","onResponseSubscription","onCustomerIdSubscription","constructor","getInstance","instance","startPayment","config","setupEventListeners","networkClient","console","log","environment","sessionToken","fetchSessionToken","merchantId","customerId","secureHash","completeConfig","JSON","stringify","error","dispose","removeEventListeners","response","remove"],"sourceRoot":"../../src","sources":["AmwalPaySDK.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -18,7 +18,12 @@ export let TransactionType = /*#__PURE__*/function (TransactionType) {
|
|
|
18
18
|
return TransactionType;
|
|
19
19
|
}({});
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Configuration interface for Amwal Pay SDK
|
|
23
|
+
*
|
|
24
|
+
* @interface AmwalPayConfig
|
|
25
|
+
* @description Complete configuration for initializing and starting a payment session
|
|
26
|
+
*/
|
|
22
27
|
|
|
23
28
|
// This is the configuration that will be passed to the native module
|
|
24
29
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["TurboModuleRegistry","Environment","Currency","TransactionType","getEnforcing"],"sourceRoot":"../../src","sources":["NativeReactAmwalPay.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;AAElD,WAAYC,WAAW,0BAAXA,WAAW;EAAXA,WAAW;EAAXA,WAAW;EAAXA,WAAW;EAAA,OAAXA,WAAW;AAAA;AAMvB,WAAYC,QAAQ,0BAARA,QAAQ;EAARA,QAAQ;EAAA,OAARA,QAAQ;AAAA;AAIpB,WAAYC,eAAe,0BAAfA,eAAe;EAAfA,eAAe;EAAfA,eAAe;EAAfA,eAAe;EAAA,OAAfA,eAAe;AAAA;;AAY3B;;
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","Environment","Currency","TransactionType","getEnforcing"],"sourceRoot":"../../src","sources":["NativeReactAmwalPay.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;AAElD,WAAYC,WAAW,0BAAXA,WAAW;EAAXA,WAAW;EAAXA,WAAW;EAAXA,WAAW;EAAA,OAAXA,WAAW;AAAA;AAMvB,WAAYC,QAAQ,0BAARA,QAAQ;EAARA,QAAQ;EAAA,OAARA,QAAQ;AAAA;AAIpB,WAAYC,eAAe,0BAAfA,eAAe;EAAfA,eAAe;EAAfA,eAAe;EAAfA,eAAe;EAAA,OAAfA,eAAe;AAAA;;AAY3B;AACA;AACA;AACA;AACA;AACA;;AAsDA;;AAwBA,eAAeH,mBAAmB,CAACI,YAAY,CAAO,eAAe,CAAC","ignoreList":[]}
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["ReactAmwalPay","Environment","Currency","TransactionType","AmwalPaySDK","UuidUtil","NativeEventEmitter","eventEmitter","initiate","config","defaultAdditionValues","merchantIdentifier","finalAdditionValues","additionValues","nativeConfig","environment","secureHash","currency","amount","merchantId","terminalId","locale","customerId","transactionType","sessionToken","transactionId","generateTransactionId","merchantReference","onResponse","callback","addListener","onCustomerId"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,aAAa,IAClBC,WAAW,EACXC,QAAQ,EACRC,eAAe,QAIV,0BAAuB;AAC9B,OAAOC,WAAW,MAAM,kBAAe;AACvC,SAASC,QAAQ,QAAQ,qBAAkB;AAC3C,
|
|
1
|
+
{"version":3,"names":["ReactAmwalPay","Environment","Currency","TransactionType","AmwalPaySDK","UuidUtil","NativeEventEmitter","eventEmitter","initiate","config","defaultAdditionValues","merchantIdentifier","finalAdditionValues","additionValues","nativeConfig","environment","secureHash","currency","amount","merchantId","terminalId","locale","customerId","transactionType","sessionToken","transactionId","generateTransactionId","merchantReference","onResponse","callback","addListener","onCustomerId"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,aAAa,IAClBC,WAAW,EACXC,QAAQ,EACRC,eAAe,QAIV,0BAAuB;AAC9B,OAAOC,WAAW,MAAM,kBAAe;AACvC,SAASC,QAAQ,QAAQ,qBAAkB;AAC3C,SAASC,kBAAkB,QAAgC,cAAc;;AAEzE;AACA,MAAMC,YAAY,GAAG,IAAID,kBAAkB,CAACN,aAAoB,CAAC;AAEjE,OAAO,SAASQ,QAAQA,CAACC,MAAsB,EAAQ;EACrD;EACA,MAAMC,qBAAqB,GAAG;IAC5BC,kBAAkB,EAAE;EACtB,CAAC;EAED,MAAMC,mBAAmB,GAAG;IAC1B,GAAGF,qBAAqB;IACxB,GAAGD,MAAM,CAACI;EACZ,CAAC;EAED,MAAMC,YAAkC,GAAG;IACzCC,WAAW,EAAEN,MAAM,CAACM,WAAW;IAC/BC,UAAU,EAAEP,MAAM,CAACO,UAAU;IAC7BC,QAAQ,EAAER,MAAM,CAACQ,QAAQ;IACzBC,MAAM,EAAET,MAAM,CAACS,MAAM;IACrBC,UAAU,EAAEV,MAAM,CAACU,UAAU;IAC7BC,UAAU,EAAEX,MAAM,CAACW,UAAU;IAC7BC,MAAM,EAAEZ,MAAM,CAACY,MAAM;IACrBC,UAAU,EAAEb,MAAM,CAACa,UAAU;IAC7BC,eAAe,EAAEd,MAAM,CAACc,eAAe;IACvCC,YAAY,EAAEf,MAAM,CAACe,YAAY;IACjCC,aAAa,EAAEhB,MAAM,CAACgB,aAAa,IAAIpB,QAAQ,CAACqB,qBAAqB,CAAC,CAAC;IACvEb,cAAc,EAAED,mBAAmB;IACnCe,iBAAiB,EAAElB,MAAM,CAACkB;EAC5B,CAAC;;EAED;EACA3B,aAAa,CAACQ,QAAQ,CAACM,YAAY,CAAC;AACtC;AAEA,OAAO,SAASc,UAAUA,CACxBC,QAA8C,EAC3B;EACnB,OAAOtB,YAAY,CAACuB,WAAW,CAAC,YAAY,EAAED,QAAQ,CAAC;AACzD;AACA,OAAO,SAASE,YAAYA,CAC1BF,QAAsC,EACnB;EACnB,OAAOtB,YAAY,CAACuB,WAAW,CAAC,cAAc,EAAED,QAAQ,CAAC;AAC3D;AAEA,SACE5B,WAAW,EACXC,QAAQ,EACRC,eAAe,EAGfC,WAAW,EACXC,QAAQ","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Alert","Environment","SecureHashUtil","NetworkClient","constructor","getInstance","instance","getWebhookUrl","env","SIT","UAT","PROD","fetchSessionToken","merchantId","customerId","secureHashValue","webhookUrl","dataMap","secureHash","clearSecureHash","response","fetch","method","headers","body","JSON","stringify","responseData","json","ok","success","data","sessionToken","errorMessage","errorList","join","showErrorDialog","error","message","alert","text"],"sourceRoot":"../../../src","sources":["network/NetworkClient.ts"],"mappings":";;AAAA,SAASA,KAAK,QAAQ,cAAc;AACpC,SAASC,WAAW,QAAQ,2BAAwB;AACpD,OAAOC,cAAc,MAAM,4BAAyB;AAEpD,MAAMC,aAAa,CAAC;EAGVC,WAAWA,CAAA,EAAG,CAAC;EAEvB,OAAOC,WAAWA,CAAA,EAAkB;IAClC,IAAI,CAACF,aAAa,CAACG,QAAQ,EAAE;MAC3BH,aAAa,CAACG,QAAQ,GAAG,IAAIH,aAAa,CAAC,CAAC;IAC9C;IACA,OAAOA,aAAa,CAACG,QAAQ;EAC/B;EAEQC,aAAaA,CAACC,GAAgB,EAAU;IAC9C,QAAQA,GAAG;MACT,KAAKP,WAAW,CAACQ,GAAG;QAClB,OAAO,iCAAiC;MAC1C,KAAKR,WAAW,CAACS,GAAG;QAClB,OAAO,iCAAiC;MAC1C,KAAKT,WAAW,CAACU,IAAI;QACnB,OAAO,8BAA8B;MACvC;QACE,OAAO,iCAAiC;IAC5C;EACF;EAEA,MAAMC,iBAAiBA,CACrBJ,GAAgB,EAChBK,UAAkB,EAClBC,UAAyB,EACzBC,eAAuB,EACC;IACxB,IAAI;MACF,MAAMC,UAAU,GAAG,IAAI,CAACT,aAAa,CAACC,GAAG,CAAC;MAE1C,MAAMS,OAAO,GAAG;QACdJ,UAAU;QACVC;MACF,CAAC;MAED,MAAMI,UAAU,GAAGhB,cAAc,CAACiB,eAAe,
|
|
1
|
+
{"version":3,"names":["Alert","Environment","SecureHashUtil","NetworkClient","constructor","getInstance","instance","getWebhookUrl","env","SIT","UAT","PROD","fetchSessionToken","merchantId","customerId","secureHashValue","webhookUrl","dataMap","secureHash","clearSecureHash","response","fetch","method","headers","body","JSON","stringify","responseData","json","ok","success","data","sessionToken","errorMessage","errorList","join","showErrorDialog","error","message","alert","text"],"sourceRoot":"../../../src","sources":["network/NetworkClient.ts"],"mappings":";;AAAA,SAASA,KAAK,QAAQ,cAAc;AACpC,SAASC,WAAW,QAAQ,2BAAwB;AACpD,OAAOC,cAAc,MAAM,4BAAyB;AAEpD,MAAMC,aAAa,CAAC;EAGVC,WAAWA,CAAA,EAAG,CAAC;EAEvB,OAAOC,WAAWA,CAAA,EAAkB;IAClC,IAAI,CAACF,aAAa,CAACG,QAAQ,EAAE;MAC3BH,aAAa,CAACG,QAAQ,GAAG,IAAIH,aAAa,CAAC,CAAC;IAC9C;IACA,OAAOA,aAAa,CAACG,QAAQ;EAC/B;EAEQC,aAAaA,CAACC,GAAgB,EAAU;IAC9C,QAAQA,GAAG;MACT,KAAKP,WAAW,CAACQ,GAAG;QAClB,OAAO,iCAAiC;MAC1C,KAAKR,WAAW,CAACS,GAAG;QAClB,OAAO,iCAAiC;MAC1C,KAAKT,WAAW,CAACU,IAAI;QACnB,OAAO,8BAA8B;MACvC;QACE,OAAO,iCAAiC;IAC5C;EACF;EAEA,MAAMC,iBAAiBA,CACrBJ,GAAgB,EAChBK,UAAkB,EAClBC,UAAyB,EACzBC,eAAuB,EACC;IACxB,IAAI;MACF,MAAMC,UAAU,GAAG,IAAI,CAACT,aAAa,CAACC,GAAG,CAAC;MAE1C,MAAMS,OAAO,GAAG;QACdJ,UAAU;QACVC;MACF,CAAC;MAED,MAAMI,UAAU,GAAGhB,cAAc,CAACiB,eAAe,CAC/CJ,eAAe,EACfE,OACF,CAAC;MAED,MAAMG,QAAQ,GAAG,MAAMC,KAAK,CAC1B,GAAGL,UAAU,+BAA+B,EAC5C;QACEM,MAAM,EAAE,MAAM;QACdC,OAAO,EAAE;UACP,QAAQ,EAAE,YAAY;UACtB,iBAAiB,EAAE,gBAAgB;UACnC,cAAc,EAAE;QAClB,CAAC;QACDC,IAAI,EAAEC,IAAI,CAACC,SAAS,CAAC;UACnBb,UAAU;UACVE,eAAe,EAAEG,UAAU;UAC3BJ;QACF,CAAC;MACH,CACF,CAAC;MAED,MAAMa,YAAY,GAAG,MAAMP,QAAQ,CAACQ,IAAI,CAAC,CAAC;MAE1C,IAAIR,QAAQ,CAACS,EAAE,IAAIF,YAAY,CAACG,OAAO,EAAE;QACvC,OAAOH,YAAY,CAACI,IAAI,CAACC,YAAY;MACvC,CAAC,MAAM;QACL,MAAMC,YAAY,GAChBN,YAAY,CAACO,SAAS,EAAEC,IAAI,CAAC,GAAG,CAAC,IAAI,eAAe;QACtD,IAAI,CAACC,eAAe,CAACH,YAAY,CAAC;QAClC,OAAO,IAAI;MACb;IACF,CAAC,CAAC,OAAOI,KAAK,EAAE;MACd,IAAI,CAACD,eAAe,CAAC,sBAAsB,CAAC;MAC5C,OAAO,IAAI;IACb;EACF;EAEQA,eAAeA,CAACE,OAAe,EAAQ;IAC7CtC,KAAK,CAACuC,KAAK,CAAC,OAAO,EAAED,OAAO,EAAE,CAAC;MAAEE,IAAI,EAAE;IAAK,CAAC,CAAC,CAAC;EACjD;AACF;AAEA,eAAerC,aAAa","ignoreList":[]}
|
|
@@ -13,19 +13,19 @@ class SecureHashUtil {
|
|
|
13
13
|
}
|
|
14
14
|
static generateSecureHash(message, secretKey) {
|
|
15
15
|
try {
|
|
16
|
-
// Convert hex string to byte array
|
|
16
|
+
// Convert hex string to byte array
|
|
17
17
|
const keyBytes = secretKey.match(/.{2}/g)?.map(byte => parseInt(byte, 16));
|
|
18
18
|
if (!keyBytes) {
|
|
19
19
|
throw new Error('Invalid secret key format');
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
// Convert key bytes to hex string for crypto-js
|
|
22
|
+
// Convert key bytes to hex string for crypto-js
|
|
23
23
|
const keyHex = keyBytes.map(byte => byte.toString(16).padStart(2, '0')).join('');
|
|
24
24
|
|
|
25
|
-
// Generate HMAC-SHA256
|
|
25
|
+
// Generate HMAC-SHA256
|
|
26
26
|
const hash = HmacSHA256(message, Hex.parse(keyHex));
|
|
27
27
|
|
|
28
|
-
// Convert to uppercase hex string
|
|
28
|
+
// Convert to uppercase hex string
|
|
29
29
|
return hash.toString(Hex).toUpperCase();
|
|
30
30
|
} catch (e) {
|
|
31
31
|
console.error('Error generating secure hash:', e);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["HmacSHA256","Hex","SecureHashUtil","clearSecureHash","secretKey","data","secureHashValue","concatenatedString","composeData","generateSecureHash","requestParameters","Object","entries","sort","keyA","keyB","localeCompare","filter","_","value","map","key","join","message","keyBytes","match","byte","parseInt","Error","keyHex","toString","padStart","hash","parse","toUpperCase","e","console","error"],"sourceRoot":"../../../src","sources":["utils/SecureHashUtil.ts"],"mappings":";;AAAA,OAAOA,UAAU,MAAM,uBAAuB;AAC9C,OAAOC,GAAG,MAAM,mBAAmB;AAInC,MAAMC,cAAc,CAAC;EACnB,OAAOC,eAAeA,CAACC,SAAiB,EAAEC,IAAa,EAAU;IAC/D,OAAOA,IAAI,CAACC,eAAe;IAC3B,MAAMC,kBAAkB,GAAG,IAAI,CAACC,WAAW,CAACH,IAAI,CAAC;IACjD,OAAO,IAAI,CAACI,kBAAkB,CAACF,kBAAkB,EAAEH,SAAS,CAAC;EAC/D;EAEA,OAAeI,WAAWA,CAACE,iBAA0B,EAAU;IAC7D,OAAOC,MAAM,CAACC,OAAO,CAACF,iBAAiB,CAAC,CACrCG,IAAI,CAAC,CAAC,CAACC,IAAI,CAAC,EAAE,CAACC,IAAI,CAAC,KAAKD,IAAI,CAACE,aAAa,CAACD,IAAI,CAAC,CAAC,CAClDE,MAAM,CAAC,CAAC,CAACC,CAAC,EAAEC,KAAK,CAAC,KAAKA,KAAK,IAAI,IAAI,IAAIA,KAAK,KAAK,EAAE,CAAC,CACrDC,GAAG,CAAC,CAAC,CAACC,GAAG,EAAEF,KAAK,CAAC,KAAK,GAAGE,GAAG,IAAIF,KAAK,EAAE,CAAC,CACxCG,IAAI,CAAC,GAAG,CAAC;EACd;EAEA,OAAeb,kBAAkBA,
|
|
1
|
+
{"version":3,"names":["HmacSHA256","Hex","SecureHashUtil","clearSecureHash","secretKey","data","secureHashValue","concatenatedString","composeData","generateSecureHash","requestParameters","Object","entries","sort","keyA","keyB","localeCompare","filter","_","value","map","key","join","message","keyBytes","match","byte","parseInt","Error","keyHex","toString","padStart","hash","parse","toUpperCase","e","console","error"],"sourceRoot":"../../../src","sources":["utils/SecureHashUtil.ts"],"mappings":";;AAAA,OAAOA,UAAU,MAAM,uBAAuB;AAC9C,OAAOC,GAAG,MAAM,mBAAmB;AAInC,MAAMC,cAAc,CAAC;EACnB,OAAOC,eAAeA,CAACC,SAAiB,EAAEC,IAAa,EAAU;IAC/D,OAAOA,IAAI,CAACC,eAAe;IAC3B,MAAMC,kBAAkB,GAAG,IAAI,CAACC,WAAW,CAACH,IAAI,CAAC;IACjD,OAAO,IAAI,CAACI,kBAAkB,CAACF,kBAAkB,EAAEH,SAAS,CAAC;EAC/D;EAEA,OAAeI,WAAWA,CAACE,iBAA0B,EAAU;IAC7D,OAAOC,MAAM,CAACC,OAAO,CAACF,iBAAiB,CAAC,CACrCG,IAAI,CAAC,CAAC,CAACC,IAAI,CAAC,EAAE,CAACC,IAAI,CAAC,KAAKD,IAAI,CAACE,aAAa,CAACD,IAAI,CAAC,CAAC,CAClDE,MAAM,CAAC,CAAC,CAACC,CAAC,EAAEC,KAAK,CAAC,KAAKA,KAAK,IAAI,IAAI,IAAIA,KAAK,KAAK,EAAE,CAAC,CACrDC,GAAG,CAAC,CAAC,CAACC,GAAG,EAAEF,KAAK,CAAC,KAAK,GAAGE,GAAG,IAAIF,KAAK,EAAE,CAAC,CACxCG,IAAI,CAAC,GAAG,CAAC;EACd;EAEA,OAAeb,kBAAkBA,CAC/Bc,OAAe,EACfnB,SAAiB,EACT;IACR,IAAI;MACF;MACA,MAAMoB,QAAQ,GAAGpB,SAAS,CACvBqB,KAAK,CAAC,OAAO,CAAC,EACbL,GAAG,CAAEM,IAAI,IAAKC,QAAQ,CAACD,IAAI,EAAE,EAAE,CAAC,CAAC;MAErC,IAAI,CAACF,QAAQ,EAAE;QACb,MAAM,IAAII,KAAK,CAAC,2BAA2B,CAAC;MAC9C;;MAEA;MACA,MAAMC,MAAM,GAAGL,QAAQ,CACpBJ,GAAG,CAAEM,IAAI,IAAKA,IAAI,CAACI,QAAQ,CAAC,EAAE,CAAC,CAACC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CACjDT,IAAI,CAAC,EAAE,CAAC;;MAEX;MACA,MAAMU,IAAI,GAAGhC,UAAU,CAACuB,OAAO,EAAEtB,GAAG,CAACgC,KAAK,CAACJ,MAAM,CAAC,CAAC;;MAEnD;MACA,OAAOG,IAAI,CAACF,QAAQ,CAAC7B,GAAG,CAAC,CAACiC,WAAW,CAAC,CAAC;IACzC,CAAC,CAAC,OAAOC,CAAC,EAAE;MACVC,OAAO,CAACC,KAAK,CAAC,+BAA+B,EAAEF,CAAC,CAAC;MACjD,OAAO,EAAE;IACX;EACF;AACF;AAEA,eAAejC,cAAc","ignoreList":[]}
|
|
@@ -12,7 +12,8 @@ export class UuidUtil {
|
|
|
12
12
|
*/
|
|
13
13
|
static generateV4() {
|
|
14
14
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
|
15
|
-
const r = Math.random() * 16
|
|
15
|
+
const r = Math.floor(Math.random() * 16);
|
|
16
|
+
// eslint-disable-next-line no-bitwise
|
|
16
17
|
const v = c === 'x' ? r : r & 0x3 | 0x8;
|
|
17
18
|
return v.toString(16);
|
|
18
19
|
}).toLowerCase();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["UuidUtil","generateV4","replace","c","r","Math","random","v","toString","toLowerCase","generateTransactionId"],"sourceRoot":"../../../src","sources":["utils/UuidUtil.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA,OAAO,MAAMA,QAAQ,CAAC;EACpB;AACF;AACA;AACA;AACA;EACE,OAAOC,UAAUA,CAAA,EAAW;IAC1B,OAAO,sCAAsC,
|
|
1
|
+
{"version":3,"names":["UuidUtil","generateV4","replace","c","r","Math","floor","random","v","toString","toLowerCase","generateTransactionId"],"sourceRoot":"../../../src","sources":["utils/UuidUtil.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA,OAAO,MAAMA,QAAQ,CAAC;EACpB;AACF;AACA;AACA;AACA;EACE,OAAOC,UAAUA,CAAA,EAAW;IAC1B,OAAO,sCAAsC,CAC1CC,OAAO,CAAC,OAAO,EAAGC,CAAC,IAAK;MACvB,MAAMC,CAAC,GAAGC,IAAI,CAACC,KAAK,CAACD,IAAI,CAACE,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;MACxC;MACA,MAAMC,CAAC,GAAGL,CAAC,KAAK,GAAG,GAAGC,CAAC,GAAIA,CAAC,GAAG,GAAG,GAAI,GAAG;MACzC,OAAOI,CAAC,CAACC,QAAQ,CAAC,EAAE,CAAC;IACvB,CAAC,CAAC,CACDC,WAAW,CAAC,CAAC;EAClB;;EAEA;AACF;AACA;AACA;EACE,OAAOC,qBAAqBA,CAAA,EAAW;IACrC,OAAOX,QAAQ,CAACC,UAAU,CAAC,CAAC;EAC9B;AACF","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AmwalPaySDK.d.ts","sourceRoot":"","sources":["../../../src/AmwalPaySDK.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"AmwalPaySDK.d.ts","sourceRoot":"","sources":["../../../src/AmwalPaySDK.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,SAAS,CAAC;AAIjB,cAAM,WAAW;IACf,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAc;IAErC,OAAO,CAAC,sBAAsB,CAAkC;IAEhE,OAAO,CAAC,wBAAwB,CAAkC;IAElE,OAAO;IAIP,MAAM,CAAC,WAAW,IAAI,WAAW;IAOjC;;;OAGG;IACG,YAAY,CAChB,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,cAAc,CAAC,GAC3C,OAAO,CAAC,IAAI,CAAC;IA4ChB,OAAO,IAAI,IAAI;IAKf;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAuC3B;;OAEG;IACH,OAAO,CAAC,oBAAoB;CAM7B;AAED,eAAe,WAAW,CAAC"}
|
|
@@ -17,23 +17,64 @@ export interface AmwalPayResponse {
|
|
|
17
17
|
message: string;
|
|
18
18
|
data?: Object;
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Configuration interface for Amwal Pay SDK
|
|
22
|
+
*
|
|
23
|
+
* @interface AmwalPayConfig
|
|
24
|
+
* @description Complete configuration for initializing and starting a payment session
|
|
25
|
+
*/
|
|
20
26
|
export interface AmwalPayConfig {
|
|
27
|
+
/** Target environment (SIT, UAT, or PROD) */
|
|
21
28
|
environment: Environment;
|
|
29
|
+
/** Secure hash for authentication */
|
|
22
30
|
secureHash: string;
|
|
31
|
+
/** Transaction currency */
|
|
23
32
|
currency: Currency;
|
|
33
|
+
/** Transaction amount as string (e.g., "100.000") */
|
|
24
34
|
amount: string;
|
|
35
|
+
/** Merchant identifier */
|
|
25
36
|
merchantId: string;
|
|
37
|
+
/** Terminal identifier */
|
|
26
38
|
terminalId: string;
|
|
39
|
+
/** Locale for UI language ('en' or 'ar') */
|
|
27
40
|
locale: string;
|
|
41
|
+
/** Optional customer identifier */
|
|
28
42
|
customerId: string | null;
|
|
43
|
+
/** Type of transaction (NFC, CARD_WALLET, APPLE_PAY) */
|
|
29
44
|
transactionType: TransactionType;
|
|
45
|
+
/** Optional session token (auto-fetched if not provided) */
|
|
30
46
|
sessionToken?: string;
|
|
47
|
+
/** Optional transaction ID (auto-generated if not provided) */
|
|
31
48
|
transactionId?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Optional additional configuration values
|
|
51
|
+
*
|
|
52
|
+
* Supported keys:
|
|
53
|
+
* - `useBottomSheetDesign`: 'true' | 'false' - Use bottom sheet design (v2) instead of full screen
|
|
54
|
+
* - `ignoreReceipt`: 'true' | 'false' - Skip receipt display after transaction
|
|
55
|
+
* - `primaryColor`: Hex color string (e.g., '#FF5733') - Primary theme color
|
|
56
|
+
* - `secondaryColor`: Hex color string (e.g., '#33FF57') - Secondary theme color
|
|
57
|
+
* - `merchantIdentifier`: String - Apple Pay merchant identifier (default: 'merchant.applepay.amwalpay')
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* additionValues: {
|
|
62
|
+
* useBottomSheetDesign: 'true',
|
|
63
|
+
* primaryColor: '#1E88E5',
|
|
64
|
+
* secondaryColor: '#FFC107',
|
|
65
|
+
* ignoreReceipt: 'false',
|
|
66
|
+
* merchantIdentifier: 'merchant.applepay.amwalpay'
|
|
67
|
+
* }
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
32
70
|
additionValues?: {
|
|
33
71
|
[key: string]: string;
|
|
34
72
|
};
|
|
73
|
+
/** Optional merchant reference for transaction tracking */
|
|
35
74
|
merchantReference?: string;
|
|
75
|
+
/** Callback for payment response */
|
|
36
76
|
onResponse: (response: AmwalPayResponse) => void;
|
|
77
|
+
/** Callback for customer ID updates */
|
|
37
78
|
onCustomerId: (customerId: string) => void;
|
|
38
79
|
}
|
|
39
80
|
export interface AmwalPayNativeConfig {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeReactAmwalPay.d.ts","sourceRoot":"","sources":["../../../src/NativeReactAmwalPay.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,oBAAY,WAAW;IACrB,GAAG,QAAQ;IACX,GAAG,QAAQ;IACX,IAAI,SAAS;CACd;AAED,oBAAY,QAAQ;IAClB,GAAG,QAAQ;CACZ;AAED,oBAAY,eAAe;IACzB,GAAG,QAAQ;IACX,WAAW,gBAAgB;IAC3B,SAAS,cAAc;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;
|
|
1
|
+
{"version":3,"file":"NativeReactAmwalPay.d.ts","sourceRoot":"","sources":["../../../src/NativeReactAmwalPay.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,oBAAY,WAAW;IACrB,GAAG,QAAQ;IACX,GAAG,QAAQ;IACX,IAAI,SAAS;CACd;AAED,oBAAY,QAAQ;IAClB,GAAG,QAAQ;CACZ;AAED,oBAAY,eAAe;IACzB,GAAG,QAAQ;IACX,WAAW,gBAAgB;IAC3B,SAAS,cAAc;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,6CAA6C;IAC7C,WAAW,EAAE,WAAW,CAAC;IACzB,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,QAAQ,EAAE,QAAQ,CAAC;IACnB,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,0BAA0B;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,wDAAwD;IACxD,eAAe,EAAE,eAAe,CAAC;IACjC,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,cAAc,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAC3C,2DAA2D;IAC3D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oCAAoC;IACpC,UAAU,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACjD,uCAAuC;IACvC,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAGD,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAC3C,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,IAAK,SAAQ,WAAW;IAEvC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC7C,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;;AAED,wBAAuE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAsB,EACpB,WAAW,EACX,QAAQ,EACR,eAAe,EACf,KAAK,gBAAgB,EACrB,KAAK,cAAc,EAEpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAsB,EACpB,WAAW,EACX,QAAQ,EACR,eAAe,EACf,KAAK,gBAAgB,EACrB,KAAK,cAAc,EAEpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAsB,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAK1E,wBAAgB,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CA6BrD;AAED,wBAAgB,UAAU,CACxB,QAAQ,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,GAC7C,iBAAiB,CAEnB;AACD,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,GACrC,iBAAiB,CAEnB;AAED,OAAO,EACL,WAAW,EACX,QAAQ,EACR,eAAe,EACf,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,WAAW,EACX,QAAQ,GACT,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NetworkClient.d.ts","sourceRoot":"","sources":["../../../../src/network/NetworkClient.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAGrD,cAAM,aAAa;IACjB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAgB;IAEvC,OAAO;IAEP,MAAM,CAAC,WAAW,IAAI,aAAa;IAOnC,OAAO,CAAC,aAAa;IAaf,iBAAiB,CACrB,GAAG,EAAE,WAAW,EAChB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"NetworkClient.d.ts","sourceRoot":"","sources":["../../../../src/network/NetworkClient.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAGrD,cAAM,aAAa;IACjB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAgB;IAEvC,OAAO;IAEP,MAAM,CAAC,WAAW,IAAI,aAAa;IAOnC,OAAO,CAAC,aAAa;IAaf,iBAAiB,CACrB,GAAG,EAAE,WAAW,EAChB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA+CzB,OAAO,CAAC,eAAe;CAGxB;AAED,eAAe,aAAa,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SecureHashUtil.d.ts","sourceRoot":"","sources":["../../../../src/utils/SecureHashUtil.ts"],"names":[],"mappings":"AAGA,KAAK,OAAO,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAEhD,cAAM,cAAc;IAClB,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM;IAMhE,OAAO,CAAC,MAAM,CAAC,WAAW;IAQ1B,OAAO,CAAC,MAAM,CAAC,kBAAkB;
|
|
1
|
+
{"version":3,"file":"SecureHashUtil.d.ts","sourceRoot":"","sources":["../../../../src/utils/SecureHashUtil.ts"],"names":[],"mappings":"AAGA,KAAK,OAAO,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAEhD,cAAM,cAAc;IAClB,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM;IAMhE,OAAO,CAAC,MAAM,CAAC,WAAW;IAQ1B,OAAO,CAAC,MAAM,CAAC,kBAAkB;CA6BlC;AAED,eAAe,cAAc,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UuidUtil.d.ts","sourceRoot":"","sources":["../../../../src/utils/UuidUtil.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,QAAQ;IACnB;;;;OAIG;IACH,MAAM,CAAC,UAAU,IAAI,MAAM;
|
|
1
|
+
{"version":3,"file":"UuidUtil.d.ts","sourceRoot":"","sources":["../../../../src/utils/UuidUtil.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,QAAQ;IACnB;;;;OAIG;IACH,MAAM,CAAC,UAAU,IAAI,MAAM;IAW3B;;;OAGG;IACH,MAAM,CAAC,qBAAqB,IAAI,MAAM;CAGvC"}
|
package/package.json
CHANGED
package/src/AmwalPaySDK.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
initiate,
|
|
3
|
+
onCustomerId,
|
|
4
|
+
onResponse,
|
|
5
|
+
type AmwalPayConfig,
|
|
6
|
+
} from './index';
|
|
2
7
|
import NetworkClient from './network/NetworkClient';
|
|
3
8
|
import { type EventSubscription } from 'react-native';
|
|
4
9
|
|
|
5
|
-
|
|
6
10
|
class AmwalPaySDK {
|
|
7
11
|
private static instance: AmwalPaySDK;
|
|
8
12
|
|
|
@@ -12,7 +16,6 @@ class AmwalPaySDK {
|
|
|
12
16
|
|
|
13
17
|
private constructor() {
|
|
14
18
|
// Initialize the event emitter
|
|
15
|
-
|
|
16
19
|
}
|
|
17
20
|
|
|
18
21
|
static getInstance(): AmwalPaySDK {
|
|
@@ -26,7 +29,9 @@ class AmwalPaySDK {
|
|
|
26
29
|
* Initiates the payment process by first fetching a session token and then starting the payment flow
|
|
27
30
|
* @param config The payment configuration
|
|
28
31
|
*/
|
|
29
|
-
async startPayment(
|
|
32
|
+
async startPayment(
|
|
33
|
+
config: Omit<AmwalPayConfig, 'sessionToken'>
|
|
34
|
+
): Promise<void> {
|
|
30
35
|
try {
|
|
31
36
|
// Set up event listeners before starting the payment process
|
|
32
37
|
this.setupEventListeners(config);
|
|
@@ -35,7 +40,10 @@ class AmwalPaySDK {
|
|
|
35
40
|
const networkClient = NetworkClient.getInstance();
|
|
36
41
|
|
|
37
42
|
// Fetch session token
|
|
38
|
-
console.log(
|
|
43
|
+
console.log(
|
|
44
|
+
'Fetching session token for environment:',
|
|
45
|
+
config.environment
|
|
46
|
+
);
|
|
39
47
|
const sessionToken = await networkClient.fetchSessionToken(
|
|
40
48
|
config.environment,
|
|
41
49
|
config.merchantId,
|
|
@@ -53,11 +61,14 @@ class AmwalPaySDK {
|
|
|
53
61
|
// Create complete config with session token
|
|
54
62
|
const completeConfig: AmwalPayConfig = {
|
|
55
63
|
...config,
|
|
56
|
-
sessionToken
|
|
64
|
+
sessionToken,
|
|
57
65
|
};
|
|
58
66
|
|
|
59
67
|
// Initiate the payment process
|
|
60
|
-
console.log(
|
|
68
|
+
console.log(
|
|
69
|
+
'Initiating native payment with config:',
|
|
70
|
+
JSON.stringify(completeConfig)
|
|
71
|
+
);
|
|
61
72
|
initiate(completeConfig);
|
|
62
73
|
} catch (error) {
|
|
63
74
|
console.error('Error starting payment:', error);
|
|
@@ -73,13 +84,21 @@ class AmwalPaySDK {
|
|
|
73
84
|
* Sets up event listeners for AmwalPay events
|
|
74
85
|
* @param config The payment configuration containing callback functions
|
|
75
86
|
*/
|
|
76
|
-
private setupEventListeners(
|
|
87
|
+
private setupEventListeners(
|
|
88
|
+
config: Omit<AmwalPayConfig, 'sessionToken'>
|
|
89
|
+
): void {
|
|
77
90
|
// Remove any existing listeners
|
|
78
91
|
this.removeEventListeners();
|
|
79
92
|
|
|
80
93
|
console.log('🟢 Setting up event listeners...');
|
|
81
|
-
console.log(
|
|
82
|
-
|
|
94
|
+
console.log(
|
|
95
|
+
'🟢 onResponse callback exists?',
|
|
96
|
+
typeof config.onResponse === 'function'
|
|
97
|
+
);
|
|
98
|
+
console.log(
|
|
99
|
+
'🟢 onCustomerId callback exists?',
|
|
100
|
+
typeof config.onCustomerId === 'function'
|
|
101
|
+
);
|
|
83
102
|
|
|
84
103
|
this.onResponseSubscription = onResponse((response) => {
|
|
85
104
|
console.log('🟢 SDK onResponse listener triggered with:', response);
|
|
@@ -115,4 +134,4 @@ class AmwalPaySDK {
|
|
|
115
134
|
}
|
|
116
135
|
}
|
|
117
136
|
|
|
118
|
-
export default AmwalPaySDK;
|
|
137
|
+
export default AmwalPaySDK;
|
|
@@ -4,7 +4,7 @@ import { TurboModuleRegistry } from 'react-native';
|
|
|
4
4
|
export enum Environment {
|
|
5
5
|
SIT = 'SIT',
|
|
6
6
|
UAT = 'UAT',
|
|
7
|
-
PROD = 'PROD'
|
|
7
|
+
PROD = 'PROD',
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export enum Currency {
|
|
@@ -14,7 +14,7 @@ export enum Currency {
|
|
|
14
14
|
export enum TransactionType {
|
|
15
15
|
NFC = 'NFC',
|
|
16
16
|
CARD_WALLET = 'CARD_WALLET',
|
|
17
|
-
APPLE_PAY = 'APPLE_PAY'
|
|
17
|
+
APPLE_PAY = 'APPLE_PAY',
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export interface AmwalPayResponse {
|
|
@@ -23,22 +23,62 @@ export interface AmwalPayResponse {
|
|
|
23
23
|
data?: Object; // Changed from 'any' to 'Object'
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Configuration interface for Amwal Pay SDK
|
|
28
|
+
*
|
|
29
|
+
* @interface AmwalPayConfig
|
|
30
|
+
* @description Complete configuration for initializing and starting a payment session
|
|
31
|
+
*/
|
|
27
32
|
export interface AmwalPayConfig {
|
|
33
|
+
/** Target environment (SIT, UAT, or PROD) */
|
|
28
34
|
environment: Environment;
|
|
35
|
+
/** Secure hash for authentication */
|
|
29
36
|
secureHash: string;
|
|
37
|
+
/** Transaction currency */
|
|
30
38
|
currency: Currency;
|
|
39
|
+
/** Transaction amount as string (e.g., "100.000") */
|
|
31
40
|
amount: string;
|
|
41
|
+
/** Merchant identifier */
|
|
32
42
|
merchantId: string;
|
|
43
|
+
/** Terminal identifier */
|
|
33
44
|
terminalId: string;
|
|
45
|
+
/** Locale for UI language ('en' or 'ar') */
|
|
34
46
|
locale: string;
|
|
47
|
+
/** Optional customer identifier */
|
|
35
48
|
customerId: string | null;
|
|
49
|
+
/** Type of transaction (NFC, CARD_WALLET, APPLE_PAY) */
|
|
36
50
|
transactionType: TransactionType;
|
|
51
|
+
/** Optional session token (auto-fetched if not provided) */
|
|
37
52
|
sessionToken?: string;
|
|
53
|
+
/** Optional transaction ID (auto-generated if not provided) */
|
|
38
54
|
transactionId?: string;
|
|
55
|
+
/**
|
|
56
|
+
* Optional additional configuration values
|
|
57
|
+
*
|
|
58
|
+
* Supported keys:
|
|
59
|
+
* - `useBottomSheetDesign`: 'true' | 'false' - Use bottom sheet design (v2) instead of full screen
|
|
60
|
+
* - `ignoreReceipt`: 'true' | 'false' - Skip receipt display after transaction
|
|
61
|
+
* - `primaryColor`: Hex color string (e.g., '#FF5733') - Primary theme color
|
|
62
|
+
* - `secondaryColor`: Hex color string (e.g., '#33FF57') - Secondary theme color
|
|
63
|
+
* - `merchantIdentifier`: String - Apple Pay merchant identifier (default: 'merchant.applepay.amwalpay')
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* additionValues: {
|
|
68
|
+
* useBottomSheetDesign: 'true',
|
|
69
|
+
* primaryColor: '#1E88E5',
|
|
70
|
+
* secondaryColor: '#FFC107',
|
|
71
|
+
* ignoreReceipt: 'false',
|
|
72
|
+
* merchantIdentifier: 'merchant.applepay.amwalpay'
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
39
76
|
additionValues?: { [key: string]: string };
|
|
77
|
+
/** Optional merchant reference for transaction tracking */
|
|
40
78
|
merchantReference?: string;
|
|
79
|
+
/** Callback for payment response */
|
|
41
80
|
onResponse: (response: AmwalPayResponse) => void;
|
|
81
|
+
/** Callback for customer ID updates */
|
|
42
82
|
onCustomerId: (customerId: string) => void;
|
|
43
83
|
}
|
|
44
84
|
|
package/src/index.tsx
CHANGED
|
@@ -8,10 +8,7 @@ import ReactAmwalPay, {
|
|
|
8
8
|
} from './NativeReactAmwalPay';
|
|
9
9
|
import AmwalPaySDK from './AmwalPaySDK';
|
|
10
10
|
import { UuidUtil } from './utils/UuidUtil';
|
|
11
|
-
import {
|
|
12
|
-
NativeEventEmitter,
|
|
13
|
-
type EventSubscription,
|
|
14
|
-
} from 'react-native';
|
|
11
|
+
import { NativeEventEmitter, type EventSubscription } from 'react-native';
|
|
15
12
|
|
|
16
13
|
// Create an event emitter for the native module
|
|
17
14
|
const eventEmitter = new NativeEventEmitter(ReactAmwalPay as any);
|
|
@@ -47,10 +44,14 @@ export function initiate(config: AmwalPayConfig): void {
|
|
|
47
44
|
ReactAmwalPay.initiate(nativeConfig);
|
|
48
45
|
}
|
|
49
46
|
|
|
50
|
-
export function onResponse(
|
|
47
|
+
export function onResponse(
|
|
48
|
+
callback: (response: AmwalPayResponse) => void
|
|
49
|
+
): EventSubscription {
|
|
51
50
|
return eventEmitter.addListener('onResponse', callback);
|
|
52
51
|
}
|
|
53
|
-
export function onCustomerId(
|
|
52
|
+
export function onCustomerId(
|
|
53
|
+
callback: (customerId: string) => void
|
|
54
|
+
): EventSubscription {
|
|
54
55
|
return eventEmitter.addListener('onCustomerId', callback);
|
|
55
56
|
}
|
|
56
57
|
|
|
@@ -1,84 +1,87 @@
|
|
|
1
|
-
import { Alert } from 'react-native';
|
|
2
|
-
import { Environment } from '../NativeReactAmwalPay';
|
|
3
|
-
import SecureHashUtil from '../utils/SecureHashUtil';
|
|
4
|
-
|
|
5
|
-
class NetworkClient {
|
|
6
|
-
private static instance: NetworkClient;
|
|
7
|
-
|
|
8
|
-
private constructor() {}
|
|
9
|
-
|
|
10
|
-
static getInstance(): NetworkClient {
|
|
11
|
-
if (!NetworkClient.instance) {
|
|
12
|
-
NetworkClient.instance = new NetworkClient();
|
|
13
|
-
}
|
|
14
|
-
return NetworkClient.instance;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
private getWebhookUrl(env: Environment): string {
|
|
18
|
-
switch (env) {
|
|
19
|
-
case Environment.SIT:
|
|
20
|
-
return 'https://test.amwalpg.com:24443/';
|
|
21
|
-
case Environment.UAT:
|
|
22
|
-
return 'https://test.amwalpg.com:14443/';
|
|
23
|
-
case Environment.PROD:
|
|
24
|
-
return 'https://webhook.amwalpg.com/';
|
|
25
|
-
default:
|
|
26
|
-
return 'https://test.amwalpg.com:24443/';
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async fetchSessionToken(
|
|
31
|
-
env: Environment,
|
|
32
|
-
merchantId: string,
|
|
33
|
-
customerId: string | null,
|
|
34
|
-
secureHashValue: string
|
|
35
|
-
): Promise<string | null> {
|
|
36
|
-
try {
|
|
37
|
-
const webhookUrl = this.getWebhookUrl(env);
|
|
38
|
-
|
|
39
|
-
const dataMap = {
|
|
40
|
-
merchantId,
|
|
41
|
-
customerId
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const secureHash = SecureHashUtil.clearSecureHash(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
'
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
1
|
+
import { Alert } from 'react-native';
|
|
2
|
+
import { Environment } from '../NativeReactAmwalPay';
|
|
3
|
+
import SecureHashUtil from '../utils/SecureHashUtil';
|
|
4
|
+
|
|
5
|
+
class NetworkClient {
|
|
6
|
+
private static instance: NetworkClient;
|
|
7
|
+
|
|
8
|
+
private constructor() {}
|
|
9
|
+
|
|
10
|
+
static getInstance(): NetworkClient {
|
|
11
|
+
if (!NetworkClient.instance) {
|
|
12
|
+
NetworkClient.instance = new NetworkClient();
|
|
13
|
+
}
|
|
14
|
+
return NetworkClient.instance;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
private getWebhookUrl(env: Environment): string {
|
|
18
|
+
switch (env) {
|
|
19
|
+
case Environment.SIT:
|
|
20
|
+
return 'https://test.amwalpg.com:24443/';
|
|
21
|
+
case Environment.UAT:
|
|
22
|
+
return 'https://test.amwalpg.com:14443/';
|
|
23
|
+
case Environment.PROD:
|
|
24
|
+
return 'https://webhook.amwalpg.com/';
|
|
25
|
+
default:
|
|
26
|
+
return 'https://test.amwalpg.com:24443/';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async fetchSessionToken(
|
|
31
|
+
env: Environment,
|
|
32
|
+
merchantId: string,
|
|
33
|
+
customerId: string | null,
|
|
34
|
+
secureHashValue: string
|
|
35
|
+
): Promise<string | null> {
|
|
36
|
+
try {
|
|
37
|
+
const webhookUrl = this.getWebhookUrl(env);
|
|
38
|
+
|
|
39
|
+
const dataMap = {
|
|
40
|
+
merchantId,
|
|
41
|
+
customerId,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const secureHash = SecureHashUtil.clearSecureHash(
|
|
45
|
+
secureHashValue,
|
|
46
|
+
dataMap
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const response = await fetch(
|
|
50
|
+
`${webhookUrl}Membership/GetSDKSessionToken`,
|
|
51
|
+
{
|
|
52
|
+
method: 'POST',
|
|
53
|
+
headers: {
|
|
54
|
+
'Accept': 'text/plain',
|
|
55
|
+
'Accept-Language': 'en-US,en;q=0.9',
|
|
56
|
+
'Content-Type': 'application/json',
|
|
57
|
+
},
|
|
58
|
+
body: JSON.stringify({
|
|
59
|
+
merchantId,
|
|
60
|
+
secureHashValue: secureHash,
|
|
61
|
+
customerId,
|
|
62
|
+
}),
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const responseData = await response.json();
|
|
67
|
+
|
|
68
|
+
if (response.ok && responseData.success) {
|
|
69
|
+
return responseData.data.sessionToken;
|
|
70
|
+
} else {
|
|
71
|
+
const errorMessage =
|
|
72
|
+
responseData.errorList?.join(',') || 'Unknown error';
|
|
73
|
+
this.showErrorDialog(errorMessage);
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
} catch (error) {
|
|
77
|
+
this.showErrorDialog('Something Went Wrong');
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private showErrorDialog(message: string): void {
|
|
83
|
+
Alert.alert('Error', message, [{ text: 'OK' }]);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export default NetworkClient;
|
|
@@ -1,45 +1,52 @@
|
|
|
1
|
-
import HmacSHA256 from 'crypto-js/hmac-sha256';
|
|
2
|
-
import Hex from 'crypto-js/enc-hex';
|
|
3
|
-
|
|
4
|
-
type DataMap = { [key: string]: string | null };
|
|
5
|
-
|
|
6
|
-
class SecureHashUtil {
|
|
7
|
-
static clearSecureHash(secretKey: string, data: DataMap): string {
|
|
8
|
-
delete data.secureHashValue;
|
|
9
|
-
const concatenatedString = this.composeData(data);
|
|
10
|
-
return this.generateSecureHash(concatenatedString, secretKey);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
private static composeData(requestParameters: DataMap): string {
|
|
14
|
-
return Object.entries(requestParameters)
|
|
15
|
-
.sort(([keyA], [keyB]) => keyA.localeCompare(keyB))
|
|
16
|
-
.filter(([_, value]) => value != null && value !== '')
|
|
17
|
-
.map(([key, value]) => `${key}=${value}`)
|
|
18
|
-
.join('&');
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
private static generateSecureHash(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
1
|
+
import HmacSHA256 from 'crypto-js/hmac-sha256';
|
|
2
|
+
import Hex from 'crypto-js/enc-hex';
|
|
3
|
+
|
|
4
|
+
type DataMap = { [key: string]: string | null };
|
|
5
|
+
|
|
6
|
+
class SecureHashUtil {
|
|
7
|
+
static clearSecureHash(secretKey: string, data: DataMap): string {
|
|
8
|
+
delete data.secureHashValue;
|
|
9
|
+
const concatenatedString = this.composeData(data);
|
|
10
|
+
return this.generateSecureHash(concatenatedString, secretKey);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
private static composeData(requestParameters: DataMap): string {
|
|
14
|
+
return Object.entries(requestParameters)
|
|
15
|
+
.sort(([keyA], [keyB]) => keyA.localeCompare(keyB))
|
|
16
|
+
.filter(([_, value]) => value != null && value !== '')
|
|
17
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
18
|
+
.join('&');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
private static generateSecureHash(
|
|
22
|
+
message: string,
|
|
23
|
+
secretKey: string
|
|
24
|
+
): string {
|
|
25
|
+
try {
|
|
26
|
+
// Convert hex string to byte array
|
|
27
|
+
const keyBytes = secretKey
|
|
28
|
+
.match(/.{2}/g)
|
|
29
|
+
?.map((byte) => parseInt(byte, 16));
|
|
30
|
+
|
|
31
|
+
if (!keyBytes) {
|
|
32
|
+
throw new Error('Invalid secret key format');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Convert key bytes to hex string for crypto-js
|
|
36
|
+
const keyHex = keyBytes
|
|
37
|
+
.map((byte) => byte.toString(16).padStart(2, '0'))
|
|
38
|
+
.join('');
|
|
39
|
+
|
|
40
|
+
// Generate HMAC-SHA256
|
|
41
|
+
const hash = HmacSHA256(message, Hex.parse(keyHex));
|
|
42
|
+
|
|
43
|
+
// Convert to uppercase hex string
|
|
44
|
+
return hash.toString(Hex).toUpperCase();
|
|
45
|
+
} catch (e) {
|
|
46
|
+
console.error('Error generating secure hash:', e);
|
|
47
|
+
return '';
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export default SecureHashUtil;
|
package/src/utils/UuidUtil.ts
CHANGED
|
@@ -9,11 +9,14 @@ export class UuidUtil {
|
|
|
9
9
|
* @returns A lowercase UUID string
|
|
10
10
|
*/
|
|
11
11
|
static generateV4(): string {
|
|
12
|
-
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
|
|
13
|
+
.replace(/[xy]/g, (c) => {
|
|
14
|
+
const r = Math.floor(Math.random() * 16);
|
|
15
|
+
// eslint-disable-next-line no-bitwise
|
|
16
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
17
|
+
return v.toString(16);
|
|
18
|
+
})
|
|
19
|
+
.toLowerCase();
|
|
17
20
|
}
|
|
18
21
|
|
|
19
22
|
/**
|
|
@@ -23,4 +26,4 @@ export class UuidUtil {
|
|
|
23
26
|
static generateTransactionId(): string {
|
|
24
27
|
return UuidUtil.generateV4();
|
|
25
28
|
}
|
|
26
|
-
}
|
|
29
|
+
}
|