#include #include #include #include String byteArrayAsHexString(byte *buffer, byte bufferSize) { String s = ""; for (byte i = 0; i < bufferSize; i++) { s += (buffer[i] < 0x10 ? "0" : ""); s += String(buffer[i], HEX); } return s; } String CentsToEuros(long cents){ char euros[16]; sprintf(euros, "%s%ld,%02ld", cents < 0 ? "-" : "", abs(cents / 100), abs(cents % 100)); return euros; } unsigned long cooldownSecondsRemaining(unsigned long timeout, unsigned long timer) { return (timeout - (millis() - timer)) / 1000 + 1; } String getIdempotencyKey(){ const int len = 16; byte buf[len]; esp_fill_random(buf, len); return byteArrayAsHexString(buf, len); } String splitString(const String& data, char separator, int index) { unsigned int maxIndex = data.length() - 1; int strIndex[] = {0, -1}; int found = 0; for (int i = 0; i <= maxIndex && found <= index; i++) { if (data.charAt(i) == separator || i == maxIndex) { found++; strIndex[0] = strIndex[1] + 1; strIndex[1] = (i == maxIndex) ? i + 1 : i; } } return found > index ? data.substring(strIndex[0], strIndex[1]) : ""; } String cardLink(WiFiClient *wifi, HTTPClient *http, const String& apiUrl, const String& cardId) { String finalRequestUrl = apiUrl + "/api/card/" + cardId + "/link"; http->begin(*wifi, finalRequestUrl.c_str()); http->addHeader("Content-Type", "application/json"); int httpResponseCode = http->PUT(""); if (httpResponseCode == 304) return "E:Already registered."; if (httpResponseCode == 200 || httpResponseCode == 404) { String payload = http->getString(); http->end(); Serial.println(payload); StaticJsonDocument<256> json; DeserializationError error = deserializeJson(json, payload.c_str()); if (error) { Serial.println(error.c_str()); return String("E:JsonError:") + httpResponseCode; } const char* status = json["status"]; if (strcmp(status, "success") != 0) { const char* message = json["message"]; return String("E:") + message; } JsonObject data = json["data"]; const char* nickname = data["nickname"]; long balance = data["balance"]; return String("S:") + nickname + ":" + CentsToEuros(balance); } http->end(); if (httpResponseCode > 0) { return String("E:HTTP Error ") + httpResponseCode; } return String("E:Internal Error ") + httpResponseCode; } String cardBalance(WiFiClient *wifi, HTTPClient *http, const String& apiUrl, const String& cardId) { String finalRequestUrl = apiUrl + "/api/card/" + cardId + "/balance"; http->begin(*wifi, finalRequestUrl.c_str()); http->addHeader("Content-Type", "application/json"); int httpResponseCode = http->GET(); if (httpResponseCode == 200 || httpResponseCode == 404) { String payload = http->getString(); http->end(); Serial.println(payload); StaticJsonDocument<256> json; DeserializationError error = deserializeJson(json, payload.c_str()); if (error) { Serial.println(error.c_str()); return "E:JsonError"; } const char* status = json["status"]; if (strcmp(status, "success") != 0) { const char* message = json["message"]; return String("E:") + message; } JsonObject data = json["data"]; const char* nickname = data["nickname"]; long balance = data["balance"]; return String("S:") + nickname + ":" + CentsToEuros(balance); } http->end(); if (httpResponseCode > 0) { return String("E:HTTP Error ") + httpResponseCode; } return String("E:Internal Error ") + httpResponseCode; } String cardTransaction(WiFiClient *wifi, HTTPClient *http, const String& apiUrl, const String& cardId, const String& amount) { String idempotencyKey = getIdempotencyKey(); String finalRequestUrl = apiUrl + "/api/card/" + cardId + "/transaction/" + idempotencyKey + "?amount=" + amount; http->begin(*wifi, finalRequestUrl.c_str()); http->addHeader("Content-Type", "application/json"); int httpResponseCode = http->PUT(""); if (httpResponseCode == 200 || httpResponseCode == 404 || httpResponseCode == 412) { String payload = http->getString(); http->end(); Serial.println(payload); StaticJsonDocument<256> json; DeserializationError error = deserializeJson(json, payload.c_str()); if (error) { return "E:JsonError"; } const char* status = json["status"]; if (strcmp(status, "success") != 0) { const char* message = json["message"]; return String("E:") + message; } JsonObject data = json["data"]; const char* nickname = data["nickname"]; long balance = data["balance"]; return String("S:") + nickname + ":" + CentsToEuros(balance); } http->end(); if (httpResponseCode > 0) { return String("E:HTTP Error ") + httpResponseCode; } return String("E:Internal Error ") + httpResponseCode; }