1 /*
2 * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3 */
4
5 #include <string.h>
6 #include <stdarg.h>
7
8 #include "amp_config.h"
9 #include "aos_system.h"
10 #include "amp_defines.h"
11 #include "amp_task.h"
12 #include "be_inl.h"
13
14 #include "alipay_box_sdk.h"
15 #include "alipay_box_sdk_api.h"
16 #include "alipay_xp_sdk_api.h"
17 #include "alipay_xp_sdk_ex_api.h"
18 #include "ant_kal.h"
19
20 #ifdef CUSTOM_PROFILE
21 #include "custom_profile.h"
22 #endif
23
24 #define MOD_STR "PAYBOX"
25
26 #define PAYBOX_APP_VERSION "1.2.1"
27
28 typedef struct {
29 const ant_char* mqtt_product_key;
30 const ant_char* supplier_id;
31 const ant_char* item_id;
32 const ant_char* box_model;
33 const ant_char* box_version;
34 #ifdef USE_SERVER_XP
35 const ant_char *xp_device_secret;
36 const ant_char* xp_product_key;
37 const ant_char* xp_product_secret;
38 #endif
39 } alipay_box_sdk_profile_t;
40
41 typedef struct paybox_module {
42 uint8_t flag;
43 //uint8_t data[128];
44 int js_cb_ref;
45 } paybox_module_t;
46
47 static paybox_module_t g_paybox_module;
48 static void (*g_network_status_cb)(int);
49
__paybox_dn_dynamic_get(void)50 static ant_char *__paybox_dn_dynamic_get(void)
51 {
52 #define XP_DN_MAX 200
53 static ant_char s_dn[XP_DN_MAX+1] = {0};
54 if(0 == strlen(s_dn)){
55 ant_s32 ret = ant_system_get_sn(s_dn,XP_DN_MAX);
56 if(0 != ret){
57 ant_memset(s_dn, 0x0, XP_DN_MAX);
58 amp_error(MOD_STR, "%s: get sn null,ret:%d", __func__,ret);
59 return NULL;
60 }
61 }
62 amp_debug(MOD_STR, "%s: %s", __func__, s_dn);
63 return s_dn;
64 }
65
__paybox_string_duplicate(char * src)66 static char *__paybox_string_duplicate(char *src)
67 {
68 char *dst;
69 size_t len = 0;
70
71 if (src == NULL) {
72 return NULL;
73 }
74
75 len = strlen(src);
76
77 dst = aos_malloc(len+1);
78 if (dst == NULL) {
79 return NULL;
80 }
81
82 memcpy(dst, src, len);
83 dst[len] = '\0';
84 return dst;
85 }
86
native_paybox_ota_attach(void)87 static int native_paybox_ota_attach(void)
88 {
89 static xp_ota_api_t pos_api = {0};
90
91 pos_api.start = ant_fota_start;
92 pos_api.w = ant_fota_write;
93 pos_api.upgrade = ant_fota_upgrade;
94 pos_api.get_max_size = ant_fota_get_max;
95 pos_api.erase_block = ant_fota_block_erase;
96 pos_api.end = ant_fota_end;
97 pos_api.get_security = ant_fota_get_security;
98
99 return alipay_xp_sdk_fota_api_attach(pos_api);
100 }
101
native_paybox_event_notify(char * name)102 static void native_paybox_event_notify(char *name)
103 {
104 duk_context *ctx;
105
106 if (g_paybox_module.flag == 0) {
107 return;
108 }
109
110 ctx = be_get_context();
111 be_push_ref(ctx, g_paybox_module.js_cb_ref);
112
113 duk_push_string(ctx, name);
114 duk_push_object(ctx);
115
116 if (duk_pcall(ctx, 2) != DUK_EXEC_SUCCESS) {
117 amp_console("%s", duk_safe_to_stacktrace(ctx, -1));
118 }
119
120 duk_pop(ctx);
121
122 duk_gc(ctx, 0);
123 }
124
125
native_paybox_event_init_notify(char * name,alipay_box_sdk_init_event_t * data)126 static void native_paybox_event_init_notify(char *name, alipay_box_sdk_init_event_t *data)
127 {
128 duk_context *ctx;
129
130 if (name == NULL) {
131 return;
132 }
133
134 if (data == NULL) {
135 return;
136 }
137
138 if (g_paybox_module.flag == 0) {
139 return;
140 }
141
142 ctx = be_get_context();
143 be_push_ref(ctx, g_paybox_module.js_cb_ref);
144
145 duk_push_string(ctx, name);
146
147 duk_push_object(ctx);
148 duk_push_int(ctx, data->result);
149 duk_put_prop_string(ctx, -2, "result");
150
151 if (duk_pcall(ctx, 2) != DUK_EXEC_SUCCESS) {
152 amp_console("%s", duk_safe_to_stacktrace(ctx, -1));
153 }
154
155 duk_pop(ctx);
156
157 duk_gc(ctx, 0);
158 }
159
native_paybox_event_login_notify(char * name,alipay_box_login_event_t * data)160 static void native_paybox_event_login_notify(char *name, alipay_box_login_event_t *data)
161 {
162 duk_context *ctx;
163
164 if (name == NULL) {
165 return;
166 }
167
168 if (data == NULL) {
169 return;
170 }
171
172 if (g_paybox_module.flag == 0) {
173 return;
174 }
175
176 ctx = be_get_context();
177 be_push_ref(ctx, g_paybox_module.js_cb_ref);
178
179 duk_push_string(ctx, name);
180
181 duk_push_object(ctx);
182 duk_push_int(ctx, data->bind_status);
183 duk_put_prop_string(ctx, -2, "status");
184
185 if (duk_pcall(ctx, 2) != DUK_EXEC_SUCCESS) {
186 amp_console("%s", duk_safe_to_stacktrace(ctx, -1));
187 }
188
189 duk_pop(ctx);
190
191 duk_gc(ctx, 0);
192 }
193
194
native_paybox_event_trade_notify(char * name,alipay_box_trade_event_t * data)195 static void native_paybox_event_trade_notify(char *name, alipay_box_trade_event_t *data)
196 {
197 duk_context *ctx;
198
199 if (name == NULL) {
200 return;
201 }
202
203 if (data == NULL) {
204 return;
205 }
206
207 if (g_paybox_module.flag == 0) {
208 return;
209 }
210
211 ctx = be_get_context();
212 be_push_ref(ctx, g_paybox_module.js_cb_ref);
213
214 duk_push_string(ctx, name);
215 duk_push_object(ctx);
216
217 duk_push_string(ctx, data->trade_id);
218 duk_put_prop_string(ctx, -2, "tradeid");
219 duk_push_string(ctx, data->money);
220 duk_put_prop_string(ctx, -2, "amount");
221
222 duk_push_int(ctx, data->money_switch);
223 duk_put_prop_string(ctx, -2, "moneySwitch");
224
225 #ifdef ALIPAY_BOX_ISV
226 duk_push_string(ctx, data->prefix);
227 duk_put_prop_string(ctx, -2, "prefix");
228
229 duk_push_string(ctx, data->suffix);
230 duk_put_prop_string(ctx, -2, "suffix");
231 #else
232 duk_push_string(ctx, data->file_id);
233 duk_put_prop_string(ctx, -2, "fileId");
234 #endif
235
236 if (duk_pcall(ctx, 2) != DUK_EXEC_SUCCESS) {
237 amp_console("%s", duk_safe_to_stacktrace(ctx, -1));
238 }
239
240 duk_pop(ctx);
241
242 duk_gc(ctx, 0);
243 }
244
native_paybox_sdk_event_handler(alipay_box_sdk_event_t * event,void * user_data)245 static void native_paybox_sdk_event_handler(alipay_box_sdk_event_t *event, void *user_data)
246 {
247 amp_debug(MOD_STR, "%s: receive event: %d", __func__, event->event_id);
248 switch(event->event_id)
249 {
250 case ALIPAY_BOX_EVENT_SDK_INIT:
251 amp_debug(MOD_STR, "%s: alipay_box_sdk init result: %d", __func__, event->data->init.result);
252 native_paybox_event_init_notify("init", &(event->data->init));
253 break;
254
255 case ALIPAY_BOX_EVENT_SERVER_CONNECTED:
256 amp_debug(MOD_STR, "Paybox server connected");
257 native_paybox_event_notify("connect");
258 break;
259
260 case ALIPAY_BOX_EVENT_SERVER_DISCONNECTED:
261 amp_debug(MOD_STR, "Paybox server disconnected");
262 native_paybox_event_notify("disconnect");
263 break;
264
265 case ALIPAY_BOX_EVENT_LOGIN:
266 amp_debug(MOD_STR, "Paybox login with '%s'", (event->data->login.bind_status == 1) ? "BIND" : "UNBIND");
267 native_paybox_event_login_notify("login", &event->data->login);
268 break;
269
270 case ALIPAY_BOX_EVENT_BIND:
271 amp_debug(MOD_STR, "Paybox bind");
272 native_paybox_event_notify("bind");
273 break;
274
275 case ALIPAY_BOX_EVENT_UNBIND:
276 amp_debug(MOD_STR, "Paybox unbind");
277 native_paybox_event_notify("unbind");
278 break;
279
280 case ALIPAY_BOX_EVENT_TRADE: {
281 alipay_box_trade_event_t *trade = &event->data->trade;
282 amp_debug(MOD_STR, "Paybox trade event: %s", trade->money);
283 native_paybox_event_trade_notify("trade", &event->data->trade);
284 }
285 break;
286
287 default:
288 break;
289 }
290 }
291
native_paybox_network_status_register(void (* cb)(int))292 void native_paybox_network_status_register(void (*cb)(int))
293 {
294 g_network_status_cb = cb;
295 amp_info(MOD_STR, "register network status callback success");
296 }
297
native_paybox_event_handler(alipay_box_event_t * event,void * usr_data)298 static void native_paybox_event_handler(alipay_box_event_t *event, void *usr_data)
299 {
300 amp_debug(MOD_STR, "%s: receive event %d", __func__, event->event_id - ANT_MSG_ID_IDX_BASE);
301 switch (event->event_id)
302 {
303 case ANT_EVENT_KEY:
304 amp_debug(MOD_STR, "Paybox key");
305 break;
306
307 case ANT_EVENT_TIMESYNC:
308 amp_debug(MOD_STR, "Paybox time sync");
309 //alipay_box_sdk_init(native_paybox_sdk_event_handler, NULL, ALIPAY_BOX_MODE_NORMAL);
310 break;
311
312 case ANT_EVENT_NETWORK:
313 amp_debug(MOD_STR, "Paybox network");
314 if (g_network_status_cb)
315 g_network_status_cb(1);
316 break;
317
318 case ANT_EVENT_IDLE_EVENT:
319 amp_debug(MOD_STR, "Paybox idle");
320 break;
321 case ANT_EVENT_BATTERY_CHARGE_STATUS:
322 amp_debug(MOD_STR, "Paybox battery charge status");
323 break;
324
325 case ANT_EVENT_KEY_FUNC_LONG_PRESSED:
326 amp_debug(MOD_STR, "Paybox key long press");
327 break;
328
329 default:
330 break;
331 }
332 }
333
native_paybox_shutdown_handler(void)334 static int native_paybox_shutdown_handler(void)
335 {
336 amp_debug(MOD_STR, "Paybox shut down");
337 if (g_paybox_module.flag == 1) {
338 native_paybox_event_notify("shutdown");
339 }
340 return 1;
341 }
342
native_paybox_open(duk_context * ctx)343 static duk_ret_t native_paybox_open(duk_context *ctx)
344 {
345 alipay_box_sdk_profile_t profile;
346 alipay_xp_sdk_device_config_t devcfg;
347 char *str;
348 ant_char *p_dn = NULL;
349 static char init_ok = 0;
350 char dn_static = 1;
351 int ret = -1;
352
353 if (init_ok)
354 {
355 amp_warn(MOD_STR, "paybox init already, ignore");
356 ret = 0;
357 goto out;
358 }
359
360 p_dn = __paybox_dn_dynamic_get();
361 if(!p_dn)
362 {
363 dn_static = 0;
364 }
365
366 if (!duk_is_object(ctx, 0))
367 {
368 amp_warn(MOD_STR, "parameter must be object and function");
369 ret = -1;
370 goto out;
371 }
372
373 duk_get_prop_string(ctx, 0, "mqttPrductKey");
374 duk_get_prop_string(ctx, 0, "supplierId");
375 duk_get_prop_string(ctx, 0, "itemId");
376 if (!duk_is_string(ctx, -3) || !duk_is_string(ctx, -2) ||
377 !duk_is_string(ctx, -1))
378 {
379 amp_warn(MOD_STR,
380 "Parameter 1 must be an object like {mqttPrductKey: string, supplierId: string, itemId: string, "
381 "boxModel: string, boxVersion: string, xpPrductKey: string, xpPrductSecret: string ");
382 ret = -1;
383 goto out;
384 }
385
386 str = (char*)duk_get_string(ctx, -3);
387 profile.mqtt_product_key = __paybox_string_duplicate(str);
388 str = (char*)duk_get_string(ctx, -2);
389 profile.supplier_id = __paybox_string_duplicate(str);
390 str = (char*)duk_get_string(ctx, -1);
391 profile.item_id = __paybox_string_duplicate(str);
392
393 duk_pop_3(ctx);
394
395 duk_get_prop_string(ctx, 0, "boxModel");
396 duk_get_prop_string(ctx, 0, "boxVersion");
397 if (!duk_is_string(ctx, -2) || !duk_is_string(ctx, -1))
398 {
399 amp_warn(MOD_STR,
400 "Parameter 1 must be an object like {mqttPrductKey: string, supplierId: string, itemId: string, "
401 "boxModel: string, boxVersion: string, xpPrductKey: string, xpPrductSecret: string ");
402 ret = -1;
403 goto out;
404 }
405
406 str = (char*)duk_get_string(ctx, -2);
407 profile.box_model = __paybox_string_duplicate(str);
408 str = (char*)duk_get_string(ctx, -1);
409 profile.box_version = __paybox_string_duplicate(str);
410
411 duk_pop_2(ctx);
412
413 duk_get_prop_string(ctx, 0, "xpPrductKey");
414 duk_get_prop_string(ctx, 0, "xpPrductSecret");
415 duk_get_prop_string(ctx, 0, "xpDeviceSecret");
416 if (!duk_is_string(ctx, -3) || !duk_is_string(ctx, -2) || !duk_is_string(ctx, -1))
417 {
418 amp_warn(MOD_STR,
419 "Parameter 1 must be an object like {mqttPrductKey: string, supplierId: string, itemId: string, "
420 "boxModel: string, boxVersion: string, xpPrductKey: string, xpPrductSecret: string ");
421 ret = -1;
422 goto out;
423 }
424
425 str = (char*)duk_get_string(ctx, -3);
426 profile.xp_product_key = __paybox_string_duplicate(str);
427 str = (char*)duk_get_string(ctx, -2);
428 profile.xp_product_secret = __paybox_string_duplicate(str);
429 str = (char *)duk_get_string(ctx, -1);
430 profile.xp_device_secret = __paybox_string_duplicate(str);
431
432 duk_pop_3(ctx);
433
434 #if 0 //may be required in the future
435 if (ret = alipay_box_sdk_set_mqtt_product_key(profile.mqtt_product_key))
436 {
437 amp_warn(MOD_STR, "alipay_box_sdk_set_mqtt_product_key failed!");
438 ret = -1;
439 goto out;
440 }
441 if (strcmp(profile.supplier_id, "null") &&
442 (ret = alipay_box_sdk_set_supplier_id(profile.supplier_id)) != 0)
443 {
444 amp_warn(MOD_STR, "alipay_box_sdk_set_supplier_id failed!");
445 ret = -1;
446 goto out;
447 }
448 if (strcmp(profile.item_id, "null") &&
449 (ret = alipay_box_sdk_set_item_id(profile.item_id)) != 0)
450 {
451 amp_warn(MOD_STR, "alipay_box_sdk_set_item_id failed!");
452 ret = -1;
453 goto out;
454 }
455 if (ret = alipay_box_sdk_set_box_model(profile.box_model))
456 {
457 amp_warn(MOD_STR, "alipay_box_sdk_set_box_model failed!");
458 ret = -1;
459 goto out;
460 }
461 if (ret = alipay_box_sdk_set_box_version(profile.box_version))
462 {
463 amp_warn(MOD_STR, "alipay_box_sdk_set_box_version failed!");
464 ret = -1;
465 goto out;
466 }
467 if (ret = alipay_box_sdk_set_xp_product_key(profile.xp_product_key))
468 {
469 amp_warn(MOD_STR, "alipay_box_sdk_set_xp_product_key failed!");
470 ret = -1;
471 goto out;
472 }
473 if (ret = alipay_box_sdk_set_xp_product_secret(profile.xp_product_secret))
474 {
475 amp_warn(MOD_STR, "alipay_box_sdk_set_xp_product_secret failed!");
476 ret = -1;
477 goto out;
478 }
479 #endif
480
481 memset(&devcfg, 0, sizeof(devcfg));
482 devcfg.product_key = profile.xp_product_key;
483 devcfg.product_secret = profile.xp_product_secret;
484 devcfg.device_secret = profile.xp_device_secret;
485 devcfg.version = PAYBOX_APP_VERSION;
486 devcfg.device_name = p_dn;
487 devcfg.dn_api = __paybox_dn_dynamic_get;
488
489 if (!dn_static && !devcfg.dn_api) {
490 amp_error(MOD_STR, "deviname is not found and devicename dynamic is null");
491 ret = -1;
492 goto out;
493 }
494
495 ret = alipay_xp_sdk_device_init(devcfg);
496 if (ret) {
497 amp_error(MOD_STR, "xp sdk device init fail %d", ret);
498 ret = -1;
499 goto out;
500 }
501
502 ret = native_paybox_ota_attach();
503 if (ret) {
504 amp_error(MOD_STR, "paybox ota attach fail %d", ret);
505 ret = -1;
506 goto out;
507 }
508
509 ret = alipay_sdk_init(native_paybox_event_handler, native_paybox_sdk_event_handler,
510 native_paybox_shutdown_handler, NULL, NULL, NULL, ALIPAY_BOX_MODE_NORMAL);
511 if (ret) {
512 amp_error(MOD_STR, "alipaybox sdk init fail %d", ret);
513 ret = -1;
514 goto out;
515 }
516 amp_debug(MOD_STR, "%s: alipay sdk init success", __func__);
517 init_ok = 1;
518
519 duk_push_int(ctx, 0);
520 return 1;
521
522 out:
523 duk_push_int(ctx, ret);
524 return 1;
525 }
526
native_paybox_on_data(duk_context * ctx)527 static duk_ret_t native_paybox_on_data(duk_context *ctx)
528 {
529 int ret = -1;
530
531 if (!duk_is_function(ctx, 1)) {
532 amp_warn(MOD_STR, "parameter must be handle, function");
533 goto out;
534 }
535
536 duk_dup(ctx, 1);
537 g_paybox_module.js_cb_ref = be_ref(ctx);
538 g_paybox_module.flag = 1;
539
540 ret = 1;
541 out:
542 duk_push_int(ctx, ret);
543 return 1;
544 }
545
native_paybox_close(duk_context * ctx)546 static duk_ret_t native_paybox_close(duk_context *ctx)
547 {
548 int ret = -1;
549
550 if (!duk_is_number(ctx, 0)) {
551 amp_warn(MOD_STR, "parameter must be number");
552 goto out;
553 }
554
555 memset(&g_paybox_module, 0, sizeof(g_paybox_module));
556
557 duk_push_int(ctx, 0);
558 return 1;
559
560 out:
561 duk_push_int(ctx, ret);
562 return 1;
563 }
564
native_paybox_clean(void)565 static void native_paybox_clean(void)
566 {
567
568 }
569
module_paybox_register(void)570 void module_paybox_register(void)
571 {
572 duk_context *ctx = be_get_context();
573
574 amp_module_free_register(native_paybox_clean);
575
576 memset(&g_paybox_module, 0, sizeof(g_paybox_module));
577
578 duk_push_object(ctx);
579
580 AMP_ADD_FUNCTION("open", native_paybox_open, 2);
581 AMP_ADD_FUNCTION("on", native_paybox_on_data, 2);
582 AMP_ADD_FUNCTION("close", native_paybox_close, 1);
583
584 duk_put_prop_string(ctx, -2, "PAYBOX");
585 }
586
587