react-amwal-pay 0.1.16 → 0.1.18
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/ReactAmwalPay.podspec +2 -1
- package/android/build.gradle +1 -1
- package/android/gradle.properties +1 -1
- package/ios/ReactAmwalPay.swift +95 -345
- package/lib/module/AmwalPaySDK.js +57 -16
- package/lib/module/AmwalPaySDK.js.map +1 -1
- package/lib/module/index.js +2 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/network/NetworkClient.js +38 -11
- package/lib/module/network/NetworkClient.js.map +1 -1
- package/lib/module/utils/Logger.js +151 -0
- package/lib/module/utils/Logger.js.map +1 -0
- package/lib/typescript/src/AmwalPaySDK.d.ts +13 -0
- package/lib/typescript/src/AmwalPaySDK.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/network/NetworkClient.d.ts +1 -0
- package/lib/typescript/src/network/NetworkClient.d.ts.map +1 -1
- package/lib/typescript/src/utils/Logger.d.ts +76 -0
- package/lib/typescript/src/utils/Logger.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/AmwalPaySDK.ts +72 -28
- package/src/index.tsx +4 -0
- package/src/network/NetworkClient.ts +43 -11
- package/src/utils/Logger.ts +162 -0
package/src/AmwalPaySDK.ts
CHANGED
|
@@ -5,17 +5,21 @@ import {
|
|
|
5
5
|
type AmwalPayConfig,
|
|
6
6
|
} from './index';
|
|
7
7
|
import NetworkClient from './network/NetworkClient';
|
|
8
|
+
import Logger from './utils/Logger';
|
|
8
9
|
import { type EventSubscription } from 'react-native';
|
|
9
10
|
|
|
10
11
|
class AmwalPaySDK {
|
|
11
12
|
private static instance: AmwalPaySDK;
|
|
13
|
+
private logger: Logger;
|
|
12
14
|
|
|
13
15
|
private onResponseSubscription: EventSubscription | null = null;
|
|
14
16
|
|
|
15
17
|
private onCustomerIdSubscription: EventSubscription | null = null;
|
|
16
18
|
|
|
17
19
|
private constructor() {
|
|
18
|
-
// Initialize the
|
|
20
|
+
// Initialize the logger
|
|
21
|
+
this.logger = Logger.getInstance();
|
|
22
|
+
this.logger.info('AmwalPaySDK', 'SDK instance created');
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
static getInstance(): AmwalPaySDK {
|
|
@@ -25,6 +29,32 @@ class AmwalPaySDK {
|
|
|
25
29
|
return AmwalPaySDK.instance;
|
|
26
30
|
}
|
|
27
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Enable or disable debug logging
|
|
34
|
+
*/
|
|
35
|
+
setDebugEnabled(enabled: boolean): void {
|
|
36
|
+
this.logger.setDebugEnabled(enabled);
|
|
37
|
+
this.logger.info(
|
|
38
|
+
'AmwalPaySDK',
|
|
39
|
+
`Debug logging ${enabled ? 'enabled' : 'disabled'}`
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Get SDK logs for debugging purposes
|
|
45
|
+
*/
|
|
46
|
+
getLogs(): string {
|
|
47
|
+
return this.logger.exportLogs();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Clear all SDK logs
|
|
52
|
+
*/
|
|
53
|
+
clearLogs(): void {
|
|
54
|
+
this.logger.clearLogs();
|
|
55
|
+
this.logger.info('AmwalPaySDK', 'Logs cleared');
|
|
56
|
+
}
|
|
57
|
+
|
|
28
58
|
/**
|
|
29
59
|
* Initiates the payment process by first fetching a session token and then starting the payment flow
|
|
30
60
|
* @param config The payment configuration
|
|
@@ -33,6 +63,12 @@ class AmwalPaySDK {
|
|
|
33
63
|
config: Omit<AmwalPayConfig, 'sessionToken'>
|
|
34
64
|
): Promise<void> {
|
|
35
65
|
try {
|
|
66
|
+
this.logger.info('AmwalPaySDK', 'Starting payment process', {
|
|
67
|
+
merchantId: config.merchantId,
|
|
68
|
+
customerId: config.customerId,
|
|
69
|
+
environment: config.environment,
|
|
70
|
+
});
|
|
71
|
+
|
|
36
72
|
// Set up event listeners before starting the payment process
|
|
37
73
|
this.setupEventListeners(config);
|
|
38
74
|
|
|
@@ -40,10 +76,11 @@ class AmwalPaySDK {
|
|
|
40
76
|
const networkClient = NetworkClient.getInstance();
|
|
41
77
|
|
|
42
78
|
// Fetch session token
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
config.
|
|
46
|
-
);
|
|
79
|
+
this.logger.debug('AmwalPaySDK', 'Fetching session token', {
|
|
80
|
+
environment: config.environment,
|
|
81
|
+
merchantId: config.merchantId,
|
|
82
|
+
});
|
|
83
|
+
|
|
47
84
|
const sessionToken = await networkClient.fetchSessionToken(
|
|
48
85
|
config.environment,
|
|
49
86
|
config.merchantId,
|
|
@@ -51,13 +88,13 @@ class AmwalPaySDK {
|
|
|
51
88
|
config.secureHash
|
|
52
89
|
);
|
|
53
90
|
|
|
54
|
-
console.log('Session token result:', sessionToken ? 'Success' : 'Failed');
|
|
55
|
-
|
|
56
91
|
if (!sessionToken) {
|
|
57
|
-
|
|
92
|
+
this.logger.error('AmwalPaySDK', 'Failed to fetch session token');
|
|
58
93
|
return;
|
|
59
94
|
}
|
|
60
95
|
|
|
96
|
+
this.logger.info('AmwalPaySDK', 'Session token fetched successfully');
|
|
97
|
+
|
|
61
98
|
// Create complete config with session token
|
|
62
99
|
const completeConfig: AmwalPayConfig = {
|
|
63
100
|
...config,
|
|
@@ -65,17 +102,21 @@ class AmwalPaySDK {
|
|
|
65
102
|
};
|
|
66
103
|
|
|
67
104
|
// Initiate the payment process
|
|
68
|
-
|
|
69
|
-
'
|
|
70
|
-
|
|
105
|
+
this.logger.debug(
|
|
106
|
+
'AmwalPaySDK',
|
|
107
|
+
'Initiating native payment',
|
|
108
|
+
completeConfig
|
|
71
109
|
);
|
|
72
110
|
initiate(completeConfig);
|
|
111
|
+
|
|
112
|
+
this.logger.info('AmwalPaySDK', 'Payment process initiated successfully');
|
|
73
113
|
} catch (error) {
|
|
74
|
-
|
|
114
|
+
this.logger.error('AmwalPaySDK', 'Error starting payment', error);
|
|
75
115
|
}
|
|
76
116
|
}
|
|
77
117
|
|
|
78
118
|
dispose(): void {
|
|
119
|
+
this.logger.info('AmwalPaySDK', 'Disposing SDK instance');
|
|
79
120
|
// Remove all event listeners
|
|
80
121
|
this.removeEventListeners();
|
|
81
122
|
}
|
|
@@ -90,43 +131,46 @@ class AmwalPaySDK {
|
|
|
90
131
|
// Remove any existing listeners
|
|
91
132
|
this.removeEventListeners();
|
|
92
133
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
);
|
|
98
|
-
console.log(
|
|
99
|
-
'🟢 onCustomerId callback exists?',
|
|
100
|
-
typeof config.onCustomerId === 'function'
|
|
101
|
-
);
|
|
134
|
+
this.logger.debug('AmwalPaySDK', 'Setting up event listeners', {
|
|
135
|
+
hasOnResponse: typeof config.onResponse === 'function',
|
|
136
|
+
hasOnCustomerId: typeof config.onCustomerId === 'function',
|
|
137
|
+
});
|
|
102
138
|
|
|
103
139
|
this.onResponseSubscription = onResponse((response) => {
|
|
104
|
-
|
|
105
|
-
console.log('Received AmwalPayResponse:', response);
|
|
140
|
+
this.logger.info('AmwalPaySDK', 'Received payment response', response);
|
|
106
141
|
if (config.onResponse) {
|
|
107
142
|
config.onResponse(response);
|
|
108
143
|
} else {
|
|
109
|
-
|
|
144
|
+
this.logger.error(
|
|
145
|
+
'AmwalPaySDK',
|
|
146
|
+
'onResponse callback is not a function'
|
|
147
|
+
);
|
|
110
148
|
}
|
|
111
149
|
});
|
|
112
150
|
|
|
113
151
|
this.onCustomerIdSubscription = onCustomerId((customerId) => {
|
|
114
|
-
|
|
115
|
-
console.log('Received customerId:', customerId);
|
|
152
|
+
this.logger.info('AmwalPaySDK', 'Received customer ID', { customerId });
|
|
116
153
|
if (config.onCustomerId) {
|
|
117
154
|
config.onCustomerId(customerId);
|
|
118
155
|
} else {
|
|
119
|
-
|
|
156
|
+
this.logger.error(
|
|
157
|
+
'AmwalPaySDK',
|
|
158
|
+
'onCustomerId callback is not a function'
|
|
159
|
+
);
|
|
120
160
|
}
|
|
121
161
|
});
|
|
122
162
|
|
|
123
|
-
|
|
163
|
+
this.logger.debug('AmwalPaySDK', 'Event listeners setup completed');
|
|
124
164
|
}
|
|
125
165
|
|
|
126
166
|
/**
|
|
127
167
|
* Removes all event listeners
|
|
128
168
|
*/
|
|
129
169
|
private removeEventListeners(): void {
|
|
170
|
+
if (this.onResponseSubscription || this.onCustomerIdSubscription) {
|
|
171
|
+
this.logger.debug('AmwalPaySDK', 'Removing event listeners');
|
|
172
|
+
}
|
|
173
|
+
|
|
130
174
|
this.onResponseSubscription?.remove();
|
|
131
175
|
this.onCustomerIdSubscription?.remove();
|
|
132
176
|
this.onResponseSubscription = null;
|
package/src/index.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import ReactAmwalPay, {
|
|
|
8
8
|
} from './NativeReactAmwalPay';
|
|
9
9
|
import AmwalPaySDK from './AmwalPaySDK';
|
|
10
10
|
import { UuidUtil } from './utils/UuidUtil';
|
|
11
|
+
import Logger, { LogLevel, type LogEntry } from './utils/Logger';
|
|
11
12
|
import { NativeEventEmitter, type EventSubscription } from 'react-native';
|
|
12
13
|
|
|
13
14
|
// Create an event emitter for the native module
|
|
@@ -63,4 +64,7 @@ export {
|
|
|
63
64
|
type AmwalPayConfig,
|
|
64
65
|
AmwalPaySDK,
|
|
65
66
|
UuidUtil,
|
|
67
|
+
Logger,
|
|
68
|
+
LogLevel,
|
|
69
|
+
type LogEntry,
|
|
66
70
|
};
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { Alert } from 'react-native';
|
|
2
2
|
import { Environment } from '../NativeReactAmwalPay';
|
|
3
3
|
import SecureHashUtil from '../utils/SecureHashUtil';
|
|
4
|
+
import Logger from '../utils/Logger';
|
|
4
5
|
|
|
5
6
|
class NetworkClient {
|
|
6
7
|
private static instance: NetworkClient;
|
|
8
|
+
private logger: Logger;
|
|
7
9
|
|
|
8
|
-
private constructor() {
|
|
10
|
+
private constructor() {
|
|
11
|
+
this.logger = Logger.getInstance();
|
|
12
|
+
}
|
|
9
13
|
|
|
10
14
|
static getInstance(): NetworkClient {
|
|
11
15
|
if (!NetworkClient.instance) {
|
|
@@ -15,16 +19,19 @@ class NetworkClient {
|
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
private getWebhookUrl(env: Environment): string {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
const urls = {
|
|
23
|
+
[Environment.SIT]: 'https://test.amwalpg.com:24443/',
|
|
24
|
+
[Environment.UAT]: 'https://test.amwalpg.com:14443/',
|
|
25
|
+
[Environment.PROD]: 'https://webhook.amwalpg.com/',
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const url = urls[env] || urls[Environment.SIT];
|
|
29
|
+
this.logger.debug(
|
|
30
|
+
'NetworkClient',
|
|
31
|
+
`Using webhook URL for ${Environment[env]}`,
|
|
32
|
+
{ url }
|
|
33
|
+
);
|
|
34
|
+
return url;
|
|
28
35
|
}
|
|
29
36
|
|
|
30
37
|
async fetchSessionToken(
|
|
@@ -34,6 +41,12 @@ class NetworkClient {
|
|
|
34
41
|
secureHashValue: string
|
|
35
42
|
): Promise<string | null> {
|
|
36
43
|
try {
|
|
44
|
+
this.logger.info('NetworkClient', 'Fetching session token', {
|
|
45
|
+
environment: Environment[env],
|
|
46
|
+
merchantId,
|
|
47
|
+
hasCustomerId: !!customerId,
|
|
48
|
+
});
|
|
49
|
+
|
|
37
50
|
const webhookUrl = this.getWebhookUrl(env);
|
|
38
51
|
|
|
39
52
|
const dataMap = {
|
|
@@ -46,6 +59,11 @@ class NetworkClient {
|
|
|
46
59
|
dataMap
|
|
47
60
|
);
|
|
48
61
|
|
|
62
|
+
this.logger.debug('NetworkClient', 'Making API request', {
|
|
63
|
+
url: `${webhookUrl}Membership/GetSDKSessionToken`,
|
|
64
|
+
method: 'POST',
|
|
65
|
+
});
|
|
66
|
+
|
|
49
67
|
const response = await fetch(
|
|
50
68
|
`${webhookUrl}Membership/GetSDKSessionToken`,
|
|
51
69
|
{
|
|
@@ -65,21 +83,35 @@ class NetworkClient {
|
|
|
65
83
|
|
|
66
84
|
const responseData = await response.json();
|
|
67
85
|
|
|
86
|
+
this.logger.debug('NetworkClient', 'API response received', {
|
|
87
|
+
status: response.status,
|
|
88
|
+
ok: response.ok,
|
|
89
|
+
success: responseData.success,
|
|
90
|
+
});
|
|
91
|
+
|
|
68
92
|
if (response.ok && responseData.success) {
|
|
93
|
+
this.logger.info('NetworkClient', 'Session token fetched successfully');
|
|
69
94
|
return responseData.data.sessionToken;
|
|
70
95
|
} else {
|
|
71
96
|
const errorMessage =
|
|
72
97
|
responseData.errorList?.join(',') || 'Unknown error';
|
|
98
|
+
this.logger.error('NetworkClient', 'API request failed', {
|
|
99
|
+
status: response.status,
|
|
100
|
+
errorMessage,
|
|
101
|
+
responseData,
|
|
102
|
+
});
|
|
73
103
|
this.showErrorDialog(errorMessage);
|
|
74
104
|
return null;
|
|
75
105
|
}
|
|
76
106
|
} catch (error) {
|
|
107
|
+
this.logger.error('NetworkClient', 'Network request failed', error);
|
|
77
108
|
this.showErrorDialog('Something Went Wrong');
|
|
78
109
|
return null;
|
|
79
110
|
}
|
|
80
111
|
}
|
|
81
112
|
|
|
82
113
|
private showErrorDialog(message: string): void {
|
|
114
|
+
this.logger.warn('NetworkClient', 'Showing error dialog', { message });
|
|
83
115
|
Alert.alert('Error', message, [{ text: 'OK' }]);
|
|
84
116
|
}
|
|
85
117
|
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger utility for AmwalPay SDK
|
|
3
|
+
* Provides structured logging with different levels and optional debug mode
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export enum LogLevel {
|
|
7
|
+
DEBUG = 0,
|
|
8
|
+
INFO = 1,
|
|
9
|
+
WARN = 2,
|
|
10
|
+
ERROR = 3,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface LogEntry {
|
|
14
|
+
timestamp: string;
|
|
15
|
+
level: LogLevel;
|
|
16
|
+
tag: string;
|
|
17
|
+
message: string;
|
|
18
|
+
data?: any;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
class Logger {
|
|
22
|
+
private static instance: Logger;
|
|
23
|
+
private isDebugEnabled: boolean = __DEV__;
|
|
24
|
+
private logLevel: LogLevel = LogLevel.INFO;
|
|
25
|
+
private logs: LogEntry[] = [];
|
|
26
|
+
private maxLogEntries: number = 1000;
|
|
27
|
+
|
|
28
|
+
private constructor() {}
|
|
29
|
+
|
|
30
|
+
static getInstance(): Logger {
|
|
31
|
+
if (!Logger.instance) {
|
|
32
|
+
Logger.instance = new Logger();
|
|
33
|
+
}
|
|
34
|
+
return Logger.instance;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Enable or disable debug logging
|
|
39
|
+
*/
|
|
40
|
+
setDebugEnabled(enabled: boolean): void {
|
|
41
|
+
this.isDebugEnabled = enabled;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Set minimum log level
|
|
46
|
+
*/
|
|
47
|
+
setLogLevel(level: LogLevel): void {
|
|
48
|
+
this.logLevel = level;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Log debug message
|
|
53
|
+
*/
|
|
54
|
+
debug(tag: string, message: string, data?: any): void {
|
|
55
|
+
this.log(LogLevel.DEBUG, tag, message, data);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Log info message
|
|
60
|
+
*/
|
|
61
|
+
info(tag: string, message: string, data?: any): void {
|
|
62
|
+
this.log(LogLevel.INFO, tag, message, data);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Log warning message
|
|
67
|
+
*/
|
|
68
|
+
warn(tag: string, message: string, data?: any): void {
|
|
69
|
+
this.log(LogLevel.WARN, tag, message, data);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Log error message
|
|
74
|
+
*/
|
|
75
|
+
error(tag: string, message: string, data?: any): void {
|
|
76
|
+
this.log(LogLevel.ERROR, tag, message, data);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Internal logging method
|
|
81
|
+
*/
|
|
82
|
+
private log(level: LogLevel, tag: string, message: string, data?: any): void {
|
|
83
|
+
if (level < this.logLevel) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const timestamp = new Date().toISOString();
|
|
88
|
+
const logEntry: LogEntry = {
|
|
89
|
+
timestamp,
|
|
90
|
+
level,
|
|
91
|
+
tag,
|
|
92
|
+
message,
|
|
93
|
+
data,
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// Store log entry
|
|
97
|
+
this.logs.push(logEntry);
|
|
98
|
+
|
|
99
|
+
// Maintain max log entries
|
|
100
|
+
if (this.logs.length > this.maxLogEntries) {
|
|
101
|
+
this.logs.shift();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Console output
|
|
105
|
+
if (this.isDebugEnabled || level >= LogLevel.WARN) {
|
|
106
|
+
const levelStr = LogLevel[level];
|
|
107
|
+
const prefix = `[AmwalPay][${levelStr}][${tag}]`;
|
|
108
|
+
|
|
109
|
+
switch (level) {
|
|
110
|
+
case LogLevel.DEBUG:
|
|
111
|
+
console.debug(prefix, message, data || '');
|
|
112
|
+
break;
|
|
113
|
+
case LogLevel.INFO:
|
|
114
|
+
console.info(prefix, message, data || '');
|
|
115
|
+
break;
|
|
116
|
+
case LogLevel.WARN:
|
|
117
|
+
console.warn(prefix, message, data || '');
|
|
118
|
+
break;
|
|
119
|
+
case LogLevel.ERROR:
|
|
120
|
+
console.error(prefix, message, data || '');
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Get all stored logs
|
|
128
|
+
*/
|
|
129
|
+
getLogs(): LogEntry[] {
|
|
130
|
+
return [...this.logs];
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Get logs filtered by level
|
|
135
|
+
*/
|
|
136
|
+
getLogsByLevel(level: LogLevel): LogEntry[] {
|
|
137
|
+
return this.logs.filter((log) => log.level === level);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Get logs filtered by tag
|
|
142
|
+
*/
|
|
143
|
+
getLogsByTag(tag: string): LogEntry[] {
|
|
144
|
+
return this.logs.filter((log) => log.tag === tag);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Clear all stored logs
|
|
149
|
+
*/
|
|
150
|
+
clearLogs(): void {
|
|
151
|
+
this.logs = [];
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Export logs as JSON string
|
|
156
|
+
*/
|
|
157
|
+
exportLogs(): string {
|
|
158
|
+
return JSON.stringify(this.logs, null, 2);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export default Logger;
|