EverydayTech Platform - Developer Reference
Complete Source Code Documentation - All Applications
Loading...
Searching...
No Matches
cwa-gnap-api.ts
Go to the documentation of this file.
1/**
2 * CWA Fieldpine GNAP API Integration
3 * Based on real API analysis from iig.cwanz.online
4 */
5
6export interface CWAApiResponse<T = any> {
7 data?: T;
8 error?: string;
9 status?: string;
10}
11
12export interface LocationData {
13 id: string;
14 name: string;
15 address?: string;
16 phone?: string;
17 status?: string;
18}
19
20export interface StatsData {
21 sales_today?: number;
22 transactions_today?: number;
23 last_updated?: string;
24}
25
26export interface SalesTotalsData {
27 total?: number;
28 count?: number;
29 period?: string;
30}
31
32export class CWAGnapApi {
33 private baseUrl: string;
34 private apiKey?: string;
35
36 constructor(baseUrl?: string) {
37 this.baseUrl = baseUrl || process.env.NEXT_PUBLIC_FIELDPINE_GNAP_API_URL || 'https://iig.cwanz.online/GNAP/j';
38 }
39
40 /**
41 * Set the API key for authenticated requests
42 */
43 setApiKey(apiKey: string) {
44 this.apiKey = apiKey;
45 }
46
47 /**
48 * Make a BUCK request to the GNAP API
49 */
50 private async buckRequest(service: string, params: Record<string, string | number> = {}): Promise<CWAApiResponse> {
51 const url = new URL(`${this.baseUrl}/BUCK`);
52
53 // Add the service parameter
54 url.searchParams.set('3', service);
55
56 // Add additional parameters
57 Object.entries(params).forEach(([key, value]) => {
58 url.searchParams.set(key, String(value));
59 });
60
61 const headers: HeadersInit = {
62 'Accept': '*/*',
63 'Cache-Control': 'no-cache',
64 };
65
66 // Add authentication if available
67 if (this.apiKey) {
68 headers['Cookie'] = `FieldpineApiKey=${this.apiKey}`;
69 }
70
71 try {
72 const response = await fetch(url.toString(), {
73 method: 'GET',
74 headers,
75 });
76
77 if (!response.ok) {
78 return {
79 error: `HTTP ${response.status}: ${response.statusText}`,
80 status: 'error'
81 };
82 }
83
84 const data = await response.json();
85 return {
86 data,
87 status: 'success'
88 };
89 } catch (error) {
90 return {
91 error: error instanceof Error ? error.message : 'Unknown error',
92 status: 'error'
93 };
94 }
95 }
96
97 /**
98 * Make a simple GET request to non-BUCK endpoints
99 */
100 private async simpleRequest(endpoint: string, params: Record<string, string | number> = {}): Promise<CWAApiResponse> {
101 const baseUrl = this.baseUrl.replace('/GNAP/j', ''); // Use base domain for simple requests
102 const url = new URL(`${baseUrl}/${endpoint}`);
103
104 Object.entries(params).forEach(([key, value]) => {
105 url.searchParams.set(key, String(value));
106 });
107
108 const headers: HeadersInit = {
109 'Accept': '*/*',
110 'Cache-Control': 'no-cache',
111 };
112
113 if (this.apiKey) {
114 headers['Cookie'] = `FieldpineApiKey=${this.apiKey}`;
115 }
116
117 try {
118 const response = await fetch(url.toString(), {
119 method: 'GET',
120 headers,
121 });
122
123 if (!response.ok) {
124 return {
125 error: `HTTP ${response.status}: ${response.statusText}`,
126 status: 'error'
127 };
128 }
129
130 const data = await response.text(); // Some endpoints return text, not JSON
131
132 try {
133 const jsonData = JSON.parse(data);
134 return { data: jsonData, status: 'success' };
135 } catch {
136 return { data, status: 'success' };
137 }
138 } catch (error) {
139 return {
140 error: error instanceof Error ? error.message : 'Unknown error',
141 status: 'error'
142 };
143 }
144 }
145
146 // Specific API methods based on discovered endpoints
147
148 /**
149 * Get locations list
150 * BUCK?3=retailmax.elink.locations&101=1
151 */
152 async getLocations(includeAll = true): Promise<CWAApiResponse<LocationData[]>> {
153 return this.buckRequest('retailmax.elink.locations', includeAll ? { '101': 1 } : undefined);
154 }
155
156 /**
157 * Get specific locations by range
158 * buck?3=retailmax.elink.locations&10=100-160,164,185,186
159 */
160 async getLocationsByRange(range: string): Promise<CWAApiResponse<LocationData[]>> {
161 return this.buckRequest('retailmax.elink.locations', { '10': range });
162 }
163
164 /**
165 * Get today's statistics
166 * buck?3=retailmax.elink.stats.today
167 */
168 async getStatsToday(): Promise<CWAApiResponse<StatsData>> {
169 return this.buckRequest('retailmax.elink.stats.today');
170 }
171
172 /**
173 * Get today's statistics with specific fields
174 * buck?3=retailmax.elink.stats.today&9=f112,0,1
175 */
176 async getStatsTodayWithFields(fields: string): Promise<CWAApiResponse<StatsData>> {
177 return this.buckRequest('retailmax.elink.stats.today', { '9': fields });
178 }
179
180 /**
181 * Get sales totals
182 * buck?3=retailmax.elink.sale.totals&13=120&7=101&9=f110,4,month-0
183 */
184 async getSalesTotals(params: {
185 field13?: number,
186 field7?: number,
187 field9?: string
188 } = {}): Promise<CWAApiResponse<SalesTotalsData>> {
189 const requestParams: Record<string, string | number> = {};
190 if (params.field13) requestParams['13'] = params.field13;
191 if (params.field7) requestParams['7'] = params.field7;
192 if (params.field9) requestParams['9'] = params.field9;
193
194 return this.buckRequest('retailmax.elink.sale.totals', requestParams);
195 }
196
197 /**
198 * Get user interface components
199 * buck?3=retailmax.elink.userinterface&100=sshome
200 */
201 async getUserInterface(component: string): Promise<CWAApiResponse> {
202 return this.buckRequest('retailmax.elink.userinterface', { '100': component });
203 }
204
205 /**
206 * Get printing pending list
207 * buck?3=retailmax.elink.printingpending.list
208 */
209 async getPrintingPending(): Promise<CWAApiResponse> {
210 return this.buckRequest('retailmax.elink.printingpending.list');
211 }
212
213 /**
214 * Get contact log list
215 * buck?3=retailmax.elink.contactlog.list&500=quicksummary
216 */
217 async getContactLog(filter?: string): Promise<CWAApiResponse> {
218 const params = filter ? { '500': filter } : undefined;
219 return this.buckRequest('retailmax.elink.contactlog.list', params);
220 }
221
222 /**
223 * Get server status
224 * buck?3=gds.server.status
225 */
226 async getServerStatus(): Promise<CWAApiResponse> {
227 return this.buckRequest('gds.server.status');
228 }
229
230 /**
231 * Get configuration settings
232 * buck?3=retailmax.elink.config.setting&9=f100,0,RmSystem
233 */
234 async getConfigSetting(setting: string): Promise<CWAApiResponse> {
235 return this.buckRequest('retailmax.elink.config.setting', { '9': setting });
236 }
237
238 /**
239 * Get base configuration
240 * BUCK?3=retailmax.elink.config.basesetting&112=1&112=999&9=f100,0,SaleSendRandomHost.1.Address
241 */
242 async getBaseSetting(setting: string, field112Values: number[] = [1, 999]): Promise<CWAApiResponse> {
243 const params: Record<string, string | number> = { '9': setting };
244 field112Values.forEach((value, index) => {
245 params[`112`] = value; // Note: This will overwrite, but that's how the original API works
246 });
247 return this.buckRequest('retailmax.elink.config.basesetting', params);
248 }
249
250 /**
251 * Get advisor event list
252 * buck?3=retailmax.elink.advisor.eventlist&110=accou…other,products,staff,reference,security,technical
253 */
254 async getAdvisorEventList(categories: string): Promise<CWAApiResponse> {
255 return this.buckRequest('retailmax.elink.advisor.eventlist', { '110': categories });
256 }
257
258 // Simple endpoint methods
259
260 /**
261 * Get membership information
262 * membership?id=cartridgeworld
263 */
264 async getMembership(id: string): Promise<CWAApiResponse> {
265 return this.simpleRequest('membership', { id });
266 }
267
268 /**
269 * Get products
270 * products?99=7
271 */
272 async getProducts(filter?: number): Promise<CWAApiResponse> {
273 const params = filter ? { '99': filter } : undefined;
274 return this.simpleRequest('products', params);
275 }
276
277 /**
278 * Get locations (simple endpoint)
279 * locations
280 */
281 async getLocationsSimple(): Promise<CWAApiResponse> {
282 return this.simpleRequest('locations');
283 }
284
285 /**
286 * Get retail configuration
287 * RetailConfig
288 */
289 async getRetailConfig(): Promise<CWAApiResponse> {
290 return this.simpleRequest('RetailConfig');
291 }
292
293 /**
294 * Get echo response
295 * echo.js
296 */
297 async getEcho(): Promise<CWAApiResponse> {
298 return this.simpleRequest('echo.js');
299 }
300}
301
302// Create singleton instance
303export const cwaApi = new CWAGnapApi();
304
305// Helper function to set API key globally
306export function setCWAApiKey(apiKey: string) {
307 cwaApi.setApiKey(apiKey);
308}