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