diff --git a/LNPay.cpp b/LNPay.cpp new file mode 100644 index 0000000..26bf38e --- /dev/null +++ b/LNPay.cpp @@ -0,0 +1,137 @@ +/** + * LNPay Payment Connector + * + * @author Tim Kijewski + * + */ + +#include +#include +#include +#include + +#include "PaymentConnector.h" + + //API Setup + String api_key = ""; // Can be found here: https://lnpay.co/dashboard/integrations + String wallet_key = ""; // Can be found here: https://lnpay.co/dashboard/advanced-wallets + + + //Endpoint Setup + String api_endpoint = "https://lnpay.co/v1"; + String invoice_create_endpoint = "/wallet/" + wallet_key + "/invoice"; + String invoice_check_endpoint = "/lntx/{{tx_id}}"; //append LNTX ID to the end (e.g. /user/lntx/lntx_mfEKSse22) + + //HTTP client + HTTPClient http; + + + //Constructor + PaymentConnector::PaymentConnector (String currency_pair) { + _currency_pair = currency_pair; + } + + + /** + * PaymentConnector::createRequest + * + * @param String method - GET,POST + * @param String path - REST path to be appended to api_endpoint + * @param String data - string of data for POST requests + * + * @return String - response data from request + * + */ + String PaymentConnector::createRequest(String method,String path, String data) + { + String payload; + int httpCode; + + Serial.println("PaymentConnector::createRequest BEGIN-------"); + Serial.println("METHOD:" + method); + Serial.println("URL:" + api_endpoint + path); + Serial.println("DATA:" + data); + + http.begin(api_endpoint + path); //Getting fancy to response size + http.addHeader("Content-Type","application/json"); + http.addHeader("X-Api-Key",api_key); + + if (method.equals("POST")) + httpCode = http.POST(data); //Make the request + else if (method.equals("GET")) { + httpCode = http.GET(); //Make the request + } else { + Serial.println("This HTTP method usage is not defined"); + } + + if (httpCode > 0) { //Check for the returning code + payload = http.getString(); + Serial.println("RESPONSE:" + payload); + } else { + Serial.println("Error on HTTP request"); + } + http.end(); //Free the resources + Serial.println("PaymentConnector::createRequest END--------"); + + return payload; + } + + + /** + * PaymentConnector::createInvoice + * + * @param int num_satoshis - number of satoshis for invoice + * @param String memo - Memo for invoice + * + * @return createInvoiceResponse - object containing both a payment_request AND an ID for lookup + * + */ + createInvoiceResponse PaymentConnector::createInvoice(int num_satoshis, String memo) { + String toPost = "{ \"num_satoshis\" : " + (String) num_satoshis +", \"memo\" :\""+ memo + String(random(1,1000)) + "\"}"; + + String payload = PaymentConnector::createRequest((String)"POST",invoice_create_endpoint,toPost); + + const size_t capacity = JSON_OBJECT_SIZE(2) + 500; + DynamicJsonDocument doc(capacity); + deserializeJson(doc, payload); + Serial.println(payload); + + const char* payment_request = doc["payment_request"]; + const char* id = doc["id"]; + String payreq = (String) payment_request; + String lntx_id = (String) id; + Serial.println(payreq); + Serial.println(lntx_id); + + createInvoiceResponse cir; + + cir.payment_request = payreq; + cir.payment_id = lntx_id; + + return cir; + } + + /** + * PaymentConnector::checkIfPaymentIsSettled + * + * @param String id - provided from the PaymentConnector::createInvoice call to check if settled + * + * @return int - 1 or 0 depending on settled + * + */ + int PaymentConnector::checkIfPaymentIsSettled(String id) { + invoice_check_endpoint.replace("{{tx_id}}",id); + String payload = PaymentConnector::createRequest((String)"GET",invoice_check_endpoint); + + const size_t capacity = JSON_OBJECT_SIZE(2) + 500; + DynamicJsonDocument doc(capacity); + deserializeJson(doc, payload); + + const char* settled = doc["settled"]; + int settledInt = (int) settled; + if (settledInt == 1){ + return 1; + } else{ + return 0; + } + } diff --git a/PaymentConnector.h b/PaymentConnector.h new file mode 100644 index 0000000..0f5f143 --- /dev/null +++ b/PaymentConnector.h @@ -0,0 +1,29 @@ +/** + * createInvoiceResponse + * + * @param String payment_request - Payment request to be saved from the createInvoice request + * @param String payment_id - to be used to poll for invoice settled or not + * + * + */ +class createInvoiceResponse { + public: + String payment_request; + String payment_id; +}; + +/** + * PaymentConnector + * + * Skeleton for functions required to make a PaymentConnector + * + */ +class PaymentConnector { + public: + PaymentConnector(String currency_pair); + createInvoiceResponse createInvoice(int num_satoshis, String memo); + int checkIfPaymentIsSettled(String id); + String createRequest(String method, String path, String data = ""); + private: + String _currency_pair; +}; diff --git a/main.ino b/main.ino new file mode 100644 index 0000000..55ccdf0 --- /dev/null +++ b/main.ino @@ -0,0 +1,42 @@ +#include +#include +#include "PaymentConnector.h" + +PaymentConnector lnpay("BTCUSD"); + +void setup() { + Serial.begin(115200); + M5.begin(); + Wire.begin(); + WiFi.begin("SSID", "PASSWORD"); + int i = 0; + while (WiFi.status() != WL_CONNECTED) { + if(i >= 5){ + M5.Lcd.fillScreen(BLACK); + M5.Lcd.setCursor(55, 80); + M5.Lcd.setTextSize(2); + M5.Lcd.setTextColor(TFT_RED); + M5.Lcd.println("WIFI NOT CONNECTED"); + } + i++; + } + + + + +} + +void loop() { + // put your main code here, to run repeatedly: + + + //createInvoiceResponse resp = lnpay.createInvoice(20,"Memo!"); + + int settled = 0; + while (!settled) { + settled = lnpay.checkIfPaymentIsSettled(resp.payment_id); + Serial.println("SETTLED:" + settled); + delay(1000); + } + +}