summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--Makefile.PL7
-rw-r--r--anteraja.c140
-rw-r--r--configure.ac1
-rw-r--r--handler.h83
-rw-r--r--pikul.c60
-rw-r--r--pikul.h5
-rw-r--r--pikul.i50
-rw-r--r--shipping.h10
9 files changed, 300 insertions, 59 deletions
diff --git a/.gitignore b/.gitignore
index d367ba6..3c5fb6d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,6 @@ install-sh
ltmain.sh
Makefile.in
missing
+*.old
+*.p*
+*_wrap.c
diff --git a/Makefile.PL b/Makefile.PL
new file mode 100644
index 0000000..2344c9c
--- /dev/null
+++ b/Makefile.PL
@@ -0,0 +1,7 @@
+use ExtUtils::MakeMaker;
+WriteMakefile(
+ NAME => 'Pikul',
+ INC => '`pkg-config --cflags json-c`',
+ LIBS => ['-lpikul -lcurl -ljson-c'],
+ OBJECT => '$(O_FILES)'
+);
diff --git a/anteraja.c b/anteraja.c
index 2fc265c..81b709a 100644
--- a/anteraja.c
+++ b/anteraja.c
@@ -8,27 +8,72 @@
\"destination\":\"%s\",\
\"weight\":%d\
}"
+#define SERVICES_WEIGHT 5
+
+#define ORDER_PATH "order"
+#define ORDER_POST \
+"{\
+\"booking_id\":\"%s-%s\",\
+\"service_code\":\"%s\",\
+\"parcel_total_weight\":%d,\
+\"shipper\":{\
+\"name\":\"%s\",\
+\"phone\":\"%s\",\
+\"district\":\"%s\",\
+\"address\":\"%s\",\
+\"postcode\":\"%s\"\
+},\
+\"receiver\":{\
+\"name\":\"%s\",\
+\"phone\":\"%s\",\
+\"district\":\"%s\",\
+\"address\":\"%s\",\
+\"postcode\":\"%s\"\
+},\
+\"items\":[\
+%s\
+],\
+\"use_insurance\":%s,\
+\"declared_value\":%d\
+}"
+#define ORDER_WEIGHT 5
+#define ORDER_INSURANCE strlen("false")
+#define ORDER_SUBTOTAL 9
+
+#define ORDER_ITEM \
+"{\
+\"item_name\":\"%s\",\
+\"item_quantity\":%d,\
+\"declared_value\":%d,\
+\"weight\":%d\
+}"
+#define ORDER_ITEM_QUANTITY 2
+#define ORDER_ITEM_PRICE 9
+#define ORDER_ITEM_WEIGHT 5
extern CURL *curl;
static const char *status_trail[] = { "status", NULL };
+static char *prefix = NULL;
-void anteraja_init(char *provisions[], struct shipping *shipping)
+void anteraja_init(char *provisions[])
{
- enum { BASE_PATH, ACCESS_KEY };
- shipping->base = malloc(strlen(provisions[BASE_PATH]) + 1);
- strcpy(shipping->base, provisions[BASE_PATH]);
- headers((const char *[]){ "access-key-id", "secret-access-key", NULL },
- &provisions[ACCESS_KEY], shipping);
- shipping->headers = curl_slist_append(shipping->headers, "Content-Type:application/json");
+ enum { BASE_PATH, ACCESS_KEY_ID, SECRET_ACCESS_KEY, PREFIX };
+ shipping.base = malloc(strlen(provisions[BASE_PATH]) + 1);
+ strcpy(shipping.base, provisions[BASE_PATH]);
+ headers((const char *[]){ "access-key-id", "secret-access-key", NULL }, &provisions[ACCESS_KEY_ID]);
+ shipping.headers = curl_slist_append(shipping.headers, "Content-Type:application/json");
+ if (provisions[PREFIX]) {
+ prefix = malloc(strlen(provisions[PREFIX]) + 1);
+ strcpy(prefix, provisions[PREFIX]);
+ }
}
-void anteraja_services(const char *origin, const char *destination, double weight,
- struct shipping *shipping, char **url, char **post)
+void anteraja_services(const char *origin, const char *destination, double weight, char **url, char **post)
{
- *url = malloc(strlen(shipping->base) + strlen(SERVICES_PATH) + 1);
- sprintf(*url, "%s%s", shipping->base, SERVICES_PATH);
- *post = malloc(strlen(SERVICES_POST) + strlen(origin) + strlen(destination) + strlen("50000")
+ *url = malloc(strlen(shipping.base) + strlen(SERVICES_PATH) + 1);
+ sprintf(*url, "%s%s", shipping.base, SERVICES_PATH);
+ *post = malloc(strlen(SERVICES_POST) + strlen(origin) + strlen(destination) + SERVICES_WEIGHT
- 2 * strlen("%s") - strlen("%d") + 1);
sprintf(*post, SERVICES_POST, origin, destination, weight < 1.0 ? 1000 : (int)weight * 1000);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, *post);
@@ -38,7 +83,7 @@ size_t anteraja_services_handle(const char *contents, size_t size, size_t nmemb,
struct pikul_services **services)
{
size_t realsize = size * nmemb;
- handle_services(contents, realsize, status_trail, (const char *[]){
+ handle(SERVICES, contents, realsize, status_trail, (const char *[]){
"content",
"services",
NULL
@@ -50,3 +95,72 @@ size_t anteraja_services_handle(const char *contents, size_t size, size_t nmemb,
}, services);
return realsize;
}
+
+void anteraja_order(const char *order_number, const char *service, const char *sender_name,
+ const char *sender_phone, const char *origin, const char *sender_address,
+ const char *sender_postal, const char *receiver_name, const char *receiver_phone,
+ const char *destination, const char *receiver_address, const char *receiver_postal,
+ int nitems, char **items[], double subtotal, char **url, char **post)
+{
+ *url = malloc(strlen(shipping.base) + strlen(ORDER_PATH) + 1);
+ sprintf(*url, "%s%s", shipping.base, ORDER_PATH);
+ enum { SKU, QUANTITY, DESCRIPTION, PRICE, WEIGHT };
+ char *json = NULL;
+ double total_weight = .0;
+ for (int i = 0; i < nitems; i++) {
+ size_t length = strlen(ORDER_ITEM) + strlen(items[i][DESCRIPTION]) + ORDER_ITEM_QUANTITY
+ + ORDER_ITEM_PRICE + ORDER_ITEM_WEIGHT - strlen("%s") - 3 * strlen("%d")
+ + strlen(",");
+ char item[length + 1];
+ int quantity = atoi(items[i][QUANTITY]);
+ if (quantity > 1)
+ nitems -= quantity - 1;
+ double price = atof(items[i][PRICE]);
+ if (price < 1000.0)
+ price = 1000.0;
+ double weight = atof(items[i][WEIGHT]) * 1000.0;
+ if (weight < 100.0)
+ weight = 100.0;
+ total_weight += weight * quantity;
+ sprintf(item, ORDER_ITEM, items[i][DESCRIPTION], quantity, (int)price, (int)weight);
+ if (json)
+ json = realloc(json, strlen(json) + length + 1);
+ else {
+ json = malloc(length + 1);
+ memset(json, '\0', strlen(json));
+ }
+ strcat(json, item);
+ if (i + 1 < nitems)
+ strcat(json, ",");
+ else
+ json[strlen(json)] = '\0';
+ }
+ *post = malloc(strlen(ORDER_POST) + strlen(prefix) + strlen(order_number) + strlen(service)
+ + ORDER_WEIGHT + strlen(sender_name) + strlen(sender_phone) + strlen(origin)
+ + strlen(sender_address) + strlen(sender_postal) + strlen(receiver_name)
+ + strlen(receiver_phone) + strlen(destination) + strlen(receiver_address)
+ + strlen(receiver_postal) + strlen(json) + ORDER_INSURANCE + ORDER_SUBTOTAL
+ - 15 * strlen("%s") - 2 * strlen("%d") + 1);
+ sprintf(*post, ORDER_POST, prefix, order_number, service, (int)total_weight, sender_name,
+ sender_phone, origin, sender_address, sender_postal, receiver_name, receiver_phone,
+ destination, receiver_address, receiver_postal, json,
+ total_weight < 1000.0 ? "true" : "false", subtotal < 1000.0 ? 1000 : (int)subtotal);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, *post);
+}
+
+size_t anteraja_order_handle(const char *contents, size_t size, size_t nmemb, char **tracking_number)
+{
+ size_t realsize = size * nmemb;
+ handle(ORDER, contents, realsize, status_trail, (const char *[]){
+ "content",
+ "waybill_no",
+ NULL
+ }, NULL, tracking_number);
+ return realsize;
+}
+
+void anteraja_cleanup()
+{
+ if (prefix)
+ free(prefix);
+}
diff --git a/configure.ac b/configure.ac
index c6d63c1..5dbace7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,6 +7,7 @@ PKG_CHECK_MODULES([DEPS], [libcurl json-c])
AC_TYPE_SIZE_T
AC_C_INLINE
AC_FUNC_MALLOC
+AC_FUNC_REALLOC
AC_CHECK_FUNCS([memset])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile])
diff --git a/handler.h b/handler.h
index 9c46975..a2c031b 100644
--- a/handler.h
+++ b/handler.h
@@ -8,8 +8,10 @@
extern json_tokener *tokener;
void recurse(struct json_object *, const char *[], struct json_object **);
-inline void handle_services(const char *contents, size_t num_bytes, const char *status_trail[],
- const char *trail[], const char *attributes[], struct pikul_services **services)
+enum type { SERVICES, ORDER };
+
+inline void handle(enum type type, const char *contents, size_t num_bytes, const char *status_trail[],
+ const char *trail[], const char *attributes[], void *data)
{
#ifdef DEBUG
((char *)contents)[num_bytes] = '\0';
@@ -30,37 +32,54 @@ inline void handle_services(const char *contents, size_t num_bytes, const char *
recurse(response, status_trail, &status);
if (json_object_get_int(status) != 200)
return;
- struct json_object *array = NULL;
- recurse(response, trail, &array);
- size_t length = json_object_array_length(array);
- *services = malloc(sizeof(struct pikul_services) + sizeof(struct pikul_service *[length]));
- (*services)->length = length;
- enum { CODE, NAME, ETD, COST };
- for (size_t i = 0; i < length; i++) {
- (*services)->list[i] = malloc(sizeof(struct pikul_service));
- struct pikul_service *service = (*services)->list[i];
- json_object *object = json_object_array_get_idx(array, i);
- struct json_object_iterator iterator = json_object_iter_begin(object);
- struct json_object_iterator iterator_end = json_object_iter_end(object);
- while (!json_object_iter_equal(&iterator, &iterator_end)) {
- const char *name = json_object_iter_peek_name(&iterator);
- json_object *value = json_object_iter_peek_value(&iterator);
- if (!strcmp(name, attributes[COST]))
- service->cost = json_object_get_double(value);
- else {
- int len = json_object_get_string_len(value);
- if (len) {
- char *string = malloc(len + 1);
- strcpy(string, json_object_get_string(value));
- if (!strcmp(name, attributes[CODE]))
- service->code = string;
- else if (!strcmp(name, attributes[NAME]))
- service->name = string;
- else if (!strcmp(name, attributes[ETD]))
- service->etd = string;
+ switch (type) {
+ case SERVICES:
+ ;
+ struct json_object *array = NULL;
+ recurse(response, trail, &array);
+ size_t length = json_object_array_length(array);
+ struct pikul_services **services = (struct pikul_services **)data;
+ *services = malloc(sizeof(struct pikul_services)
+ + sizeof(struct pikul_service *[length]));
+ (*services)->length = length;
+ enum { CODE, NAME, ETD, COST };
+ for (size_t i = 0; i < length; i++) {
+ (*services)->list[i] = malloc(sizeof(struct pikul_service));
+ struct pikul_service *service = (*services)->list[i];
+ json_object *object = json_object_array_get_idx(array, i);
+ struct json_object_iterator iterator = json_object_iter_begin(object);
+ struct json_object_iterator iterator_end = json_object_iter_end(object);
+ while (!json_object_iter_equal(&iterator, &iterator_end)) {
+ const char *name = json_object_iter_peek_name(&iterator);
+ json_object *value = json_object_iter_peek_value(&iterator);
+ if (!strcmp(name, attributes[COST]))
+ service->cost = json_object_get_double(value);
+ else {
+ int len = json_object_get_string_len(value);
+ if (len) {
+ char *string = malloc(len + 1);
+ strcpy(string, json_object_get_string(value));
+ if (!strcmp(name, attributes[CODE]))
+ service->code = string;
+ else if (!strcmp(name, attributes[NAME]))
+ service->name = string;
+ else if (!strcmp(name, attributes[ETD]))
+ service->etd = string;
+ }
+ }
+ json_object_iter_next(&iterator);
}
}
- json_object_iter_next(&iterator);
- }
+ break;
+ case ORDER:
+ ;
+ struct json_object *string = NULL;
+ recurse(response, trail, &string);
+ char **tracking_number = (char **)data;
+ *tracking_number = malloc(json_object_get_string_len(string) + 1);
+ strcpy(*tracking_number, json_object_get_string(string));
+ break;
+ default:
+ break;
}
}
diff --git a/pikul.c b/pikul.c
index d0ef912..a2e61b5 100644
--- a/pikul.c
+++ b/pikul.c
@@ -3,15 +3,19 @@
CURL *curl;
json_tokener *tokener;
-static struct shipping shipping;
+struct shipping shipping;
-extern inline void headers(const char *[], char *[], struct shipping *);
-extern inline void handle_services(const char *, size_t, const char *[], const char *[], const char *[],
- struct pikul_services **);
+void headers(const char *[], char *[]);
+void handle(enum type, const char *, size_t, const char *[], const char *[], const char *[], void *);
-extern void anteraja_init(char *[], struct shipping *);
-extern void anteraja_services(const char *, const char *, double, struct shipping *, char **, char **);
-extern size_t anteraja_services_handle(const char *, size_t, size_t, struct pikul_services **);
+void anteraja_init(char *[]);
+void anteraja_services(const char *, const char *, double, char **, char **);
+size_t anteraja_services_handle(const char *, size_t, size_t, struct pikul_services **);
+void anteraja_order(const char *, const char *, const char *, const char *, const char *, const char *,
+ const char *, const char *, const char *, const char *, const char *, const char *, int,
+ char **[], double, char **, char **);
+size_t anteraja_order_handle(const char *, size_t size, size_t nmemb, char **);
+void anteraja_cleanup();
extern void sicepat_init(char *[], struct shipping *);
extern void sicepat_services(const char *, const char *, double, struct shipping *, char **);
@@ -27,7 +31,7 @@ void pikul_init(enum pikul_company company, char *provisions[])
shipping.company = company;
switch (company) {
case PIKUL_ANTERAJA:
- anteraja_init(provisions, &shipping);
+ anteraja_init(provisions);
break;
case PIKUL_SICEPAT:
sicepat_init(provisions, &shipping);
@@ -58,7 +62,7 @@ struct pikul_services *pikul_services(const char *origin, const char *destinatio
size_t (*handler)(const char *, size_t, size_t, struct pikul_services **);
switch (shipping.company) {
case PIKUL_ANTERAJA:
- anteraja_services(origin, destination, weight, &shipping, &url, &post);
+ anteraja_services(origin, destination, weight, &url, &post);
handler = anteraja_services_handle;
break;
case PIKUL_SICEPAT:
@@ -117,8 +121,46 @@ double pikul_cost(const char *origin, const char *destination, double weight, co
return cost;
}
+char *pikul_order(const char *order_number, const char *service, const char *sender_name,
+ const char *sender_phone, const char *origin, const char *sender_address,
+ const char *sender_postal, const char *receiver_name, const char *receiver_phone,
+ const char *destination, const char *receiver_address, const char *receiver_postal,
+ int nitems, char **items[], double subtotal)
+{
+ char *tracking_number = NULL;
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &tracking_number);
+ char *url;
+ char *post = NULL;
+ size_t (*handler)(const char *, size_t, size_t, char **);
+ switch (shipping.company) {
+ case PIKUL_ANTERAJA:
+ anteraja_order(order_number, service, sender_name, sender_phone, origin,
+ sender_address, sender_postal, receiver_name, receiver_phone,
+ destination, receiver_address, receiver_postal, nitems, items,
+ subtotal, &url, &post);
+ handler = anteraja_order_handle;
+ break;
+ default:
+ break;
+ }
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, handler);
+ curl_easy_perform(curl);
+ if (post)
+ free(post);
+ free(url);
+ return tracking_number;
+}
+
void pikul_cleanup()
{
+ switch (shipping.company) {
+ case PIKUL_ANTERAJA:
+ anteraja_cleanup();
+ break;
+ default:
+ break;
+ }
free(shipping.base);
json_tokener_free(tokener);
curl_slist_free_all(shipping.headers);
diff --git a/pikul.h b/pikul.h
index 4eb790b..aa54cca 100644
--- a/pikul.h
+++ b/pikul.h
@@ -26,6 +26,11 @@ void pikul_init(enum pikul_company company, char *provisions[]);
struct pikul_services *pikul_services(const char *origin, const char *destination, double weight);
void pikul_free_services(struct pikul_services *services);
double pikul_cost(const char *origin, const char *destination, double weight, const char *service);
+char *pikul_order(const char *order_number, const char *service, const char *sender_name,
+ const char *sender_phone, const char *origin, const char *sender_address,
+ const char *sender_postal, const char *receiver_name, const char *receiver_phone,
+ const char *destination, const char *receiver_address, const char *receiver_postal,
+ int nitems, char **items[], double subtotal);
void pikul_cleanup();
#ifdef __cplusplus
diff --git a/pikul.i b/pikul.i
new file mode 100644
index 0000000..331cfcb
--- /dev/null
+++ b/pikul.i
@@ -0,0 +1,50 @@
+%module Pikul
+%{
+#include "pikul.h"
+%}
+
+%typemap(in) char *[] {
+ AV *tempav = (AV *)SvRV($input);
+ I32 len = av_len(tempav);
+ $1 = (char **)malloc((len + 2) * sizeof(char *));
+ int i;
+ for (i = 0; i <= len; i++) {
+ SV **tv = av_fetch(tempav, i, 0);
+ $1[i] = (char *)SvPV(*tv, PL_na);
+ }
+ $1[i] = NULL;
+};
+%typemap(freearg) char *[] {
+ free($1);
+}
+
+%typemap(in) char **[] {
+ AV *items = (AV *)SvRV($input);
+ I32 nitems_min1 = av_len(items);
+ $1 = (char ***)malloc((nitems_min1 + 2) * sizeof(char **));
+ int i;
+ for (i = 0; i <= nitems_min1; i++) {
+ SV **refptr = av_fetch(items, i, 0);
+ AV *flat = (AV *)SvRV(*refptr);
+ I32 nattrs_min1 = av_len(flat);
+ $1[i] = (char **)malloc((nattrs_min1 + 2) * sizeof(char *));
+ int j;
+ for (j = 0; j <= nattrs_min1; j++) {
+ SV **tv = av_fetch(flat, j, 0);
+ $1[i][j] = (char *)SvPV(*tv, PL_na);
+ }
+ $1[i][j] = NULL;
+ }
+ $1[i] = NULL;
+};
+%typemap(freearg) char **[] {
+ free($1);
+}
+
+%rename("%(strip:[pikul_])s") "";
+void pikul_init(enum pikul_company, char *[]);
+double pikul_cost(const char *, const char *, double, const char *);
+char *pikul_order(const char *, const char *, const char *, const char *, const char *, const char *,
+ const char *, const char *, const char *, const char *, const char *, const char *, int,
+ char **[], double);
+void pikul_cleanup();
diff --git a/shipping.h b/shipping.h
index e1c5ba5..37ac20f 100644
--- a/shipping.h
+++ b/shipping.h
@@ -2,18 +2,18 @@
#include <curl/curl.h>
#include "pikul.h"
-struct shipping {
+extern struct shipping {
enum pikul_company company;
char *base;
struct curl_slist *headers;
-};
+} shipping;
-inline void headers(const char *fields[], char *provisions[], struct shipping *shipping)
+inline void headers(const char *fields[], char *provisions[])
{
- shipping->headers = NULL;
+ shipping.headers = NULL;
while (*fields) {
char header[strlen(*fields) + strlen(*provisions) + 2];
sprintf(header, "%s:%s", *fields++, *provisions++);
- shipping->headers = curl_slist_append(shipping->headers, header);
+ shipping.headers = curl_slist_append(shipping.headers, header);
}
}