react-amwal-pay 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -5
- package/ReactAmwalPay.podspec +2 -1
- package/lib/AmwalPay.d.ts +47 -0
- package/lib/AmwalPay.js +63 -0
- package/lib/AmwalPay.js.map +1 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.js +4 -0
- package/lib/index.js.map +1 -0
- package/lib/module/AmwalPaySDK.js +8 -8
- package/lib/module/AmwalPaySDK.js.map +1 -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.map +1 -1
- package/lib/screens/PaymentScreen.d.ts +2 -0
- package/lib/screens/PaymentScreen.js +133 -0
- package/lib/screens/PaymentScreen.js.map +1 -0
- package/lib/services/NetworkClient.d.ts +10 -0
- package/lib/services/NetworkClient.js +65 -0
- package/lib/services/NetworkClient.js.map +1 -0
- package/lib/utils/SecureHashUtil.d.ts +9 -0
- package/lib/utils/SecureHashUtil.js +37 -0
- package/lib/utils/SecureHashUtil.js.map +1 -0
- package/package.json +1 -3
- package/src/AmwalPaySDK.ts +97 -97
- package/src/network/NetworkClient.ts +83 -83
- package/src/utils/SecureHashUtil.ts +44 -44
- package/android/build.gradle +0 -95
- package/android/gradle.properties +0 -5
- package/android/src/main/AndroidManifest.xml +0 -2
- package/android/src/main/java/com/reactamwalpay/ReactAmwalPayModule.kt +0 -115
- package/android/src/main/java/com/reactamwalpay/ReactAmwalPayPackage.kt +0 -33
- package/ios/ReactAmwalPay.h +0 -5
- package/ios/ReactAmwalPay.mm +0 -18
package/src/AmwalPaySDK.ts
CHANGED
|
@@ -1,98 +1,98 @@
|
|
|
1
|
-
import { initiate, onCustomerId, onResponse, type AmwalPayConfig } from './index';
|
|
2
|
-
import NetworkClient from './network/NetworkClient';
|
|
3
|
-
import { type EventSubscription } from 'react-native';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class AmwalPaySDK {
|
|
7
|
-
private static instance: AmwalPaySDK;
|
|
8
|
-
|
|
9
|
-
private onResponseSubscription: EventSubscription|null = null;
|
|
10
|
-
|
|
11
|
-
private onCustomerIdSubscription: EventSubscription|null = null;
|
|
12
|
-
|
|
13
|
-
private constructor() {
|
|
14
|
-
// Initialize the event emitter
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
static getInstance(): AmwalPaySDK {
|
|
19
|
-
if (!AmwalPaySDK.instance) {
|
|
20
|
-
AmwalPaySDK.instance = new AmwalPaySDK();
|
|
21
|
-
}
|
|
22
|
-
return AmwalPaySDK.instance;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Initiates the payment process by first fetching a session token and then starting the payment flow
|
|
27
|
-
* @param config The payment configuration
|
|
28
|
-
*/
|
|
29
|
-
async startPayment(config: Omit<AmwalPayConfig, 'sessionToken'>): Promise<void> {
|
|
30
|
-
try {
|
|
31
|
-
// Set up event listeners before starting the payment process
|
|
32
|
-
this.setupEventListeners(config);
|
|
33
|
-
|
|
34
|
-
// Get network client instance
|
|
35
|
-
const networkClient = NetworkClient.getInstance();
|
|
36
|
-
|
|
37
|
-
// Fetch session token
|
|
38
|
-
const sessionToken = await networkClient.fetchSessionToken(
|
|
39
|
-
config.environment,
|
|
40
|
-
config.merchantId,
|
|
41
|
-
config.customerId,
|
|
42
|
-
config.secureHash
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
if (!sessionToken) {
|
|
46
|
-
// If session token is null, the error has already been shown by NetworkClient
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Create complete config with session token
|
|
51
|
-
const completeConfig: AmwalPayConfig = {
|
|
52
|
-
...config,
|
|
53
|
-
sessionToken
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
// Initiate the payment process
|
|
57
|
-
initiate(completeConfig);
|
|
58
|
-
} catch (error) {
|
|
59
|
-
console.error('Error starting payment:', error);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
dispose(): void {
|
|
64
|
-
// Remove all event listeners
|
|
65
|
-
this.removeEventListeners();
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Sets up event listeners for AmwalPay events
|
|
70
|
-
* @param config The payment configuration containing callback functions
|
|
71
|
-
*/
|
|
72
|
-
private setupEventListeners(config: Omit<AmwalPayConfig, 'sessionToken'>): void {
|
|
73
|
-
// Remove any existing listeners
|
|
74
|
-
this.removeEventListeners();
|
|
75
|
-
|
|
76
|
-
this.onResponseSubscription = onResponse((response) => {
|
|
77
|
-
console.log('Received AmwalPayResponse:', response);
|
|
78
|
-
config.onResponse(response);
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
this.onCustomerIdSubscription = onCustomerId((customerId) => {
|
|
82
|
-
console.log('Received customerId:', customerId);
|
|
83
|
-
config.onCustomerId(customerId);
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Removes all event listeners
|
|
89
|
-
*/
|
|
90
|
-
private removeEventListeners(): void {
|
|
91
|
-
this.onResponseSubscription?.remove();
|
|
92
|
-
this.onCustomerIdSubscription?.remove();
|
|
93
|
-
this.onResponseSubscription = null;
|
|
94
|
-
this.onCustomerIdSubscription = null;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
1
|
+
import { initiate, onCustomerId, onResponse, type AmwalPayConfig } from './index';
|
|
2
|
+
import NetworkClient from './network/NetworkClient';
|
|
3
|
+
import { type EventSubscription } from 'react-native';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AmwalPaySDK {
|
|
7
|
+
private static instance: AmwalPaySDK;
|
|
8
|
+
|
|
9
|
+
private onResponseSubscription: EventSubscription|null = null;
|
|
10
|
+
|
|
11
|
+
private onCustomerIdSubscription: EventSubscription|null = null;
|
|
12
|
+
|
|
13
|
+
private constructor() {
|
|
14
|
+
// Initialize the event emitter
|
|
15
|
+
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static getInstance(): AmwalPaySDK {
|
|
19
|
+
if (!AmwalPaySDK.instance) {
|
|
20
|
+
AmwalPaySDK.instance = new AmwalPaySDK();
|
|
21
|
+
}
|
|
22
|
+
return AmwalPaySDK.instance;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Initiates the payment process by first fetching a session token and then starting the payment flow
|
|
27
|
+
* @param config The payment configuration
|
|
28
|
+
*/
|
|
29
|
+
async startPayment(config: Omit<AmwalPayConfig, 'sessionToken'>): Promise<void> {
|
|
30
|
+
try {
|
|
31
|
+
// Set up event listeners before starting the payment process
|
|
32
|
+
this.setupEventListeners(config);
|
|
33
|
+
|
|
34
|
+
// Get network client instance
|
|
35
|
+
const networkClient = NetworkClient.getInstance();
|
|
36
|
+
|
|
37
|
+
// Fetch session token
|
|
38
|
+
const sessionToken = await networkClient.fetchSessionToken(
|
|
39
|
+
config.environment,
|
|
40
|
+
config.merchantId,
|
|
41
|
+
config.customerId,
|
|
42
|
+
config.secureHash
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
if (!sessionToken) {
|
|
46
|
+
// If session token is null, the error has already been shown by NetworkClient
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Create complete config with session token
|
|
51
|
+
const completeConfig: AmwalPayConfig = {
|
|
52
|
+
...config,
|
|
53
|
+
sessionToken
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// Initiate the payment process
|
|
57
|
+
initiate(completeConfig);
|
|
58
|
+
} catch (error) {
|
|
59
|
+
console.error('Error starting payment:', error);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
dispose(): void {
|
|
64
|
+
// Remove all event listeners
|
|
65
|
+
this.removeEventListeners();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Sets up event listeners for AmwalPay events
|
|
70
|
+
* @param config The payment configuration containing callback functions
|
|
71
|
+
*/
|
|
72
|
+
private setupEventListeners(config: Omit<AmwalPayConfig, 'sessionToken'>): void {
|
|
73
|
+
// Remove any existing listeners
|
|
74
|
+
this.removeEventListeners();
|
|
75
|
+
|
|
76
|
+
this.onResponseSubscription = onResponse((response) => {
|
|
77
|
+
console.log('Received AmwalPayResponse:', response);
|
|
78
|
+
config.onResponse(response);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
this.onCustomerIdSubscription = onCustomerId((customerId) => {
|
|
82
|
+
console.log('Received customerId:', customerId);
|
|
83
|
+
config.onCustomerId(customerId);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Removes all event listeners
|
|
89
|
+
*/
|
|
90
|
+
private removeEventListeners(): void {
|
|
91
|
+
this.onResponseSubscription?.remove();
|
|
92
|
+
this.onCustomerIdSubscription?.remove();
|
|
93
|
+
this.onResponseSubscription = null;
|
|
94
|
+
this.onCustomerIdSubscription = null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
98
|
export default AmwalPaySDK;
|
|
@@ -1,84 +1,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(secureHashValue, dataMap);
|
|
45
|
-
|
|
46
|
-
const response = await fetch(`${webhookUrl}Membership/GetSDKSessionToken`, {
|
|
47
|
-
method: 'POST',
|
|
48
|
-
headers: {
|
|
49
|
-
'Accept': 'text/plain',
|
|
50
|
-
'Accept-Language': 'en-US,en;q=0.9',
|
|
51
|
-
'Content-Type': 'application/json',
|
|
52
|
-
},
|
|
53
|
-
body: JSON.stringify({
|
|
54
|
-
merchantId,
|
|
55
|
-
secureHashValue: secureHash,
|
|
56
|
-
customerId
|
|
57
|
-
})
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
const responseData = await response.json();
|
|
61
|
-
|
|
62
|
-
if (response.ok && responseData.success) {
|
|
63
|
-
return responseData.data.sessionToken;
|
|
64
|
-
} else {
|
|
65
|
-
const errorMessage = responseData.errorList?.join(',') || 'Unknown error';
|
|
66
|
-
this.showErrorDialog(errorMessage);
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
} catch (error) {
|
|
70
|
-
this.showErrorDialog('Something Went Wrong');
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
private showErrorDialog(message: string): void {
|
|
76
|
-
Alert.alert(
|
|
77
|
-
'Error',
|
|
78
|
-
message,
|
|
79
|
-
[{ text: 'OK' }]
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
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(secureHashValue, dataMap);
|
|
45
|
+
|
|
46
|
+
const response = await fetch(`${webhookUrl}Membership/GetSDKSessionToken`, {
|
|
47
|
+
method: 'POST',
|
|
48
|
+
headers: {
|
|
49
|
+
'Accept': 'text/plain',
|
|
50
|
+
'Accept-Language': 'en-US,en;q=0.9',
|
|
51
|
+
'Content-Type': 'application/json',
|
|
52
|
+
},
|
|
53
|
+
body: JSON.stringify({
|
|
54
|
+
merchantId,
|
|
55
|
+
secureHashValue: secureHash,
|
|
56
|
+
customerId
|
|
57
|
+
})
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const responseData = await response.json();
|
|
61
|
+
|
|
62
|
+
if (response.ok && responseData.success) {
|
|
63
|
+
return responseData.data.sessionToken;
|
|
64
|
+
} else {
|
|
65
|
+
const errorMessage = responseData.errorList?.join(',') || 'Unknown error';
|
|
66
|
+
this.showErrorDialog(errorMessage);
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
} catch (error) {
|
|
70
|
+
this.showErrorDialog('Something Went Wrong');
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private showErrorDialog(message: string): void {
|
|
76
|
+
Alert.alert(
|
|
77
|
+
'Error',
|
|
78
|
+
message,
|
|
79
|
+
[{ text: 'OK' }]
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
84
|
export default NetworkClient;
|
|
@@ -1,45 +1,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(message: string, secretKey: string): string {
|
|
22
|
-
try {
|
|
23
|
-
// Convert hex string to byte array
|
|
24
|
-
const keyBytes = secretKey.match(/.{2}/g)?.map(byte => parseInt(byte, 16));
|
|
25
|
-
|
|
26
|
-
if (!keyBytes) {
|
|
27
|
-
throw new Error('Invalid secret key format');
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Convert key bytes to hex string for crypto-js
|
|
31
|
-
const keyHex = keyBytes.map(byte => byte.toString(16).padStart(2, '0')).join('');
|
|
32
|
-
|
|
33
|
-
// Generate HMAC-SHA256
|
|
34
|
-
const hash = HmacSHA256(message, Hex.parse(keyHex));
|
|
35
|
-
|
|
36
|
-
// Convert to uppercase hex string
|
|
37
|
-
return hash.toString(Hex).toUpperCase();
|
|
38
|
-
} catch (e) {
|
|
39
|
-
console.error('Error generating secure hash:', e);
|
|
40
|
-
return '';
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
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(message: string, secretKey: string): string {
|
|
22
|
+
try {
|
|
23
|
+
// Convert hex string to byte array
|
|
24
|
+
const keyBytes = secretKey.match(/.{2}/g)?.map(byte => parseInt(byte, 16));
|
|
25
|
+
|
|
26
|
+
if (!keyBytes) {
|
|
27
|
+
throw new Error('Invalid secret key format');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Convert key bytes to hex string for crypto-js
|
|
31
|
+
const keyHex = keyBytes.map(byte => byte.toString(16).padStart(2, '0')).join('');
|
|
32
|
+
|
|
33
|
+
// Generate HMAC-SHA256
|
|
34
|
+
const hash = HmacSHA256(message, Hex.parse(keyHex));
|
|
35
|
+
|
|
36
|
+
// Convert to uppercase hex string
|
|
37
|
+
return hash.toString(Hex).toUpperCase();
|
|
38
|
+
} catch (e) {
|
|
39
|
+
console.error('Error generating secure hash:', e);
|
|
40
|
+
return '';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
45
|
export default SecureHashUtil;
|
package/android/build.gradle
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
buildscript {
|
|
2
|
-
ext.getExtOrDefault = {name ->
|
|
3
|
-
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['ReactAmwalPay_' + name]
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
repositories {
|
|
7
|
-
google()
|
|
8
|
-
mavenCentral()
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
dependencies {
|
|
12
|
-
classpath "com.android.tools.build:gradle:8.7.3"
|
|
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
|
-
apply plugin: "com.facebook.react"
|
|
23
|
-
|
|
24
|
-
def getExtOrIntegerDefault(name) {
|
|
25
|
-
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["ReactAmwalPay_" + name]).toInteger()
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
android {
|
|
29
|
-
namespace "com.reactamwalpay"
|
|
30
|
-
|
|
31
|
-
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
32
|
-
|
|
33
|
-
defaultConfig {
|
|
34
|
-
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
35
|
-
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
buildFeatures {
|
|
39
|
-
buildConfig true
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
buildTypes {
|
|
43
|
-
release {
|
|
44
|
-
minifyEnabled false
|
|
45
|
-
shrinkResources false
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
lintOptions {
|
|
50
|
-
disable "GradleCompatible"
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
compileOptions {
|
|
54
|
-
sourceCompatibility JavaVersion.VERSION_1_8
|
|
55
|
-
targetCompatibility JavaVersion.VERSION_1_8
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
sourceSets {
|
|
59
|
-
main {
|
|
60
|
-
java.srcDirs += [
|
|
61
|
-
"generated/java",
|
|
62
|
-
"generated/jni"
|
|
63
|
-
]
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
repositories {
|
|
69
|
-
mavenCentral()
|
|
70
|
-
google()
|
|
71
|
-
}
|
|
72
|
-
rootProject.allprojects { Project subproject ->
|
|
73
|
-
subproject.repositories {
|
|
74
|
-
maven { url uri("E:/react_amwal_pay/android/repo") }
|
|
75
|
-
|
|
76
|
-
maven { url = uri("https://storage.googleapis.com/download.flutter.io") }
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
def kotlin_version = getExtOrDefault("kotlinVersion")
|
|
80
|
-
|
|
81
|
-
dependencies {
|
|
82
|
-
implementation "com.facebook.react:react-android"
|
|
83
|
-
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
84
|
-
implementation("com.amwal-pay:amwal_sdk:1.0.91"){
|
|
85
|
-
exclude group: 'com.android.support', module: 'support-v4'
|
|
86
|
-
exclude group: 'com.android.support', module: 'design'
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
react {
|
|
92
|
-
jsRootDir = file("../src/")
|
|
93
|
-
libraryName = "ReactAmwalPay"
|
|
94
|
-
codegenJavaPackageName = "com.reactamwalpay"
|
|
95
|
-
}
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
package com.reactamwalpay
|
|
2
|
-
|
|
3
|
-
import android.util.Log
|
|
4
|
-
import com.facebook.react.bridge.*
|
|
5
|
-
import com.facebook.react.module.annotations.ReactModule
|
|
6
|
-
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
7
|
-
import com.anwalpay.sdk.AmwalSDK
|
|
8
|
-
import org.json.JSONObject
|
|
9
|
-
|
|
10
|
-
@ReactModule(name = ReactAmwalPayModule.NAME)
|
|
11
|
-
class ReactAmwalPayModule(reactContext: ReactApplicationContext) :
|
|
12
|
-
NativeReactAmwalPaySpec(reactContext) {
|
|
13
|
-
|
|
14
|
-
private val amwalSDK = AmwalSDK()
|
|
15
|
-
|
|
16
|
-
override fun getName(): String {
|
|
17
|
-
return NAME
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
private fun sendEvent(eventName: String, params: WritableMap?) {
|
|
23
|
-
reactApplicationContext
|
|
24
|
-
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
25
|
-
.emit(eventName, params)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
override fun initiate(config: ReadableMap) {
|
|
29
|
-
Log.d(NAME, "initiate called")
|
|
30
|
-
val activity = reactApplicationContext.currentActivity
|
|
31
|
-
if (activity == null) {
|
|
32
|
-
// Since we can't use Promise here (method signature must match the spec),
|
|
33
|
-
// we'll send an error event
|
|
34
|
-
val params = Arguments.createMap()
|
|
35
|
-
params.putString("type", "onResponse")
|
|
36
|
-
val errorData = Arguments.createMap()
|
|
37
|
-
errorData.putString("status", "ERROR")
|
|
38
|
-
errorData.putString("message", "Activity context is not available")
|
|
39
|
-
params.putMap("data", errorData)
|
|
40
|
-
sendEvent("AmwalPayEvent", params)
|
|
41
|
-
return
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
Log.d(NAME, "initiate got here")
|
|
45
|
-
try {
|
|
46
|
-
val sdkConfig = AmwalSDK.Config(
|
|
47
|
-
environment = AmwalSDK.Config.Environment.valueOf(config.getString("environment") ?: ""),
|
|
48
|
-
sessionToken = config.getString("sessionToken") ?: "",
|
|
49
|
-
currency = AmwalSDK.Config.Currency.valueOf(config.getString("currency") ?: ""),
|
|
50
|
-
amount = config.getString("amount") ?: "",
|
|
51
|
-
merchantId = config.getString("merchantId") ?: "",
|
|
52
|
-
terminalId = config.getString("terminalId") ?: "",
|
|
53
|
-
locale = java.util.Locale(config.getString("locale") ?: "en"),
|
|
54
|
-
customerId = if (config.hasKey("customerId")) config.getString("customerId") else null,
|
|
55
|
-
transactionType = AmwalSDK.Config.TransactionType.valueOf(config.getString("transactionType") ?: "")
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
// Ensure this runs on the UI thread
|
|
59
|
-
(reactApplicationContext.currentActivity ?: return).runOnUiThread {
|
|
60
|
-
amwalSDK.start(
|
|
61
|
-
activity,
|
|
62
|
-
sdkConfig,
|
|
63
|
-
onResponse = {
|
|
64
|
-
Log.d(NAME, "onResponse called")
|
|
65
|
-
val params = Arguments.createMap()
|
|
66
|
-
try {
|
|
67
|
-
val json = JSONObject(it.toString())
|
|
68
|
-
val dataMap = jsonToWritableMap(json)
|
|
69
|
-
params.putMap("data", dataMap)
|
|
70
|
-
} catch (e: Exception) {
|
|
71
|
-
params.putString("data", it.toString())
|
|
72
|
-
}
|
|
73
|
-
emitOnResponse(params)
|
|
74
|
-
},
|
|
75
|
-
onCustomerId = {
|
|
76
|
-
Log.d(NAME, "onCustomerId called")
|
|
77
|
-
emitOnCustomerId(it)
|
|
78
|
-
}
|
|
79
|
-
)
|
|
80
|
-
}
|
|
81
|
-
} catch (e: Exception) {
|
|
82
|
-
Log.e(NAME, "Error initializing AmwalSDK", e)
|
|
83
|
-
val params = Arguments.createMap()
|
|
84
|
-
params.putString("type", "onResponse")
|
|
85
|
-
val errorData = Arguments.createMap()
|
|
86
|
-
errorData.putString("status", "ERROR")
|
|
87
|
-
errorData.putString("message", e.message ?: "Unknown error")
|
|
88
|
-
params.putMap("data", errorData)
|
|
89
|
-
sendEvent("AmwalPayEvent", params)
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Helper function to convert JSONObject to WritableMap
|
|
94
|
-
private fun jsonToWritableMap(jsonObject: JSONObject): WritableMap {
|
|
95
|
-
val map = Arguments.createMap()
|
|
96
|
-
val keys = jsonObject.keys()
|
|
97
|
-
while (keys.hasNext()) {
|
|
98
|
-
val key = keys.next()
|
|
99
|
-
val value = jsonObject.get(key)
|
|
100
|
-
when (value) {
|
|
101
|
-
is JSONObject -> map.putMap(key, jsonToWritableMap(value))
|
|
102
|
-
is Boolean -> map.putBoolean(key, value)
|
|
103
|
-
is Int -> map.putInt(key, value)
|
|
104
|
-
is Double -> map.putDouble(key, value)
|
|
105
|
-
is String -> map.putString(key, value)
|
|
106
|
-
else -> map.putString(key, value.toString())
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return map
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
companion object {
|
|
113
|
-
const val NAME = "ReactAmwalPay"
|
|
114
|
-
}
|
|
115
|
-
}
|