Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

💸 CYD PromptPay Terminal (Stripe)

English · ภาษาไทย

A tiny self-contained payment terminal: an ESP32 with a 2.8" touch screen that displays a Thai PromptPay QR generated through Stripe, then flips to a green success screen (with a beep!) the moment the customer's payment lands.

PlatformIO License

QR screen

How it works

boot ─▶ WiFi ─▶ enter amount on touch keypad ─▶ create QR via Stripe ─▶ show QR
                     ▲                                                  │ poll every 3 s
                     │              tap screen                          ▼
                     ◀────────────────────────────────────  PAYMENT RECEIVED ✓
  1. Enter the amount on the on-screen keypad (minimum 10 THB — Stripe's floor for PromptPay)
  2. The board creates a PaymentIntent (amount, currency=thb, payment_method_types[]=promptpay, confirm=true) — one call to the fully documented Stripe API, and the response already contains the EMVCo QR payload
  3. The QR renders on the white card; the board polls the PaymentIntent every 3 seconds
  4. succeeded → full-screen green check + beep. Tap to return to the keypad.

No Payment Link needed — a single secret key is enough to take payments.

The library also keeps a legacy createQr() that derives the QR from a Payment Link via Stripe's undocumented checkout endpoints. It breaks with payment_method_types_mismatch when the link doesn't offer PromptPay — prefer createQrDirect().

Getting your Stripe keys

All three values come from the Stripe Dashboard:

Value Where
pk_live_... publishable key Developers → API keys (only needed for the legacy Payment Link path)
sk_live_... secret key Developers → API keys (click Reveal)
plink_... payment link id (optional, legacy path only) Payment Links → create one — the id is in its details

PromptPay must be enabled in Settings → Payment methods (Thai Stripe accounts).

🔐 Security — read before you commit anything

  • Keys live in include/secrets.h, which is gitignored. Copy the template and fill it in:

    cp include/secrets.h.example include/secrets.h
  • The secret key can move money-related state on your account. If it ever leaks — a screenshot, a pastebin, a committed file — roll it immediately: Dashboard → Developers → API keys → ⋯ → Roll key.

  • Better: instead of sk_live_..., create a restricted key (Developers → API keys → Create restricted key) with only PaymentIntents read/write — that's all this project needs.

  • TLS note: the firmware uses setInsecure() (no certificate pinning), standard practice on ESP32 hobby projects but worth knowing.

Hardware

Runs on a 2.8" ESP32 display board of the CYD family (pinout-compatible with the well-documented ESP32-2432S028R). Everything is on the board — screen, touch, speaker for the payment beep. No wiring.

👉 The exact board used: Shopee listing

If colors look inverted remove -D TFT_INVERSION_ON=1 from platformio.ini; if touch is offset adjust touch.setCal(...) in src/main.cpp.

Getting started

git clone https://github.com/moomdate/CYD-PromptPay-Terminal.git
cd CYD-PromptPay-Terminal
cp include/secrets.h.example include/secrets.h   # fill in WiFi + Stripe values
pio run -t upload

The screen walks through: connecting WiFi → amount keypad → QR screen with the amount → success screen. Errors show Stripe's message with a tap-to-retry.

Configuration in include/secrets.h:

Setting Meaning
UI_LANGUAGE on-screen language: LANG_TH or LANG_EN (Thai Sarabun font is embedded in the firmware)
AMOUNT_SATANG default amount when nothing is typed, in satang (1000 = 10.00 THB)

The StripePromptPay library

The Stripe logic is a standalone library published on the PlatformIO Registry (source) — use it in any project:

lib_deps = moomdate/StripePromptPay @ ^1.0.0
#include <StripePromptPay.h>

StripePromptPay stripe;
stripe.begin(STRIPE_PK, STRIPE_SK);

if (stripe.createQrDirect(1000, "you@example.com")) {  // 10.00 THB
  render(stripe.qrData());                 // EMVCo payload for any QR lib
  String st = stripe.paymentStatus();      // "requires_action" → "succeeded"
}
Serial.println(stripe.lastError());        // populated on failure

It has no display dependencies — just WiFi + ArduinoJson — so it works on any ESP32.

Project structure

include/
├── secrets.h.example  # template — copy to secrets.h (gitignored)
src/
├── main.cpp           # UI: amount keypad, QR card, polling, success screens
├── lang.h             # EN/TH string tables (UI_LANGUAGE)
├── fonts/             # Sarabun (OFL) smooth fonts with Thai glyphs
tools/gen_vlw.py       # regenerate the fonts from any OFL TTF

Stripe logic comes from the StripePromptPay registry package.

License

MIT

About

A $6 PromptPay payment terminal — ESP32 + 2.8" touch screen, powered by Stripe. Enter amount, show QR, beep when paid. Thai/English UI.

Topics

Resources

Stars

52 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages