react-amwal-pay 0.1.8 → 0.1.10
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 +182 -128
- package/ReactAmwalPay.podspec +23 -23
- package/android/build.gradle +93 -93
- package/ios/ReactAmwalPay.m +14 -14
- package/ios/ReactAmwalPay.swift +111 -111
- 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 +13 -2
- 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/module/utils/UuidUtil.js +29 -0
- package/lib/module/utils/UuidUtil.js.map +1 -0
- package/lib/typescript/src/NativeReactAmwalPay.d.ts +8 -0
- package/lib/typescript/src/NativeReactAmwalPay.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/utils/UuidUtil.d.ts +18 -0
- package/lib/typescript/src/utils/UuidUtil.d.ts.map +1 -0
- package/package.json +173 -173
- package/src/AmwalPaySDK.ts +97 -97
- package/src/NativeReactAmwalPay.ts +4 -0
- package/src/index.tsx +14 -0
- package/src/network/NetworkClient.ts +83 -83
- package/src/utils/SecureHashUtil.ts +44 -44
- package/src/utils/UuidUtil.ts +26 -0
|
@@ -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;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UUID utility for generating unique transaction IDs
|
|
3
|
+
* Similar to Dart's Uuid().v1() but using standard UUID v4 format
|
|
4
|
+
*/
|
|
5
|
+
export class UuidUtil {
|
|
6
|
+
/**
|
|
7
|
+
* Generates a UUID v4 string (random-based)
|
|
8
|
+
* This provides similar functionality to Dart's Uuid().v1()
|
|
9
|
+
* @returns A lowercase UUID string
|
|
10
|
+
*/
|
|
11
|
+
static generateV4(): string {
|
|
12
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
13
|
+
const r = (Math.random() * 16) | 0;
|
|
14
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
15
|
+
return v.toString(16);
|
|
16
|
+
}).toLowerCase();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Generates a transaction ID for Amwal payments
|
|
21
|
+
* @returns A lowercase UUID string suitable for transaction identification
|
|
22
|
+
*/
|
|
23
|
+
static generateTransactionId(): string {
|
|
24
|
+
return UuidUtil.generateV4();
|
|
25
|
+
}
|
|
26
|
+
}
|