1517 lines
44 KiB
C++
1517 lines
44 KiB
C++
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
|
|
#include <curl/curl.h>
|
|
#include <pcrecpp.h>
|
|
#include <json-c/json.h>
|
|
|
|
#include "clog.h"
|
|
|
|
static void getit(struct json_object *new_obj, const char *field);
|
|
|
|
#include "stripe.h"
|
|
|
|
struct MemoryStruct {
|
|
char *memory;
|
|
size_t size;
|
|
};
|
|
|
|
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
|
|
{
|
|
size_t realsize = size * nmemb;
|
|
struct MemoryStruct *mem = (struct MemoryStruct *)userp;
|
|
|
|
mem->memory = static_cast<char*>(realloc(mem->memory, mem->size + realsize + 1));
|
|
if(mem->memory == NULL) {
|
|
/* out of memory! */
|
|
logfmt( logDEBUG, "not enough memory (realloc returned NULL)\n");
|
|
return 0;
|
|
}
|
|
|
|
memcpy(&(mem->memory[mem->size]), contents, realsize);
|
|
mem->size += realsize;
|
|
mem->memory[mem->size] = 0;
|
|
|
|
return realsize;
|
|
}
|
|
|
|
void remove_all_chars(char* str, char c) {
|
|
char *pr = str, *pw = str;
|
|
while (*pr) {
|
|
*pw = *pr++;
|
|
pw += (*pw != c);
|
|
}
|
|
*pw = '\0';
|
|
}
|
|
|
|
long stripe_tokenize_card_parse(char *json, char *token, size_t token_size)
|
|
{
|
|
long res = -1L;
|
|
json_object *new_obj;
|
|
struct json_object *o = NULL;
|
|
new_obj = json_tokener_parse(json);
|
|
|
|
if (!json_object_object_get_ex(new_obj, "id", &o)) {
|
|
logfmt( logINFO, "Field id does not exist" );
|
|
return res;
|
|
}
|
|
enum json_type o_type = json_object_get_type(o);
|
|
if (strcmp(json_type_to_name(o_type), "string")==0) {
|
|
snprintf(token, token_size, "%s", json_object_to_json_string(o));
|
|
res = 0L;
|
|
} else {
|
|
logfmt( logINFO, "Result is not string O__o" );
|
|
}
|
|
/*
|
|
logfmt(logINFO, "new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
|
|
getit(new_obj, "id");
|
|
getit(new_obj, "object");
|
|
getit(new_obj, "client_ip");
|
|
getit(new_obj, "created");
|
|
getit(new_obj, "livemode");
|
|
getit(new_obj, "type");
|
|
getit(new_obj, "used");
|
|
*/
|
|
json_object_put(new_obj);
|
|
return res;
|
|
}
|
|
|
|
// https://github.com/json-c/json-c/blob/master/tests/test_cast.c
|
|
static void getit(struct json_object *new_obj, const char *field)
|
|
{
|
|
struct json_object *o = NULL;
|
|
if (!json_object_object_get_ex(new_obj, field, &o))
|
|
printf("Field %s does not exist\n", field);
|
|
|
|
enum json_type o_type = json_object_get_type(o);
|
|
printf("new_obj.%s json_object_get_type()=%s\n", field,
|
|
json_type_to_name(o_type));
|
|
printf("new_obj.to_string()=%s\n",
|
|
json_object_to_json_string(o));
|
|
printf("new_obj.%s json_object_get_int()=%d\n", field,
|
|
json_object_get_int(o));
|
|
// printf("new_obj.%s json_object_get_int64()=%" PRId64 "\n", field,
|
|
// json_object_get_int64(o));
|
|
printf("new_obj.%s json_object_get_boolean()=%d\n", field,
|
|
json_object_get_boolean(o));
|
|
printf("new_obj.%s json_object_get_double()=%f\n", field,
|
|
json_object_get_double(o));
|
|
}
|
|
|
|
CURL *prepare_curl(char *url, void *chunk)
|
|
{
|
|
CURL *curl;
|
|
/* In windows, this will init the winsock stuff */
|
|
curl_global_init(CURL_GLOBAL_ALL);
|
|
|
|
/* get a curl handle */
|
|
curl = curl_easy_init();
|
|
|
|
if(curl) {
|
|
/* First set the URL that is about to receive our POST. This URL can
|
|
just as well be a https:// URL if that is what should receive the
|
|
data. */
|
|
curl_easy_setopt(curl, CURLOPT_URL, url);
|
|
|
|
/* send all data to this function */
|
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
|
|
|
|
/* we pass our 'chunk' struct to the callback function */
|
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, chunk);
|
|
}
|
|
return curl;
|
|
}
|
|
|
|
/*
|
|
curl https://api.stripe.com/v1/tokens \
|
|
-u sk_test_MJYII1vrGGr7RrGw1lhYMiTq: \
|
|
-d card[number]=4242424242424242 \
|
|
-d card[exp_month]=12 \
|
|
-d card[exp_year]=2018 \
|
|
-d card[cvc]=123
|
|
*/
|
|
long stripe_tokenize_card(const char *key, const char *ccnum, const char *ccexpm, const char *ccexpy, const char *cccvc, char *token, size_t token_size)
|
|
{
|
|
CURL *curl;
|
|
CURLcode res;
|
|
|
|
long ret = -1L;
|
|
char post_fields[512];
|
|
char post_auth[256];
|
|
|
|
struct MemoryStruct chunk;
|
|
|
|
chunk.memory = static_cast<char*>(malloc(1)); /* will be grown as needed by the realloc above */
|
|
chunk.size = 0; /* no data at this point */
|
|
|
|
curl = prepare_curl("https://api.stripe.com/v1/tokens", (void *)&chunk);
|
|
|
|
if(curl) {
|
|
bzero(post_fields, sizeof(post_fields));
|
|
snprintf(post_fields, sizeof(post_fields),
|
|
"card[number]=%s&card[exp_month]=%s&card[exp_year]=%s&card[cvc]=%s",
|
|
ccnum, ccexpm, ccexpy, cccvc);
|
|
|
|
/* Now specify the POST data */
|
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_fields);
|
|
|
|
bzero(post_auth, sizeof(post_auth));
|
|
snprintf(post_auth, sizeof(post_auth), "%s:", key);
|
|
/* set user name and password for the authentication */
|
|
curl_easy_setopt(curl, CURLOPT_USERPWD, post_auth);
|
|
|
|
/* Perform the request, res will get the return code */
|
|
res = curl_easy_perform(curl);
|
|
/* Check for errors */
|
|
if(res == CURLE_OK) {
|
|
logfmt( logINFO, "%lu bytes retrieved\n", (long)chunk.size);
|
|
logfmt( logDEBUG, "%s\n", chunk.memory);
|
|
bzero(token, token_size);
|
|
ret = stripe_tokenize_card_parse(chunk.memory, token, token_size);
|
|
if (ret != 0L) {
|
|
logfmt( logINFO, "Failed to get token");
|
|
}
|
|
} else {
|
|
logfmt( logINFO, "curl_easy_perform() failed: %s\n",
|
|
curl_easy_strerror(res));
|
|
}
|
|
|
|
/* always cleanup */
|
|
curl_easy_cleanup(curl);
|
|
|
|
free(chunk.memory);
|
|
}
|
|
curl_global_cleanup();
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
{
|
|
\"id\": \"card_1BRNdFF5FERRcWDyUdOaIBzd\",
|
|
\"object\": \"card\",
|
|
\"address_city\": null,
|
|
\"address_country\": null,
|
|
\"address_line1\": null,
|
|
\"address_line1_check\": null,
|
|
\"address_line2\": null,
|
|
\"address_state\": null,
|
|
\"address_zip\": null,
|
|
\"address_zip_check\": null,
|
|
\"brand\": \"American Express\",
|
|
\"country\": \"US\",
|
|
\"customer\": \"cus_BoeZzLBOGUiRzw\",
|
|
\"cvc_check\": null,
|
|
\"dynamic_last4\": null,
|
|
\"exp_month\": 8,
|
|
\"exp_year\": 2019,
|
|
\"fingerprint\": \"9KROBb1pqZA216C4\",
|
|
\"funding\": \"credit\",
|
|
\"last4\": \"8431\",
|
|
\"metadata\": {},
|
|
\"name\": null,
|
|
\"tokenization_method\": null
|
|
}
|
|
*/
|
|
long stripe_create_card_parse(char *json, char *card, size_t card_size)
|
|
{
|
|
long res = -1L;
|
|
json_object *new_obj;
|
|
struct json_object *o = NULL;
|
|
new_obj = json_tokener_parse(json);
|
|
|
|
if (!json_object_object_get_ex(new_obj, "id", &o)) {
|
|
logfmt( logINFO, "Field ID does not exist\n" );
|
|
return res;
|
|
}
|
|
enum json_type o_type = json_object_get_type(o);
|
|
if (strcmp(json_type_to_name(o_type), "string")==0) {
|
|
snprintf(card, card_size, "%s", json_object_to_json_string(o));
|
|
res = 0L;
|
|
} else {
|
|
logfmt( logINFO, "ID is not string\n" );
|
|
res = -2L;
|
|
}
|
|
json_object_put(new_obj);
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
curl https://api.stripe.com/v1/customers/cus_BoeZzLBOGUiRzw/sources \
|
|
-u sk_test_MJYII1vrGGr7RrGw1lhYMiTq: \
|
|
-d source=tok_amex
|
|
*/
|
|
long stripe_create_card(const char *key, char *customer, char *token, char *card, size_t card_size)
|
|
{
|
|
CURL *curl;
|
|
CURLcode res;
|
|
|
|
long ret = -1L;
|
|
char post_fields[512];
|
|
char post_auth[256];
|
|
char url[256];
|
|
|
|
struct MemoryStruct chunk;
|
|
|
|
chunk.memory = static_cast<char*>(malloc(1)); /* will be grown as needed by the realloc above */
|
|
chunk.size = 0; /* no data at this point */
|
|
|
|
snprintf(url, sizeof(url), "https://api.stripe.com/v1/customers/%s/sources", customer);
|
|
curl = prepare_curl(url, (void *)&chunk);
|
|
|
|
if(curl) {
|
|
bzero(post_fields, sizeof(post_fields));
|
|
snprintf(post_fields, sizeof(post_fields),
|
|
"source=%s",
|
|
token);
|
|
|
|
/* Now specify the POST data */
|
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_fields);
|
|
|
|
bzero(post_auth, sizeof(post_auth));
|
|
snprintf(post_auth, sizeof(post_auth), "%s:", key);
|
|
/* set user name and password for the authentication */
|
|
curl_easy_setopt(curl, CURLOPT_USERPWD, post_auth);
|
|
|
|
/* Perform the request, res will get the return code */
|
|
res = curl_easy_perform(curl);
|
|
/* Check for errors */
|
|
if(res == CURLE_OK) {
|
|
logfmt( logINFO, "%lu bytes retrieved\n", (long)chunk.size);
|
|
logfmt( logDEBUG, "%s\n", chunk.memory);
|
|
bzero(card, card_size);
|
|
ret = stripe_create_card_parse(chunk.memory, card, card_size);
|
|
if (ret != 0L) {
|
|
logfmt( logINFO, "Failed to get stripe card ID\n");
|
|
}
|
|
} else {
|
|
logfmt( logINFO, "curl_easy_perform() failed: %s\n",
|
|
curl_easy_strerror(res));
|
|
}
|
|
|
|
/* always cleanup */
|
|
curl_easy_cleanup(curl);
|
|
|
|
free(chunk.memory);
|
|
}
|
|
curl_global_cleanup();
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
{
|
|
\"object\": \"list\",
|
|
\"data\": [
|
|
{
|
|
\"id\": \"card_1BR1GQF5FERRcWDyp8ncqhzS\",
|
|
\"object\": \"card\",
|
|
\"address_city\": null,
|
|
\"address_country\": null,
|
|
\"address_line1\": null,
|
|
\"address_line1_check\": null,
|
|
\"address_line2\": null,
|
|
\"address_state\": null,
|
|
\"address_zip\": null,
|
|
\"address_zip_check\": null,
|
|
\"brand\": \"Visa\",
|
|
\"country\": \"US\",
|
|
\"customer\": \"cus_BoeZzLBOGUiRzw\",
|
|
\"cvc_check\": \"pass\",
|
|
\"dynamic_last4\": null,
|
|
\"exp_month\": 12,
|
|
\"exp_year\": 2018,
|
|
\"fingerprint\": \"VsTJEtWimRlWw8lh\",
|
|
\"funding\": \"credit\",
|
|
\"last4\": \"4242\",
|
|
\"metadata\": {},
|
|
\"name\": null,
|
|
\"tokenization_method\": null
|
|
}
|
|
],
|
|
\"has_more\": false,
|
|
\"url\": \"/v1/customers/cus_BoeZzLBOGUiRzw/sources\"
|
|
}
|
|
*/
|
|
long stripe_get_all_cards_parse(char *json, vector <string> *ccids, vector <string> *ccdigits, vector <string> *ccexpm, vector <string> *ccexpy)
|
|
{
|
|
long res = -1L;
|
|
json_object *new_obj;
|
|
struct json_object *o = NULL;
|
|
struct json_object *d = NULL;
|
|
new_obj = json_tokener_parse(json);
|
|
|
|
if (!json_object_object_get_ex(new_obj, "data", &o)) {
|
|
logfmt( logINFO, "Field data does not exist" );
|
|
return res;
|
|
}
|
|
enum json_type o_type = json_object_get_type(o);
|
|
if (strcmp(json_type_to_name(o_type), "array")==0) {
|
|
//snprintf(token, token_size, "%s", json_object_to_json_string(o));
|
|
size_t orig_array_len = json_object_array_length(o);
|
|
for(size_t i = 0; i < orig_array_len; i++) {
|
|
json_object *obj = json_object_array_get_idx(o, i);
|
|
if (json_object_object_get_ex(obj, "id", &d)) {
|
|
o_type = json_object_get_type(d);
|
|
if (strcmp(json_type_to_name(o_type), "string")==0) {
|
|
res = 0L;
|
|
ccids->push_back(string(json_object_to_json_string(d)));
|
|
} else {
|
|
logfmt( logINFO, "Id is not string\n" );
|
|
if (res<0L) res = -4L;
|
|
}
|
|
} else {
|
|
logfmt( logINFO, "Id is not found\n" );
|
|
if (res<0L) res = -3L;
|
|
}
|
|
if (res==0L) {
|
|
if (json_object_object_get_ex(obj, "exp_month", &d)) {
|
|
ccexpm->push_back(string(json_object_to_json_string(d)));
|
|
}
|
|
if (json_object_object_get_ex(obj, "exp_year", &d)) {
|
|
ccexpy->push_back(string(json_object_to_json_string(d)));
|
|
}
|
|
if (json_object_object_get_ex(obj, "last4", &d)) {
|
|
ccdigits->push_back(string(json_object_to_json_string(d)));
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
logfmt( logINFO, "Data is not array\n" );
|
|
res = -2L;
|
|
}
|
|
json_object_put(new_obj);
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
curl "https://api.stripe.com/v1/customers/cus_BoeZzLBOGUiRzw/sources?object=card&limit=3" \
|
|
-u sk_test_MJYII1vrGGr7RrGw1lhYMiTq: \
|
|
-G
|
|
*/
|
|
long stripe_get_all_cards(const char *key, char *customer, vector <string> *ccids, vector <string> *ccdigits, vector <string> *ccexpm, vector <string> *ccexpy)
|
|
{
|
|
CURL *curl;
|
|
CURLcode res;
|
|
|
|
long ret = -1L;
|
|
//char post_fields[512];
|
|
char post_auth[256];
|
|
char url[256];
|
|
|
|
struct MemoryStruct chunk;
|
|
|
|
chunk.memory = static_cast<char*>(malloc(1)); /* will be grown as needed by the realloc above */
|
|
chunk.size = 0; /* no data at this point */
|
|
|
|
snprintf(url, sizeof(url), "https://api.stripe.com/v1/customers/%s/sources?object=card&limit=100", customer);
|
|
curl = prepare_curl(url, (void *)&chunk);
|
|
|
|
if(curl) {
|
|
/*
|
|
bzero(post_fields, sizeof(post_fields));
|
|
snprintf(post_fields, sizeof(post_fields),
|
|
"amount=%d¤cy=%s&description=%s&metadata[payment_id]=%s&%s=%s",
|
|
amount, currency, description, metadata, entity_name, entity);
|
|
*/
|
|
/* Now specify the POST data */
|
|
// curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_fields);
|
|
|
|
bzero(post_auth, sizeof(post_auth));
|
|
snprintf(post_auth, sizeof(post_auth), "%s:", key);
|
|
/* set user name and password for the authentication */
|
|
curl_easy_setopt(curl, CURLOPT_USERPWD, post_auth);
|
|
|
|
/* Perform the request, res will get the return code */
|
|
res = curl_easy_perform(curl);
|
|
/* Check for errors */
|
|
if(res == CURLE_OK) {
|
|
logfmt( logINFO, "%lu bytes retrieved\n", (long)chunk.size);
|
|
logfmt( logDEBUG, "%s\n", chunk.memory);
|
|
//bzero(token2, token2_size);
|
|
ret = stripe_get_all_cards_parse(chunk.memory, ccids, ccdigits, ccexpm, ccexpy);
|
|
if (ret != 0L) {
|
|
logfmt( logINFO, "Failed to load cards for %s\n", customer);
|
|
}
|
|
} else {
|
|
logfmt( logINFO, "curl_easy_perform() failed: %s\n",
|
|
curl_easy_strerror(res));
|
|
}
|
|
|
|
/* always cleanup */
|
|
curl_easy_cleanup(curl);
|
|
|
|
free(chunk.memory);
|
|
}
|
|
curl_global_cleanup();
|
|
return ret;
|
|
}
|
|
|
|
long stripe_get_card(const char *key, char *customer, const char *ccdigits, const char *ccexpm, const char *ccexpy, char *card, size_t card_size)
|
|
{
|
|
vector <string> vccids;
|
|
vector <string> vccdigits;
|
|
vector <string> vccexpm;
|
|
vector <string> vccexpy;
|
|
char digits[10];
|
|
char year[10];
|
|
snprintf(digits, sizeof(digits), "\"%s\"", ccdigits);
|
|
snprintf(year, sizeof(year), "20%s", ccexpy);
|
|
long res = stripe_get_all_cards(key, customer, &vccids, &vccdigits, &vccexpm, &vccexpy);
|
|
size_t cnt = vccids.size();
|
|
logfmt( logINFO, "Found %lu card(s)\n", cnt );
|
|
if (cnt>0 && vccdigits.size()==cnt && vccexpm.size()==cnt && vccexpy.size()==cnt) {
|
|
for (int i=0; i<cnt; i++) {
|
|
|
|
if (vccdigits[i].compare(digits)==0
|
|
&& vccexpm[i].compare(ccexpm)==0
|
|
&& (vccexpy[i].compare(ccexpy)==0 || vccexpy[i].compare(year)==0)) {
|
|
snprintf(card, card_size, "%s", vccids[i].c_str());
|
|
return 0L;
|
|
} else {
|
|
logfmt( logINFO, "No match - skipping:\n'%s'<>'%s'\n'%s'<>'%s'\n'%s'<>'%s'/'%s'\n",
|
|
vccdigits[i].c_str(), digits,
|
|
vccexpm[i].c_str(), ccexpm,
|
|
vccexpy[i].c_str(), ccexpy, year);
|
|
}
|
|
}
|
|
} else {
|
|
logfmt( logINFO, "No cards loaded\n" );
|
|
res = -1L;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
\"id\": \"ch_1AwE1GF5FERRcWDyrQ9yxFHO\",\
|
|
\"object\": \"charge\",\
|
|
\"amount\": 1000,\
|
|
\"amount_refunded\": 0,\
|
|
\"application\": null,\
|
|
\"application_fee\": null,\
|
|
\"balance_transaction\": \"txn_1AwE1GF5FERRcWDys1SwbPfO\",\
|
|
\"captured\": true,\
|
|
\"status\": \"succeeded\"
|
|
*/
|
|
long stripe_charge_entity_parse(char *json, char *id, size_t id_size)
|
|
{
|
|
long res = -1L;
|
|
json_object *new_obj;
|
|
struct json_object *o = NULL;
|
|
new_obj = json_tokener_parse(json);
|
|
|
|
if (!json_object_object_get_ex(new_obj, "id", &o)) {
|
|
logfmt( logINFO, "Field id does not exist" );
|
|
return res;
|
|
}
|
|
enum json_type o_type = json_object_get_type(o);
|
|
if (strcmp(json_type_to_name(o_type), "string")==0) {
|
|
snprintf(id, id_size, "%s", json_object_to_json_string(o));
|
|
res = 0L;
|
|
} else {
|
|
logfmt( logINFO, "Id is not string O__o" );
|
|
}
|
|
|
|
if (res==0L) {
|
|
res = -2L; // Status is not "succeeded"
|
|
if (!json_object_object_get_ex(new_obj, "status", &o)) {
|
|
logfmt( logINFO, "Field status does not exist" );
|
|
return -3L;
|
|
}
|
|
enum json_type status_type = json_object_get_type(o);
|
|
if (strcmp(json_type_to_name(status_type), "string")==0) {
|
|
if (strcmp(json_object_to_json_string(o),"\"succeeded\"")==0) {
|
|
res = 0L;
|
|
}
|
|
} else {
|
|
logfmt( logINFO, "Status is not string O__o" );
|
|
res = -4L;
|
|
}
|
|
}
|
|
json_object_put(new_obj);
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
curl https://api.stripe.com/v1/charges \
|
|
-u sk_test_MJYII1vrGGr7RrGw1lhYMiTq: \
|
|
-d amount=1000 \
|
|
-d currency=usd \
|
|
-d description="Example charge" \
|
|
-d metadata[order_id]=6735 \
|
|
-d source=tok_Mk1gcKiXo5zzgR3U9yUmx8jJ
|
|
*/
|
|
long stripe_charge_token(const char *key, char *token, int amount, const char *currency, const char *description, const char *metadata, char *id, size_t id_size)
|
|
{
|
|
return stripe_charge_real(key, "source", token, amount, currency, description, metadata, id, id_size);
|
|
}
|
|
|
|
/*
|
|
curl https://api.stripe.com/v1/charges \
|
|
-u sk_test_MJYII1vrGGr7RrGw1lhYMiTq: \
|
|
-d amount=1000 \
|
|
-d currency=usd \
|
|
-d description="Example charge" \
|
|
-d metadata[order_id]=6735 \
|
|
-d customer=cus_0c0ieRnlG77qkw
|
|
*/
|
|
long stripe_charge_customer(const char *key, char *customer, int amount, const char *currency, const char *description, const char *metadata, char *id, size_t id_size)
|
|
{
|
|
return stripe_charge_real(key, "customer", customer, amount, currency, description, metadata, id, id_size);
|
|
}
|
|
|
|
long stripe_charge_real(const char *key, const char *entity_name, char *entity, int amount, const char *currency, const char *description, const char *metadata, char *id, size_t id_size)
|
|
{
|
|
CURL *curl;
|
|
CURLcode res;
|
|
|
|
long ret = -1L;
|
|
char post_fields[512];
|
|
char post_auth[256];
|
|
|
|
struct MemoryStruct chunk;
|
|
|
|
chunk.memory = static_cast<char*>(malloc(1)); /* will be grown as needed by the realloc above */
|
|
chunk.size = 0; /* no data at this point */
|
|
|
|
curl = prepare_curl("https://api.stripe.com/v1/charges", (void *)&chunk);
|
|
|
|
if(curl) {
|
|
bzero(post_fields, sizeof(post_fields));
|
|
snprintf(post_fields, sizeof(post_fields),
|
|
"amount=%d¤cy=%s&description=%s&metadata[payment_id]=%s&%s=%s",
|
|
amount, currency, description, metadata, entity_name, entity);
|
|
|
|
/* Now specify the POST data */
|
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_fields);
|
|
|
|
bzero(post_auth, sizeof(post_auth));
|
|
snprintf(post_auth, sizeof(post_auth), "%s:", key);
|
|
/* set user name and password for the authentication */
|
|
curl_easy_setopt(curl, CURLOPT_USERPWD, post_auth);
|
|
|
|
/* Perform the request, res will get the return code */
|
|
res = curl_easy_perform(curl);
|
|
/* Check for errors */
|
|
if(res == CURLE_OK) {
|
|
logfmt( logINFO, "%lu bytes retrieved\n", (long)chunk.size);
|
|
logfmt( logDEBUG, "%s\n", chunk.memory);
|
|
//bzero(token2, token2_size);
|
|
ret = stripe_charge_entity_parse(chunk.memory, id, id_size);
|
|
if (ret != 0L) {
|
|
logfmt( logINFO, "Failed to charge %s: %s", entity_name, entity);
|
|
}
|
|
} else {
|
|
logfmt( logINFO, "curl_easy_perform() failed: %s\n",
|
|
curl_easy_strerror(res));
|
|
}
|
|
|
|
/* always cleanup */
|
|
curl_easy_cleanup(curl);
|
|
|
|
free(chunk.memory);
|
|
}
|
|
curl_global_cleanup();
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
"id": "cus_BRNA3itMe3K2qP",
|
|
"object": "customer",
|
|
"account_balance": 0,
|
|
"created": 1505999327,
|
|
"currency": "usd",
|
|
"default_source": null,
|
|
"delinquent": false,
|
|
"description": null,
|
|
"discount": null,
|
|
"email": null,
|
|
"livemode": false,
|
|
"metadata": {
|
|
},
|
|
"shipping": null,
|
|
"sources": {
|
|
"object": "list",
|
|
"data": [
|
|
|
|
],
|
|
"has_more": false,
|
|
"total_count": 0,
|
|
"url": "/v1/customers/cus_BRNA3itMe3K2qP/sources"
|
|
},
|
|
"subscriptions": {
|
|
"object": "list",
|
|
"data": [
|
|
|
|
],
|
|
"has_more": false,
|
|
"total_count": 0,
|
|
"url": "/v1/customers/cus_BRNA3itMe3K2qP/subscriptions"
|
|
*/
|
|
long stripe_create_customer_parse(char *json, char *id, size_t id_size)
|
|
{
|
|
long res = -1L;
|
|
json_object *new_obj;
|
|
struct json_object *o = NULL;
|
|
new_obj = json_tokener_parse(json);
|
|
|
|
if (!json_object_object_get_ex(new_obj, "id", &o)) {
|
|
logfmt( logINFO, "Field id does not exist" );
|
|
return res;
|
|
}
|
|
enum json_type o_type = json_object_get_type(o);
|
|
if (strcmp(json_type_to_name(o_type), "string")==0) {
|
|
snprintf(id, id_size, "%s", json_object_to_json_string(o));
|
|
res = 0L;
|
|
} else {
|
|
logfmt( logINFO, "Id is not string O__o" );
|
|
}
|
|
|
|
if (res==0L) {
|
|
res = -2L; // extra check waht we got - customer?
|
|
if (!json_object_object_get_ex(new_obj, "object", &o)) {
|
|
logfmt( logINFO, "Field object does not exist" );
|
|
return -3L;
|
|
}
|
|
enum json_type object_type = json_object_get_type(o);
|
|
if (strcmp(json_type_to_name(object_type), "string")==0) {
|
|
if (strcmp(json_object_to_json_string(o),"\"customer\"")==0) {
|
|
res = 0L;
|
|
}
|
|
} else {
|
|
logfmt( logINFO, "Object is not string O__o" );
|
|
res = -4L;
|
|
}
|
|
}
|
|
json_object_put(new_obj);
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
curl https://api.stripe.com/v1/customers \
|
|
-u sk_test_MJYII1vrGGr7RrGw1lhYMiTq: \
|
|
-d description="Olusesan Ameye" \
|
|
-d email="paying.user@example.com" \
|
|
-d metadata[customer_id]=6735 \
|
|
-d source=tok_udFYcI8zrJp4isLhiWPybdpe
|
|
*/
|
|
long stripe_create_customer(const char *key, char *token, const char *email, const char *description, const char *metadata, char *id, size_t id_size)
|
|
{
|
|
CURL *curl;
|
|
CURLcode res;
|
|
|
|
long ret = -1L;
|
|
char post_fields[512];
|
|
char post_auth[256];
|
|
|
|
struct MemoryStruct chunk;
|
|
|
|
chunk.memory = static_cast<char*>(malloc(1)); /* will be grown as needed by the realloc above */
|
|
chunk.size = 0; /* no data at this point */
|
|
|
|
curl = prepare_curl("https://api.stripe.com/v1/customers", (void *)&chunk);
|
|
|
|
if(curl) {
|
|
bzero(post_fields, sizeof(post_fields));
|
|
snprintf(post_fields, sizeof(post_fields),
|
|
"email=%s&description=%s&metadata[customer_id]=%s&source=%s",
|
|
email, description, metadata, token);
|
|
|
|
/* Now specify the POST data */
|
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_fields);
|
|
|
|
bzero(post_auth, sizeof(post_auth));
|
|
snprintf(post_auth, sizeof(post_auth), "%s:", key);
|
|
/* set user name and password for the authentication */
|
|
curl_easy_setopt(curl, CURLOPT_USERPWD, post_auth);
|
|
|
|
/* Perform the request, res will get the return code */
|
|
res = curl_easy_perform(curl);
|
|
/* Check for errors */
|
|
if(res == CURLE_OK) {
|
|
logfmt( logINFO, "%lu bytes retrieved\n", (long)chunk.size);
|
|
logfmt( logDEBUG, "%s\n", chunk.memory);
|
|
//bzero(token2, token2_size);
|
|
ret = stripe_create_customer_parse(chunk.memory, id, id_size);
|
|
if (ret != 0L) {
|
|
logfmt( logINFO, "Failed to create customer with token: %s", token);
|
|
}
|
|
} else {
|
|
logfmt( logINFO, "curl_easy_perform() failed: %s\n",
|
|
curl_easy_strerror(res));
|
|
}
|
|
|
|
/* always cleanup */
|
|
curl_easy_cleanup(curl);
|
|
|
|
free(chunk.memory);
|
|
}
|
|
curl_global_cleanup();
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
See the test_stripe_update_customer_parse() below
|
|
*/
|
|
long stripe_update_customer_parse(char *json, const char *result, char *data, size_t data_size)
|
|
{
|
|
long res = -1L;
|
|
json_object *new_obj;
|
|
struct json_object *o = NULL;
|
|
new_obj = json_tokener_parse(json);
|
|
|
|
if (!json_object_object_get_ex(new_obj, result, &o)) {
|
|
logfmt( logINFO, "Field %s does not exist", result );
|
|
return res;
|
|
}
|
|
res = 0L;
|
|
enum json_type o_type = json_object_get_type(o);
|
|
if (strcmp(json_type_to_name(o_type), "string")==0) {
|
|
snprintf(data, data_size, "%s", json_object_to_json_string(o));
|
|
} else if (strcmp(json_type_to_name(o_type), "int")==0) {
|
|
snprintf(data, data_size, "%d", json_object_get_int(o));
|
|
} else if (strcmp(json_type_to_name(o_type), "int64")==0) {
|
|
snprintf(data, data_size, "%lld", json_object_get_int64(o));
|
|
} else if (strcmp(json_type_to_name(o_type), "boolean")==0) {
|
|
snprintf(data, data_size, "%s", json_object_get_boolean(o) ? "true" : "false");
|
|
} else if (strcmp(json_type_to_name(o_type), "double")==0) {
|
|
snprintf(data, data_size, "%f", json_object_get_double(o));
|
|
} else {
|
|
logfmt( logINFO, "Result is not either string, int, int64, boolean or double: %s", json_type_to_name(o_type) );
|
|
res = -2L;
|
|
}
|
|
|
|
json_object_put(new_obj);
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
curl https://api.stripe.com/v1/customers/cus_BoeZzLBOGUiRzw \
|
|
-u sk_test_MJYII1vrGGr7RrGw1lhYMiTq:
|
|
-d default_source=card_1BR1GQF5FERRcWDyp8ncqhzS
|
|
*/
|
|
long stripe_update_customer(const char *key, char *customer, const char *entity, const char *entity_value, const char *result, char *data, size_t data_size)
|
|
{
|
|
CURL *curl;
|
|
CURLcode res;
|
|
|
|
long ret = -1L;
|
|
char post_fields[512];
|
|
char post_auth[256];
|
|
char url[256];
|
|
|
|
struct MemoryStruct chunk;
|
|
|
|
chunk.memory = static_cast<char*>(malloc(1)); /* will be grown as needed by the realloc above */
|
|
chunk.size = 0; /* no data at this point */
|
|
|
|
snprintf(url, sizeof(url), "https://api.stripe.com/v1/customers/%s", customer);
|
|
curl = prepare_curl(url, (void *)&chunk);
|
|
|
|
if(curl) {
|
|
bzero(post_fields, sizeof(post_fields));
|
|
snprintf(post_fields, sizeof(post_fields),
|
|
"%s=%s",
|
|
entity, entity_value);
|
|
|
|
/* Now specify the POST data */
|
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_fields);
|
|
|
|
bzero(post_auth, sizeof(post_auth));
|
|
snprintf(post_auth, sizeof(post_auth), "%s:", key);
|
|
/* set user name and password for the authentication */
|
|
curl_easy_setopt(curl, CURLOPT_USERPWD, post_auth);
|
|
|
|
/* Perform the request, res will get the return code */
|
|
res = curl_easy_perform(curl);
|
|
/* Check for errors */
|
|
if(res == CURLE_OK) {
|
|
logfmt( logINFO, "%lu bytes retrieved\n", (long)chunk.size);
|
|
logfmt( logDEBUG, "%s\n", chunk.memory);
|
|
//bzero(token2, token2_size);
|
|
ret = stripe_update_customer_parse(chunk.memory, result, data, data_size);
|
|
if (ret != 0L) {
|
|
logfmt( logINFO, "Failed to update %s: %s", entity, entity_value);
|
|
}
|
|
} else {
|
|
logfmt( logINFO, "curl_easy_perform() failed: %s\n",
|
|
curl_easy_strerror(res));
|
|
}
|
|
|
|
/* always cleanup */
|
|
curl_easy_cleanup(curl);
|
|
|
|
free(chunk.memory);
|
|
}
|
|
curl_global_cleanup();
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
American Express 34, 37
|
|
China UnionPay 62, 88
|
|
Diners ClubCarte Blanche 300-305
|
|
Diners Club International 300-305, 309, 36, 38-39
|
|
Diners Club US & Canada 54, 55
|
|
Discover Card 6011, 622126-622925, 644-649, 65
|
|
JCB 3528-3589
|
|
Laser 6304, 6706, 6771, 6709
|
|
Maestro 5018, 5020, 5038, 5612, 5893, 6304, 6759, 6761, 6762, 6763, 0604, 6390
|
|
Dankort 5019
|
|
MasterCard 50-55
|
|
Visa 4
|
|
Visa Electron 4026, 417500, 4405, 4508, 4844, 4913, 4917
|
|
*/
|
|
|
|
string stripe_get_card_type(const char *card)
|
|
{
|
|
string subject(card);
|
|
string result;
|
|
string cards[17] = {
|
|
"Amex",
|
|
"BCGlobal",
|
|
"Carte Blanche",
|
|
"Diners Club",
|
|
"Discover",
|
|
"Insta Payment",
|
|
"JCB",
|
|
"KoreanLocalCard",
|
|
"Laser",
|
|
"Maestro",
|
|
"Mastercard",
|
|
"Solo",
|
|
"Switch",
|
|
"Union Pay",
|
|
"Visa",
|
|
"Visa Master",
|
|
"TEST"
|
|
};
|
|
string regexs[17] = {
|
|
"^3[47][0-9]{13}$",
|
|
"^(6541|6556)[0-9]{12}$",
|
|
"^389[0-9]{11}$",
|
|
"^3(?:0[0-5]|[68][0-9])[0-9]{11}$",
|
|
"^65[4-9][0-9]{13}|64[4-9][0-9]{13}|6011[0-9]{12}|(622(?:12[6-9]|1[3-9][0-9]|[2-8][0-9][0-9]|9[01][0-9]|92[0-5])[0-9]{10})$",
|
|
"^63[7-9][0-9]{13}$",
|
|
"^(?:2131|1800|35[[:digit:]]{3})[[:digit:]]{11}$",
|
|
"^9[0-9]{15}$",
|
|
"^(6304|6706|6709|6771)[0-9]{12,15}$",
|
|
"^(5018|5020|5038|6304|6759|6761|6763)[0-9]{8,15}$",
|
|
"^5[1-5][0-9]{14}$",
|
|
"^(6334|6767)[0-9]{12}|(6334|6767)[0-9]{14}|(6334|6767)[0-9]{15}$",
|
|
"^(4903|4905|4911|4936|6333|6759)[0-9]{12}|(4903|4905|4911|4936|6333|6759)[0-9]{14}|(4903|4905|4911|4936|6333|6759)[0-9]{15}|564182[0-9]{10}|564182[0-9]{12}|564182[0-9]{13}|633110[0-9]{10}|633110[0-9]{12}|633110[0-9]{13}$",
|
|
"^(62[0-9]{14,17})$",
|
|
"^4[0-9]{12}(?:[0-9]{3})?$",
|
|
"^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14})$",
|
|
"\\.*"
|
|
};
|
|
|
|
try {
|
|
for (int i = 0; i < 17; i++) {
|
|
//logfmt(logDEBUG, "%s -> %d\n", regexs[i].c_str(), i);
|
|
pcrecpp::RE r(regexs[i].c_str());
|
|
if (r.FullMatch(subject)) {
|
|
result = cards[i];
|
|
break;
|
|
}
|
|
}
|
|
} catch (exception& e) {
|
|
// Syntax error in the regular expression
|
|
logfmt(logDEBUG, "regex_error caught: %s\n", e.what());
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
#ifdef TEST
|
|
|
|
#warning "Test build with main() entry point"
|
|
|
|
#define STRIPE_KEY "sk_test_MJYII1vrGGr7RrGw1lhYMiTq"
|
|
|
|
long test_stripe_tokenize_card(char *token, size_t token_size)
|
|
{
|
|
char *ccnum = "4242424242424242";
|
|
char *ccexpm = "12";
|
|
char *ccexpy = "18";
|
|
char *cccvc = "123";
|
|
long res = -1L;
|
|
|
|
res = stripe_tokenize_card(STRIPE_KEY, ccnum, ccexpm, ccexpy, cccvc, token, token_size);
|
|
logfmt( logINFO, "stripe_tokenize_card(%ld)=%s\n", res, token);
|
|
|
|
return res;
|
|
}
|
|
|
|
long test_stripe_tokenize_card_parse(void)
|
|
{
|
|
char token[256];
|
|
long res = -1L;
|
|
char *json = "{\
|
|
\"id\": \"tok_1AwCwAF5FERRcWDyTObhpckX\",\
|
|
\"object\": \"token\",\
|
|
\"card\": {\
|
|
\"id\": \"card_1AwCwAF5FERRcWDyP5OGybH4\",\
|
|
\"object\": \"card\",\
|
|
\"address_city\": null,\
|
|
\"address_country\": null,\
|
|
\"address_line1\": null,\
|
|
\"address_line1_check\": null,\
|
|
\"address_line2\": null,\
|
|
\"address_state\": null,\
|
|
\"address_zip\": null,\
|
|
\"address_zip_check\": null,\
|
|
\"brand\": \"Visa\",\
|
|
\"country\": \"US\",\
|
|
\"cvc_check\": \"unchecked\",\
|
|
\"dynamic_last4\": null,\
|
|
\"exp_month\": 12,\
|
|
\"exp_year\": 2018,\
|
|
\"fingerprint\": \"VsTJEtWimRlWw8lh\",\
|
|
\"funding\": \"credit\",\
|
|
\"last4\": \"4242\",\
|
|
\"metadata\": {},\
|
|
\"name\": null,\
|
|
\"tokenization_method\": null\
|
|
},\
|
|
\"client_ip\": \"176.117.172.40\",\
|
|
\"created\": 1504025498,\
|
|
\"livemode\": false,\
|
|
\"type\": \"card\",\
|
|
\"used\": false\
|
|
}";
|
|
bzero(token, sizeof(token));
|
|
res = stripe_tokenize_card_parse(json, token, sizeof(token));
|
|
logfmt( logINFO, "stripe_tokenize_card_parse(%ld)=%s\n", res, token);
|
|
|
|
return res;
|
|
}
|
|
|
|
long test_stripe_charge_token(char *token, char *id, size_t id_size)
|
|
{
|
|
long res = -1L;
|
|
int amount = 1000;
|
|
const char *currency = "usd";
|
|
const char *description = "Example charge";
|
|
const char *metadata = "6735";
|
|
|
|
res = stripe_charge_token(STRIPE_KEY, token, amount, currency, description, metadata, id, id_size);
|
|
logfmt( logINFO, "stripe_charge_token(%ld)=%s\n", res, id);
|
|
|
|
return res;
|
|
}
|
|
|
|
long test_stripe_charge_customer(char *customer, char *id, size_t id_size)
|
|
{
|
|
long res = -1L;
|
|
int amount = 1000;
|
|
const char *currency = "usd";
|
|
const char *description = "Example charge";
|
|
const char *metadata = "6735";
|
|
|
|
res = stripe_charge_customer(STRIPE_KEY, customer, amount, currency, description, metadata, id, id_size);
|
|
logfmt( logINFO, "stripe_charge_customer(%ld)=%s\n", res, id);
|
|
|
|
return res;
|
|
}
|
|
|
|
long test_stripe_charge_entity_parse(void)
|
|
{
|
|
long res = -1L;
|
|
char *json = "{\
|
|
\"id\": \"ch_1AwE1GF5FERRcWDyrQ9yxFHO\",\
|
|
\"object\": \"charge\",\
|
|
\"amount\": 1000,\
|
|
\"amount_refunded\": 0,\
|
|
\"application\": null,\
|
|
\"application_fee\": null,\
|
|
\"balance_transaction\": \"txn_1AwE1GF5FERRcWDys1SwbPfO\",\
|
|
\"captured\": true,\
|
|
\"created\": 1504029658,\
|
|
\"currency\": \"usd\",\
|
|
\"customer\": null,\
|
|
\"description\": \"Example charge\",\
|
|
\"destination\": null,\
|
|
\"dispute\": null,\
|
|
\"failure_code\": null,\
|
|
\"failure_message\": null,\
|
|
\"fraud_details\": {},\
|
|
\"invoice\": null,\
|
|
\"livemode\": false,\
|
|
\"metadata\": {\
|
|
\"payment_id\": \"6735\"\
|
|
},\
|
|
\"on_behalf_of\": null,\
|
|
\"order\": null,\
|
|
\"outcome\": {\
|
|
\"network_status\": \"approved_by_network\",\
|
|
\"reason\": null,\
|
|
\"risk_level\": \"normal\",\
|
|
\"seller_message\": \"Payment complete.\",\
|
|
\"type\": \"authorized\"\
|
|
},\
|
|
\"paid\": true,\
|
|
\"receipt_email\": null,\
|
|
\"receipt_number\": null,\
|
|
\"refunded\": false,\
|
|
\"refunds\": {\
|
|
\"object\": \"list\",\
|
|
\"data\": [],\
|
|
\"has_more\": false,\
|
|
\"total_count\": 0,\
|
|
\"url\": \"/v1/charges/ch_1AwE1GF5FERRcWDyrQ9yxFHO/refunds\"\
|
|
},\
|
|
\"review\": null,\
|
|
\"shipping\": null,\
|
|
\"source\": {\
|
|
\"id\": \"card_1AwE1GF5FERRcWDyBrNIFHFj\",\
|
|
\"object\": \"card\",\
|
|
\"address_city\": null,\
|
|
\"address_country\": null,\
|
|
\"address_line1\": null,\
|
|
\"address_line1_check\": null,\
|
|
\"address_line2\": null,\
|
|
\"address_state\": null,\
|
|
\"address_zip\": null,\
|
|
\"address_zip_check\": null,\
|
|
\"brand\": \"Visa\",\
|
|
\"country\": \"US\",\
|
|
\"customer\": null,\
|
|
\"cvc_check\": null,\
|
|
\"dynamic_last4\": null,\
|
|
\"exp_month\": 8,\
|
|
\"exp_year\": 2019,\
|
|
\"fingerprint\": \"VsTJEtWimRlWw8lh\",\
|
|
\"funding\": \"credit\",\
|
|
\"last4\": \"4242\",\
|
|
\"metadata\": {},\
|
|
\"name\": null,\
|
|
\"tokenization_method\": null\
|
|
},\
|
|
\"source_transfer\": null,\
|
|
\"statement_descriptor\": null,\
|
|
\"status\": \"succeeded\",\
|
|
\"transfer_group\": null\
|
|
}";
|
|
char id[256];
|
|
bzero(id, sizeof(id));
|
|
res = stripe_charge_entity_parse(json, id, sizeof(id));
|
|
logfmt( logINFO, "stripe_charge_token_parse(%ld)=%s\n", res, id);
|
|
|
|
return res;
|
|
}
|
|
|
|
long test_stripe_create_customer(char *token, char *id, size_t id_size)
|
|
{
|
|
long res = -1L;
|
|
char *email = "ameye@chiefsoft";
|
|
char *description = "Example Customer";
|
|
char *metadata = "6735";
|
|
|
|
res = stripe_create_customer(STRIPE_KEY, token, email, description, metadata, id, id_size);
|
|
logfmt( logINFO, "stripe_create_customer(%ld)=%s\n", res, id);
|
|
|
|
return res;
|
|
}
|
|
|
|
long test_stripe_create_customer_parse()
|
|
{
|
|
long res = -1L;
|
|
char *json = "{\
|
|
\"id\": \"cus_BRNA3itMe3K2qP\",\
|
|
\"object\": \"customer\",\
|
|
\"account_balance\": 0,\
|
|
\"created\": 1505999327,\
|
|
\"currency\": \"usd\",\
|
|
\"default_source\": null,\
|
|
\"delinquent\": false,\
|
|
\"description\": null,\
|
|
\"discount\": null,\
|
|
\"email\": null,\
|
|
\"livemode\": false,\
|
|
\"metadata\": {\
|
|
},\
|
|
\"shipping\": null,\
|
|
\"sources\": {\
|
|
\"object\":\"list\",\
|
|
\"data\": [\
|
|
],\
|
|
\"has_more\": false,\
|
|
\"total_count\": 0,\
|
|
\"url\": \"/v1/customers/cus_BRNA3itMe3K2qP/sources\"\
|
|
},\
|
|
\"subscriptions\": {\
|
|
\"object\": \"list\",\
|
|
\"data\": [\
|
|
],\
|
|
\"has_more\": false,\
|
|
\"total_count\": 0,\
|
|
\"url\": \"/v1/customers/cus_BRNA3itMe3K2qP/subscriptions\"\
|
|
}\
|
|
}";
|
|
char id[256];
|
|
bzero(id, sizeof(id));
|
|
res = stripe_create_customer_parse(json, id, sizeof(id));
|
|
logfmt( logINFO, "\nstripe_create_customer_parse(%ld)=%s\n", res, id);
|
|
|
|
return res;
|
|
}
|
|
|
|
long test_stripe_get_card(char *customer, char *card, size_t card_size)
|
|
{
|
|
char *ccdigits = "4242";
|
|
char *ccexpm = "12";
|
|
char *ccexpy = "18";
|
|
long res = -1L;
|
|
|
|
res = stripe_get_card(STRIPE_KEY, customer, ccdigits, ccexpm, ccexpy, card, card_size);
|
|
logfmt( logINFO, "stripe_get_card(%ld)=%s\n", res, card);
|
|
|
|
return res;
|
|
}
|
|
|
|
long test_stripe_get_all_cards_parse()
|
|
{
|
|
long res = -1L;
|
|
char *json = "{\
|
|
\"object\": \"list\",\
|
|
\"data\": [\
|
|
{\
|
|
\"id\": \"card_1BR1GQF5FERRcWDyp8ncqhzS\",\
|
|
\"object\": \"card\",\
|
|
\"address_city\": null,\
|
|
\"address_country\": null,\
|
|
\"address_line1\": null,\
|
|
\"address_line1_check\": null,\
|
|
\"address_line2\": null,\
|
|
\"address_state\": null,\
|
|
\"address_zip\": null,\
|
|
\"address_zip_check\": null,\
|
|
\"brand\": \"Visa\",\
|
|
\"country\": \"US\",\
|
|
\"customer\": \"cus_BoeZzLBOGUiRzw\",\
|
|
\"cvc_check\": \"pass\",\
|
|
\"dynamic_last4\": null,\
|
|
\"exp_month\": 12,\
|
|
\"exp_year\": 2018,\
|
|
\"fingerprint\": \"VsTJEtWimRlWw8lh\",\
|
|
\"funding\": \"credit\",\
|
|
\"last4\": \"4242\",\
|
|
\"metadata\": {},\
|
|
\"name\": null,\
|
|
\"tokenization_method\": null\
|
|
}\
|
|
],\
|
|
\"has_more\": false,\
|
|
\"url\": \"/v1/customers/cus_BoeZzLBOGUiRzw/sources\"\
|
|
}";
|
|
vector <string> vccids;
|
|
vector <string> vccdigits;
|
|
vector <string> vccexpm;
|
|
vector <string> vccexpy;
|
|
res = stripe_get_all_cards_parse(json, &vccids, &vccdigits, &vccexpm, &vccexpy);
|
|
logfmt( logINFO, "\nstripe_get_all_cards_parse(%ld):\n", res);
|
|
if (vccids.size()>0) {
|
|
for (int i=0; i<vccids.size(); i++) {
|
|
logfmt( logINFO, "\nid=%s\n", vccids[i].c_str() );
|
|
logfmt( logINFO, "\nlast4=%s\n", vccdigits[i].c_str() );
|
|
logfmt( logINFO, "\nexp_month=%s\n", vccexpm[i].c_str() );
|
|
logfmt( logINFO, "\nexp_year=%s\n", vccexpy[i].c_str() );
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
long test_stripe_create_card(char *customer, char *token, char *card, size_t card_size)
|
|
{
|
|
long res = -1L;
|
|
res = stripe_create_card(STRIPE_KEY, customer, token, card, card_size);
|
|
logfmt( logINFO, "stripe_create_card(%ld)=%s\n", res, card);
|
|
return res;
|
|
}
|
|
|
|
long test_stripe_create_card_parse()
|
|
{
|
|
long res = -1L;
|
|
char *json = "{\
|
|
\"id\": \"card_1BRNdFF5FERRcWDyUdOaIBzd\",\
|
|
\"object\": \"card\",\
|
|
\"address_city\": null,\
|
|
\"address_country\": null,\
|
|
\"address_line1\": null,\
|
|
\"address_line1_check\": null,\
|
|
\"address_line2\": null,\
|
|
\"address_state\": null,\
|
|
\"address_zip\": null,\
|
|
\"address_zip_check\": null,\
|
|
\"brand\": \"American Express\",\
|
|
\"country\": \"US\",\
|
|
\"customer\": \"cus_BoeZzLBOGUiRzw\",\
|
|
\"cvc_check\": null,\
|
|
\"dynamic_last4\": null,\
|
|
\"exp_month\": 8,\
|
|
\"exp_year\": 2019,\
|
|
\"fingerprint\": \"9KROBb1pqZA216C4\",\
|
|
\"funding\": \"credit\",\
|
|
\"last4\": \"8431\",\
|
|
\"metadata\": {},\
|
|
\"name\": null,\
|
|
\"tokenization_method\": null\
|
|
}";
|
|
char card[32];
|
|
bzero(card, sizeof(card));
|
|
res = stripe_create_card_parse(json, card, sizeof(card));
|
|
logfmt( logINFO, "\nstripe_create_card_parse(%ld)=%s\n", res, card);
|
|
|
|
return res;
|
|
}
|
|
|
|
long test_stripe_update_customer(char *customer, char *data, size_t data_size)
|
|
{
|
|
long res = -1L;
|
|
const char *entity = "default_source";
|
|
const char *entity_value = "card_1BRNdFF5FERRcWDyUdOaIBzd"; // "card_1BR1GQF5FERRcWDyp8ncqhzS";
|
|
const char *result = "default_source";
|
|
res = stripe_update_customer(STRIPE_KEY, customer, entity, entity_value, result, data, data_size);
|
|
logfmt( logINFO, "stripe_update_customer(%ld): %s=%s\n", res, result, data);
|
|
return res;
|
|
}
|
|
|
|
long test_stripe_update_customer_parse(void)
|
|
{
|
|
char data[64];
|
|
long res = -1L;
|
|
char *json = "{\
|
|
\"id\": \"cus_BoeZzLBOGUiRzw\",\
|
|
\"object\": \"customer\",\
|
|
\"account_balance\": 0,\
|
|
\"created\": 1511368795,\
|
|
\"currency\": null,\
|
|
\"default_source\": \"card_1BR1GQF5FERRcWDyp8ncqhzS\",\
|
|
\"delinquent\": false,\
|
|
\"description\": \"This is a test\",\
|
|
\"discount\": null,\
|
|
\"email\": \"ameye@chiefsoft\",\
|
|
\"livemode\": false,\
|
|
\"metadata\": {\
|
|
\"customer_id\": \"6735\"\
|
|
},\
|
|
\"shipping\": null,\
|
|
\"sources\": {\
|
|
\"object\": \"list\",\
|
|
\"data\": [\
|
|
{\
|
|
\"id\": \"card_1BR1GQF5FERRcWDyp8ncqhzS\",\
|
|
\"object\": \"card\",\
|
|
\"address_city\": null,\
|
|
\"address_country\": null,\
|
|
\"address_line1\": null,\
|
|
\"address_line1_check\": null,\
|
|
\"address_line2\": null,\
|
|
\"address_state\": null,\
|
|
\"address_zip\": null,\
|
|
\"address_zip_check\": null,\
|
|
\"brand\": \"Visa\",\
|
|
\"country\": \"US\",\
|
|
\"customer\": \"cus_BoeZzLBOGUiRzw\",\
|
|
\"cvc_check\": \"pass\",\
|
|
\"dynamic_last4\": null,\
|
|
\"exp_month\": 12,\
|
|
\"exp_year\": 2018,\
|
|
\"fingerprint\": \"VsTJEtWimRlWw8lh\",\
|
|
\"funding\": \"credit\",\
|
|
\"last4\": \"4242\",\
|
|
\"metadata\": {},\
|
|
\"name\": null,\
|
|
\"tokenization_method\": null\
|
|
},\
|
|
{\
|
|
\"id\": \"card_1BRO8qF5FERRcWDyPx5g5Tmu\",\
|
|
\"object\": \"card\",\
|
|
\"address_city\": null,\
|
|
\"address_country\": null,\
|
|
\"address_line1\": null,\
|
|
\"address_line1_check\": null,\
|
|
\"address_line2\": null,\
|
|
\"address_state\": null,\
|
|
\"address_zip\": null,\
|
|
\"address_zip_check\": null,\
|
|
\"brand\": \"Visa\",\
|
|
\"country\": \"US\",\
|
|
\"customer\": \"cus_BoeZzLBOGUiRzw\",\
|
|
\"cvc_check\": null,\
|
|
\"dynamic_last4\": null,\
|
|
\"exp_month\": 8,\
|
|
\"exp_year\": 2019,\
|
|
\"fingerprint\": \"VsTJEtWimRlWw8lh\",\
|
|
\"funding\": \"credit\",\
|
|
\"last4\": \"4242\",\
|
|
\"metadata\": {},\
|
|
\"name\": null,\
|
|
\"tokenization_method\": null\
|
|
},\
|
|
{\
|
|
\"id\": \"card_1BRO7xF5FERRcWDy8CUE72GH\",\
|
|
\"object\": \"card\",\
|
|
\"address_city\": null,\
|
|
\"address_country\": null,\
|
|
\"address_line1\": null,\
|
|
\"address_line1_check\": null,\
|
|
\"address_line2\": null,\
|
|
\"address_state\": null,\
|
|
\"address_zip\": null,\
|
|
\"address_zip_check\": null,\
|
|
\"brand\": \"Visa\",\
|
|
\"country\": \"US\",\
|
|
\"customer\": \"cus_BoeZzLBOGUiRzw\",\
|
|
\"cvc_check\": null,\
|
|
\"dynamic_last4\": null,\
|
|
\"exp_month\": 8,\
|
|
\"exp_year\": 2019,\
|
|
\"fingerprint\": \"VsTJEtWimRlWw8lh\",\
|
|
\"funding\": \"credit\",\
|
|
\"last4\": \"4242\",\
|
|
\"metadata\": {},\
|
|
\"name\": null,\
|
|
\"tokenization_method\": null\
|
|
},\
|
|
{\
|
|
\"id\": \"card_1BRNdFF5FERRcWDyUdOaIBzd\",\
|
|
\"object\": \"card\",\
|
|
\"address_city\": null,\
|
|
\"address_country\": null,\
|
|
\"address_line1\": null,\
|
|
\"address_line1_check\": null,\
|
|
\"address_line2\": null,\
|
|
\"address_state\": null,\
|
|
\"address_zip\": null,\
|
|
\"address_zip_check\": null,\
|
|
\"brand\": \"American Express\",\
|
|
\"country\": \"US\",\
|
|
\"customer\": \"cus_BoeZzLBOGUiRzw\",\
|
|
\"cvc_check\": null,\
|
|
\"dynamic_last4\": null,\
|
|
\"exp_month\": 8,\
|
|
\"exp_year\": 2019,\
|
|
\"fingerprint\": \"9KROBb1pqZA216C4\",\
|
|
\"funding\": \"credit\",\
|
|
\"last4\": \"8431\",\
|
|
\"metadata\": {},\
|
|
\"name\": null,\
|
|
\"tokenization_method\": null\
|
|
}\
|
|
],\
|
|
\"has_more\": false,\
|
|
\"total_count\": 4,\
|
|
\"url\": \"/v1/customers/cus_BoeZzLBOGUiRzw/sources\"\
|
|
},\
|
|
\"subscriptions\": {\
|
|
\"object\": \"list\",\
|
|
\"data\": [],\
|
|
\"has_more\": false,\
|
|
\"total_count\": 0,\
|
|
\"url\": \"/v1/customers/cus_BoeZzLBOGUiRzw/subscriptions\"\
|
|
}\
|
|
}";
|
|
const char *result = "default_source";
|
|
bzero(data, sizeof(data));
|
|
res = stripe_update_customer_parse(json, result, data, sizeof(data));
|
|
logfmt( logINFO, "stripe_update_customer_parse(%ld): %s=%s\n", res, result, data);
|
|
|
|
return res;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
// https://stripe.com/docs/testing#cards
|
|
char token[64];
|
|
char customer[64];
|
|
char id[64];
|
|
char card[64];
|
|
|
|
//test_stripe_tokenize_card_parse();
|
|
//test_stripe_charge_entity_parse();
|
|
//test_stripe_create_customer_parse();
|
|
//test_stripe_get_all_cards_parse();
|
|
//test_stripe_create_card_parse();
|
|
//test_stripe_update_customer_parse();
|
|
|
|
/*
|
|
string cards[] = {
|
|
"4242424242424242", // Visa
|
|
"5555555555554444", // Mastercard
|
|
"378282246310005", // AmEx
|
|
"6011111111111117", // Discover
|
|
"30569309025904", // Diners Club
|
|
"3530111333300000", // JCB
|
|
"6250946000000016", // Union Pay
|
|
"630490017740292441", // Laser
|
|
"6759649826438453", // Maestro
|
|
"6334589898000001", // Solo
|
|
"122000000000003", // Airplus
|
|
"5555555555554444", // Cartebleue
|
|
"5019717010103742", // Dankort
|
|
"6331101999990016" // Switch
|
|
};
|
|
int n = (sizeof(cards)/sizeof(*cards));
|
|
for (int i=0; i<n; i++) {
|
|
logfmt(logINFO, "Card %s is %s\n", cards[i].c_str(), stripe_get_card_type(cards[i].c_str()).c_str());
|
|
}
|
|
//*/
|
|
|
|
/*
|
|
bzero(token, sizeof(token));
|
|
if (test_stripe_tokenize_card(token, sizeof(token)) == 0L) {
|
|
logfmt(logINFO, "Loaded token: %s\n", token);
|
|
}
|
|
remove_all_chars(token, '"');
|
|
//*/
|
|
/*
|
|
bzero(id, sizeof(id));
|
|
if (test_stripe_charge_token(token, id, sizeof(id)) == 0L) {
|
|
logfmt(logINFO, "Charged token: %s\n", id);
|
|
}
|
|
//*/
|
|
/*
|
|
bzero(customer, sizeof(customer));
|
|
if (test_stripe_create_customer(token, customer, sizeof(customer)) == 0L) {
|
|
logfmt(logINFO, "Created customer: %s\n", customer);
|
|
}
|
|
remove_all_chars(customer, '"');
|
|
//*/
|
|
/*
|
|
bzero(id, sizeof(id));
|
|
if (test_stripe_charge_customer(customer, id, sizeof(id)) == 0L) {
|
|
logfmt(logINFO, "Charged customer: %s\n", id);
|
|
}
|
|
//*/
|
|
/*
|
|
snprintf(customer, sizeof(customer), "cus_BoeZzLBOGUiRzw");
|
|
bzero(card, sizeof(card));
|
|
if (test_stripe_get_card(customer, card, sizeof(card)) == 0L) {
|
|
logfmt(logINFO, "Loaded card: %s\n", card);
|
|
}
|
|
//*/
|
|
/*
|
|
snprintf(customer, sizeof(customer), "cus_BoeZzLBOGUiRzw");
|
|
snprintf(token, sizeof(token), "tok_visa");
|
|
bzero(card, sizeof(card));
|
|
if (test_stripe_create_card(customer, token, card, sizeof(card)) == 0L) {
|
|
logfmt(logINFO, "Created card: %s\n", card);
|
|
}
|
|
//*/
|
|
/*
|
|
snprintf(customer, sizeof(customer), "cus_BoeZzLBOGUiRzw");
|
|
bzero(card, sizeof(card));
|
|
if (test_stripe_update_customer(customer, card, sizeof(card)) == 0L) {
|
|
logfmt(logINFO, "Customer updated: %s\n", card);
|
|
}
|
|
//*/
|
|
return 0;
|
|
}
|
|
|
|
#endif
|
|
|