#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <ArduinoJson.h>
// WiFi
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// MQTT
const char* mqtt_server = "broker.hivemq.com";
WiFiClient espClient;
PubSubClient client(espClient);
// LCD
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Keypad
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {13, 12, 14, 27};
byte colPins[COLS] = {26, 25, 33, 32};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// STATES
int step = 0;
String type = "";
String number = "";
String cvv = "";
String pin = "";
void callback(char* topic, byte* payload, unsigned int length) {
String msg = "";
for (int i = 0; i < length; i++) msg += (char)payload[i];
lcd.clear();
if (msg.indexOf("success") != -1) {
lcd.print("PAYMENT OK");
} else {
lcd.print("FAILED");
}
delay(3000);
resetFlow();
}
void reconnect() {
while (!client.connected()) {
if (client.connect("ClientESP32")) {
client.subscribe("payment/response");
}
}
}
void showMenu() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("1.Debit 2.Crd");
lcd.setCursor(0,1);
lcd.print("3.UPI");
}
void resetFlow() {
step = 0;
type = "";
number = "";
cvv = "";
pin = "";
showMenu();
}
void setup() {
lcd.init();
lcd.backlight();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED);
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
showMenu();
}
void loop() {
if (!client.connected()) reconnect();
client.loop();
char key = keypad.getKey();
if (!key) return;
// STEP 0 → SELECT TYPE
if (step == 0) {
if (key == '1') { type = "debit"; step = 1; }
else if (key == '2') { type = "credit"; step = 1; }
else if (key == '3') { type = "upi"; step = 1; }
lcd.clear();
lcd.print("Enter Number:");
return;
}
// STEP 1 → ENTER NUMBER / UPI
if (step == 1) {
if (key == '#') {
step = (type == "upi") ? 3 : 2;
lcd.clear();
if (type == "upi") {
lcd.print("Enter PIN:");
} else {
lcd.print("Enter CVV:");
}
} else {
number += key;
lcd.setCursor(0,1);
lcd.print(number);
}
return;
}
// STEP 2 → ENTER CVV
if (step == 2) {
if (key == '#') {
step = 3;
lcd.clear();
lcd.print("Enter PIN:");
} else {
cvv += key;
lcd.setCursor(0,1);
lcd.print("***");
}
return;
}
// STEP 3 → ENTER PIN
if (step == 3) {
if (key == '#') {
sendData();
} else {
pin += key;
lcd.setCursor(0,1);
lcd.print("****");
}
return;
}
}
void sendData() {
StaticJsonDocument<256> doc;
doc["type"] = type;
doc["number"] = number;
doc["cvv"] = cvv;
doc["pin"] = pin;
char buffer[256];
serializeJson(doc, buffer);
client.publish("payment/request", buffer);
lcd.clear();
lcd.print("Processing...");
}