#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define a 1
#define a 2
void removeFirstChar(char* str) {
if(str == NULL || strlen(str) == 0){return;}
// Shift all characters one position to the left
for(int i = 0; str[i] != '\0'; i++){str[i] = str[i + 1];}
}
char* floatToStr(float val, int decimalPlaces){
static char buf[33];
//snprintf(buf, sizeof(buf),"%.2f", val);
dtostrf(val, (decimalPlaces + 2), decimalPlaces, buf);
return buf;
}
char* intToStr(int val, int base){
static char buf[2 + 8 * sizeof(int)];
itoa(val, buf, base);
return buf;
}
char* longToStr(long val, int base){
static char buf[2 + 8 * sizeof(long)];
//ltoa(val, buf, base);
snprintf(buf, sizeof(buf),"%x", val);
return buf;
}
void toUpperCase(char* str) {
for (int i = 0; str[i] != '\0'; i++) {str[i] = toupper((unsigned char)str[i]);}
}
// Function to create PromptPay QR code string
/*0: telephone Number, 1: ID Card Number*/
char* createPromptpayCode(bool isStatic, bool accType, char* accValue, float amounts) { // รอบรับทั้งการลงทะเบียนด้วยเบอร์มือถือ หรือเลขบัตรประชาชน 13 หลัก
static char result[300];
char amountStr[15];
char amountLenStr[15];
char crcValueStr[5];
int decimalPlaces = 2;
uint16_t crcValue;
char _accValue[14];
result[0] = '\0';
strcpy(_accValue, accValue);
strcat(result, "000201"); // ID = 00, len of data = 02, data = 01
strcat(result, isStatic ? "010212" : "010211"); // ID = 01, len of data = 02, data = 11 or 12
strcat(result, "29370016A000000677010111"); // ID = 29, len of data = 37
strcat(result, accType ? "0213" : "0113"); // ID Card Number หรือ telephone Number
if(!accType){
removeFirstChar(_accValue);
strcat(result, "0066");
strcat(result, _accValue);
}else{strcat(result, _accValue);}
strcat(result, "5802TH"); // ID = 58, len of data = 02, data = "TH"
strcat(result, "5303764"); // ID = 53, len of data = 03, data = 764 -> (เป็นหมายเลขประจำค่าเงินบาทตาม ISO 4217)
// ID = 54, len of data = จำนวนหลักของยอดเงิน(ขั้นต่ำ xx.xx), data = ยอดเงิน
strcpy(amountStr, floatToStr(amounts, decimalPlaces)); // float to string
strcpy(amountLenStr, intToStr(strlen(amountStr), 10));
strcat(result, "54");
if(strlen(amountStr) < 10){strcat(result, "0");}
strcat(result, amountLenStr);
if(amounts < 10){strcat(result, "0");}
strcat(result, amountStr);
//strcat(result, "5910ABCTRFD");// test
// ID = 63, len of data = 04, data = ค่า checksum(ตัวพิมพ์ใหญ่) จำนวน 4 หลัก
strcat(result, "6304");
crcValue = calc_crcStr(result);
strcpy(crcValueStr, longToStr(crcValue, 16)); // แปลงค่า checksum ที่คำนวนได้จากข้อมูลทั้งหมดก่อนหน้าเป็น string
toUpperCase(crcValueStr); // แปลง checksum string เป็นพิมพ์ใหญ่
if(strlen(crcValueStr) < 4){strcat(result, "0");}
strcat(result, crcValueStr);
return result;
}
// Helper function to calculate CRC from a string
uint16_t calc_crcStr(char* mess) {
return calc_crc((unsigned char*)mess, strlen(mess), 0xFFFF); // Calculate CRC
}
// Function to compute the CRC using the XMODEM algorithm
uint16_t calc_crc(unsigned char* msg, int n, uint16_t init) {
uint16_t x = init;
while (n--) {
x = crc_xmodem_update(x, (uint16_t)*msg++);
}
return x;
}
// Function to update the CRC value based on the input data byte
uint16_t crc_xmodem_update(uint16_t crc, uint8_t data) {
crc = crc ^ ((uint16_t)data << 8);
for (int i = 0; i < 8; i++) {
if (crc & 0x8000) {
crc = (crc << 1) ^ 0x1021;
} else {
crc <<= 1;
}
}
return crc;
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println(a);
char telephoneNum[] = "0847129634";
float amounts = 10;
char* qrCode = createPromptpayCode(1, 0, telephoneNum, amounts);
//char* qrCode = createPromptpayCode(1, 1, "1104377485932", amounts);
Serial.println(String(qrCode));
}
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
float amounts = 34.66;
char* qrCode = createPromptpayCode(1, 0, "0853658125", amounts);
//char* qrCode = createPromptpayCode(1, 1, "1104377485932", amounts);
Serial.println(String(qrCode));
}