1
+import 'dart:convert';
2
+import 'package:cake_wallet/ionia/ionia_merchant.dart';
3
+import 'package:cake_wallet/ionia/ionia_order.dart';
4
+import 'package:flutter/foundation.dart';
5
+import 'package:http/http.dart';
6
+import 'package:cake_wallet/ionia/ionia_user_credentials.dart';
7
+import 'package:cake_wallet/ionia/ionia_virtual_card.dart';
8
+import 'package:cake_wallet/ionia/ionia_category.dart';
9
+import 'package:cake_wallet/ionia/ionia_gift_card.dart';
10
+
11
+class IoniaApi {
12
+ static const baseUri = 'apistaging.ionia.io';
13
+ static const pathPrefix = 'cake';
14
+ static final createUserUri = Uri.https(baseUri, '/$pathPrefix/CreateUser');
15
+ static final verifyEmailUri = Uri.https(baseUri, '/$pathPrefix/VerifyEmail');
16
+ static final signInUri = Uri.https(baseUri, '/$pathPrefix/SignIn');
17
+ static final createCardUri = Uri.https(baseUri, '/$pathPrefix/CreateCard');
18
+ static final getCardsUri = Uri.https(baseUri, '/$pathPrefix/GetCards');
19
+ static final getMerchantsUrl = Uri.https(baseUri, '/$pathPrefix/GetMerchants');
20
+ static final getMerchantsByFilterUrl = Uri.https(baseUri, '/$pathPrefix/GetMerchantsByFilter');
21
+ static final getPurchaseMerchantsUrl = Uri.https(baseUri, '/$pathPrefix/PurchaseGiftCard');
22
+ static final getCurrentUserGiftCardSummariesUrl = Uri.https(baseUri, '/$pathPrefix/GetCurrentUserGiftCardSummaries');
23
+ static final changeGiftCardUrl = Uri.https(baseUri, '/$pathPrefix/ChargeGiftCard');
24
+ static final getGiftCardUrl = Uri.https(baseUri, '/$pathPrefix/GetGiftCard');
25
+ static final getPaymentStatusUrl = Uri.https(baseUri, '/$pathPrefix/PaymentStatus');
26
+
27
+ // Create user
28
+
29
+ Future<String> createUser(String email, {@required String clientId}) async {
30
+ final headers = <String, String>{'clientId': clientId};
31
+ final query = <String, String>{'emailAddress': email};
32
+ final uri = createUserUri.replace(queryParameters: query);
33
+ final response = await put(uri, headers: headers);
34
+
35
+ if (response.statusCode != 200) {
36
+ // throw exception
37
+ return null;
38
+ }
39
+
40
+ final bodyJson = json.decode(response.body) as Map<String, Object>;
41
+ final data = bodyJson['Data'] as Map<String, Object>;
42
+ final isSuccessful = bodyJson['Successful'] as bool;
43
+
44
+ if (!isSuccessful) {
45
+ throw Exception(data['ErrorMessage'] as String);
46
+ }
47
+
48
+ return data['username'] as String;
49
+ }
50
+
51
+ // Verify email
52
+
53
+ Future<IoniaUserCredentials> verifyEmail({
54
+ @required String username,
55
+ @required String email,
56
+ @required String code,
57
+ @required String clientId}) async {
58
+ final headers = <String, String>{
59
+ 'clientId': clientId,
60
+ 'username': username,
61
+ 'EmailAddress': email};
62
+ final query = <String, String>{'verificationCode': code};
63
+ final uri = verifyEmailUri.replace(queryParameters: query);
64
+ final response = await put(uri, headers: headers);
65
+
66
+ if (response.statusCode != 200) {
67
+ // throw exception
68
+ return null;
69
+ }
70
+
71
+ final bodyJson = json.decode(response.body) as Map<String, Object>;
72
+ final data = bodyJson['Data'] as Map<String, Object>;
73
+ final isSuccessful = bodyJson['Successful'] as bool;
74
+
75
+ if (!isSuccessful) {
76
+ throw Exception(bodyJson['ErrorMessage'] as String);
77
+ }
78
+
79
+ final password = data['password'] as String;
80
+ username = data['username'] as String;
81
+ return IoniaUserCredentials(username, password);
82
+ }
83
+
84
+ // Sign In
85
+
86
+ Future<String> signIn(String email, {@required String clientId}) async {
87
+ final headers = <String, String>{'clientId': clientId};
88
+ final query = <String, String>{'emailAddress': email};
89
+ final uri = signInUri.replace(queryParameters: query);
90
+ final response = await put(uri, headers: headers);
91
+
92
+ if (response.statusCode != 200) {
93
+ // throw exception
94
+ return null;
95
+ }
96
+
97
+ final bodyJson = json.decode(response.body) as Map<String, Object>;
98
+ final data = bodyJson['Data'] as Map<String, Object>;
99
+ final isSuccessful = bodyJson['Successful'] as bool;
100
+
101
+ if (!isSuccessful) {
102
+ throw Exception(data['ErrorMessage'] as String);
103
+ }
104
+
105
+ return data['username'] as String;
106
+ }
107
+
108
+ // Get virtual card
109
+
110
+ Future<IoniaVirtualCard> getCards({
111
+ @required String username,
112
+ @required String password,
113
+ @required String clientId}) async {
114
+ final headers = <String, String>{
115
+ 'clientId': clientId,
116
+ 'username': username,
117
+ 'password': password};
118
+ final response = await post(getCardsUri, headers: headers);
119
+
120
+ if (response.statusCode != 200) {
121
+ // throw exception
122
+ return null;
123
+ }
124
+
125
+ final bodyJson = json.decode(response.body) as Map<String, Object>;
126
+ final data = bodyJson['Data'] as Map<String, Object>;
127
+ final isSuccessful = bodyJson['Successful'] as bool;
128
+
129
+ if (!isSuccessful) {
130
+ throw Exception(data['message'] as String);
131
+ }
132
+
133
+ final virtualCard = data['VirtualCard'] as Map<String, Object>;
134
+ return IoniaVirtualCard.fromMap(virtualCard);
135
+ }
136
+
137
+ // Create virtual card
138
+
139
+ Future<IoniaVirtualCard> createCard({
140
+ @required String username,
141
+ @required String password,
142
+ @required String clientId}) async {
143
+ final headers = <String, String>{
144
+ 'clientId': clientId,
145
+ 'username': username,
146
+ 'password': password};
147
+ final response = await post(createCardUri, headers: headers);
148
+
149
+ if (response.statusCode != 200) {
150
+ // throw exception
151
+ return null;
152
+ }
153
+
154
+ final bodyJson = json.decode(response.body) as Map<String, Object>;
155
+ final data = bodyJson['Data'] as Map<String, Object>;
156
+ final isSuccessful = bodyJson['Successful'] as bool;
157
+
158
+ if (!isSuccessful) {
159
+ throw Exception(data['message'] as String);
160
+ }
161
+
162
+ return IoniaVirtualCard.fromMap(data);
163
+ }
164
+
165
+ // Get Merchants
166
+
167
+ Future<List<IoniaMerchant>> getMerchants({
168
+ @required String username,
169
+ @required String password,
170
+ @required String clientId}) async {
171
+ final headers = <String, String>{
172
+ 'clientId': clientId,
173
+ 'username': username,
174
+ 'password': password};
175
+ final response = await post(getMerchantsUrl, headers: headers);
176
+
177
+ if (response.statusCode != 200) {
178
+ return [];
179
+ }
180
+
181
+ final decodedBody = json.decode(response.body) as Map<String, dynamic>;
182
+ final isSuccessful = decodedBody['Successful'] as bool ?? false;
183
+
184
+ if (!isSuccessful) {
185
+ return [];
186
+ }
187
+
188
+ final data = decodedBody['Data'] as List<dynamic>;
189
+ return data.map((dynamic e) {
190
+ try {
191
+ final element = e as Map<String, dynamic>;
192
+ return IoniaMerchant.fromJsonMap(element);
193
+ } catch(_) {
194
+ return null;
195
+ }
196
+ }).where((e) => e != null)
197
+ .toList();
198
+ }
199
+
200
+ // Get Merchants By Filter
201
+
202
+ Future<List<IoniaMerchant>> getMerchantsByFilter({
203
+ @required String username,
204
+ @required String password,
205
+ @required String clientId,
206
+ String search,
207
+ List<IoniaCategory> categories,
208
+ int merchantFilterType = 0}) async {
209
+ // MerchantFilterType: {All = 0, Nearby = 1, Popular = 2, Online = 3, MyFaves = 4, Search = 5}
210
+
211
+ final headers = <String, String>{
212
+ 'clientId': clientId,
213
+ 'username': username,
214
+ 'password': password,
215
+ 'Content-Type': 'application/json'};
216
+ final body = <String, dynamic>{'MerchantFilterType': merchantFilterType};
217
+
218
+ if (search != null) {
219
+ body['SearchCriteria'] = search;
220
+ }
221
+
222
+ if (categories != null) {
223
+ body['Categories'] = categories
224
+ .map((e) => e.ids)
225
+ .expand((e) => e)
226
+ .toList();
227
+ }
228
+
229
+ final response = await post(getMerchantsByFilterUrl, headers: headers, body: json.encode(body));
230
+
231
+ if (response.statusCode != 200) {
232
+ return [];
233
+ }
234
+
235
+ final decodedBody = json.decode(response.body) as Map<String, dynamic>;
236
+ final isSuccessful = decodedBody['Successful'] as bool ?? false;
237
+
238
+ if (!isSuccessful) {
239
+ return [];
240
+ }
241
+
242
+ final data = decodedBody['Data'] as List<dynamic>;
243
+ return data.map((dynamic e) {
244
+ try {
245
+ final element = e['Merchant'] as Map<String, dynamic>;
246
+ return IoniaMerchant.fromJsonMap(element);
247
+ } catch(_) {
248
+ return null;
249
+ }
250
+ }).where((e) => e != null)
251
+ .toList();
252
+ }
253
+
254
+ // Purchase Gift Card
255
+
256
+ Future<IoniaOrder> purchaseGiftCard({
257
+ @required String merchId,
258
+ @required double amount,
259
+ @required String currency,
260
+ @required String username,
261
+ @required String password,
262
+ @required String clientId}) async {
263
+ final headers = <String, String>{
264
+ 'clientId': clientId,
265
+ 'username': username,
266
+ 'password': password,
267
+ 'Content-Type': 'application/json'};
268
+ final body = <String, dynamic>{
269
+ 'Amount': amount,
270
+ 'Currency': currency,
271
+ 'MerchantId': merchId};
272
+ final response = await post(getPurchaseMerchantsUrl, headers: headers, body: json.encode(body));
273
+
274
+ if (response.statusCode != 200) {
275
+ throw Exception('Unexpected response');
276
+ }
277
+
278
+ final decodedBody = json.decode(response.body) as Map<String, dynamic>;
279
+ final isSuccessful = decodedBody['Successful'] as bool ?? false;
280
+
281
+ if (!isSuccessful) {
282
+ throw Exception(decodedBody['ErrorMessage'] as String);
283
+ }
284
+
285
+ final data = decodedBody['Data'] as Map<String, dynamic>;
286
+ return IoniaOrder.fromMap(data);
287
+ }
288
+
289
+ // Get Current User Gift Card Summaries
290
+
291
+ Future<List<IoniaGiftCard>> getCurrentUserGiftCardSummaries({
292
+ @required String username,
293
+ @required String password,
294
+ @required String clientId}) async {
295
+ final headers = <String, String>{
296
+ 'clientId': clientId,
297
+ 'username': username,
298
+ 'password': password};
299
+ final response = await post(getCurrentUserGiftCardSummariesUrl, headers: headers);
300
+
301
+ if (response.statusCode != 200) {
302
+ return [];
303
+ }
304
+
305
+ final decodedBody = json.decode(response.body) as Map<String, dynamic>;
306
+ final isSuccessful = decodedBody['Successful'] as bool ?? false;
307
+
308
+ if (!isSuccessful) {
309
+ return [];
310
+ }
311
+
312
+ final data = decodedBody['Data'] as List<dynamic>;
313
+ return data.map((dynamic e) {
314
+ try {
315
+ final element = e as Map<String, dynamic>;
316
+ return IoniaGiftCard.fromJsonMap(element);
317
+ } catch(e) {
318
+ return null;
319
+ }
320
+ }).where((e) => e != null)
321
+ .toList();
322
+ }
323
+
324
+ // Charge Gift Card
325
+
326
+ Future<void> chargeGiftCard({
327
+ @required String username,
328
+ @required String password,
329
+ @required String clientId,
330
+ @required int giftCardId,
331
+ @required double amount}) async {
332
+ final headers = <String, String>{
333
+ 'clientId': clientId,
334
+ 'username': username,
335
+ 'password': password,
336
+ 'Content-Type': 'application/json'};
337
+ final body = <String, dynamic>{
338
+ 'Id': giftCardId,
339
+ 'Amount': amount};
340
+ final response = await post(
341
+ changeGiftCardUrl,
342
+ headers: headers,
343
+ body: json.encode(body));
344
+
345
+ if (response.statusCode != 200) {
346
+ throw Exception('Failed to update Gift Card with ID ${giftCardId};Incorrect response status: ${response.statusCode};');
347
+ }
348
+
349
+ final decodedBody = json.decode(response.body) as Map<String, dynamic>;
350
+ final isSuccessful = decodedBody['Successful'] as bool ?? false;
351
+
352
+ if (!isSuccessful) {
353
+ final data = decodedBody['Data'] as Map<String, dynamic>;
354
+ final msg = data['Message'] as String ?? '';
355
+
356
+ if (msg.isNotEmpty) {
357
+ throw Exception(msg);
358
+ }
359
+
360
+ throw Exception('Failed to update Gift Card with ID ${giftCardId};');
361
+ }
362
+ }
363
+
364
+ // Get Gift Card
365
+
366
+ Future<IoniaGiftCard> getGiftCard({
367
+ @required String username,
368
+ @required String password,
369
+ @required String clientId,
370
+ @required int id}) async {
371
+ final headers = <String, String>{
372
+ 'clientId': clientId,
373
+ 'username': username,
374
+ 'password': password,
375
+ 'Content-Type': 'application/json'};
376
+ final body = <String, dynamic>{'Id': id};
377
+ final response = await post(
378
+ getGiftCardUrl,
379
+ headers: headers,
380
+ body: json.encode(body));
381
+
382
+ if (response.statusCode != 200) {
383
+ throw Exception('Failed to get Gift Card with ID ${id};Incorrect response status: ${response.statusCode};');
384
+ }
385
+
386
+ final decodedBody = json.decode(response.body) as Map<String, dynamic>;
387
+ final isSuccessful = decodedBody['Successful'] as bool ?? false;
388
+
389
+ if (!isSuccessful) {
390
+ final msg = decodedBody['ErrorMessage'] as String ?? '';
391
+
392
+ if (msg.isNotEmpty) {
393
+ throw Exception(msg);
394
+ }
395
+
396
+ throw Exception('Failed to get Gift Card with ID ${id};');
397
+ }
398
+
399
+ final data = decodedBody['Data'] as Map<String, dynamic>;
400
+ return IoniaGiftCard.fromJsonMap(data);
401
+ }
402
+
403
+ // Payment Status
404
+
405
+ Future<int> getPaymentStatus({
406
+ @required String username,
407
+ @required String password,
408
+ @required String clientId,
409
+ @required String orderId,
410
+ @required String paymentId}) async {
411
+ final headers = <String, String>{
412
+ 'clientId': clientId,
413
+ 'username': username,
414
+ 'password': password,
415
+ 'Content-Type': 'application/json'};
416
+ final body = <String, dynamic>{
417
+ 'order_id': orderId,
418
+ 'paymentId': paymentId};
419
+ final response = await post(
420
+ getPaymentStatusUrl,
421
+ headers: headers,
422
+ body: json.encode(body));
423
+
424
+ if (response.statusCode != 200) {
425
+ throw Exception('Failed to get Payment Status for order_id ${orderId} paymentId ${paymentId};Incorrect response status: ${response.statusCode};');
426
+ }
427
+
428
+ final decodedBody = json.decode(response.body) as Map<String, dynamic>;
429
+ final isSuccessful = decodedBody['Successful'] as bool ?? false;
430
+
431
+ if (!isSuccessful) {
432
+ final msg = decodedBody['ErrorMessage'] as String ?? '';
433
+
434
+ if (msg.isNotEmpty) {
435
+ throw Exception(msg);
436
+ }
437
+
438
+ throw Exception('Failed to get Payment Status for order_id ${orderId} paymentId ${paymentId}');
439
+ }
440
+
441
+ final data = decodedBody['Data'] as Map<String, dynamic>;
442
+ return data['gift_card_id'] as int;
443
+ }
444
+}
\ No newline at end of file