#ภาษาไทย

Bank Open API QR Payments — From Sandbox to Status Lifecycle
A static PromptPay QR is easy to build yourself, but nothing tells you whether the customer has paid. This article walks through a bank's Open API sandbox, from requesting a token and issuing a dynamic QR to tracking REQUESTED/PAID/CANCELLED/VOIDED states and the requestDt trap that rejects requests even when the entire payload is correct.

Migrating an Old .aspx Site to a JSON Catalog and Filtering Images
The owner of an old .aspx site asked me to rebuild it, but more than a decade of content was in a database I could no longer access. I collected the pages from the site itself to build a JSON catalog that preserved every legacy_id, then wrote a three-layer image filter to keep stray QR codes from becoming article covers.

Let Clients Pick Photos on a Web Page Without a Login
When the person choosing photos for a website is not comfortable with computers, adding registration and login means the work stops at the login screen. This article covers a photo picker with no authentication at all, but with a server endpoint that checks every value against an allowlist strict enough to leave nothing from arbitrary input, plus limits at every layer and a backup before every write.

Scripting Government PDF Forms and Making Safer ID Copies
Government PDFs distributed as fillable forms often cannot actually handle Thai text. Subdivided fields let digits run over the borders, and tone marks collide with vowels above the line. This article covers listing field names first, filling the fields and flattening them into page content, drawing Thai text with a font that includes all the vowel marks, and making actual-size ID copies with purpose-specific watermarks.

Building a Graph API Page App with Three Required Endpoints
When a backend needs to read and reply to Page messages on its own, the only proper route is to build an app and pass the platform's review. This article covers three endpoints the platform requires but people forget until they fail review, the correct way to verify incoming request signatures, and the steps to exchange a short-lived token for a Page token stored outside the web root.

A Report Form for a Static Site with No Backend
A calculator site made entirely of static files has no server to handle forms, but users still need a way to report mistakes in the formulas. This article covers the one approach I chose—a single worker file that accepts POST requests on one route, verifies Turnstile on the server using the real client IP, accepts images pasted from the clipboard, and sends email from the network edge—along with three traps that cost me an entire night.

Speed Up Screen Recordings While Keeping the Original Clock
How to make a timelapse from a screen recording by speeding up idle sections more than active sections, using split, trim, and setpts, then joining them with concat. The main trap is that drawtext must come before setpts for the clock to follow the original timeline instead of the accelerated one.

A Cookie Banner That Loads GTM and GA4 Only After Consent
Most cookie banners look good but block nothing, because GTM and GA4 have already loaded from the first line of the page. This article covers a setup that loads the container only after acceptance, puts GA4 inside GTM to prevent double counting, hides AdSense slots initially, and checks that outgoing requests to those services stay at zero.

Reading ID Cards from the Web with a Localhost Agent
Browsers cannot access smart card readers directly. A workable approach is to write a small agent that opens a port on localhost and let the web page call it. This article covers secure contexts, CORS preflight, port conflicts with other agents, PC/SC in SHARED mode, decoding TIS-620 manually, and the day antivirus flagged the program as a backdoor.

Food Factory Drawings: Sheets, Scales, and Paper Sizes
A food factory application drawing set has 7 items, each with its own scale range, and some numbers to work out before drawing—how wide a plan will fit on A4 or A3 at 1 to 100, and how to split it across sheets without changing the scale if it will not fit.

From Model to 6-Meter Steel Cutting Layout and Workshop Cut Sheet
Read part lengths from the model, consolidate duplicates, then arrange a first-fit decreasing cutting layout on standard 6-meter stock with a 3-millimeter saw kerf allowance, plus a notch-and-bend option for right-angle corners that reduces joints from 12 to 6

Quantity Takeoff from SketchUp Models with Ruby Scripts
A finished model already contains every number a quantity takeoff needs. Give groups readable names from the start, then write a script to grep through them, with two traps to watch for that can double your areas.

SketchUp Drawing Sheets with Automatic Labels and Dimensions
A finished model is not ready for submission yet. What the authorities accept is a set of paper sheets with building numbers, dimension lines, a north arrow, and a scale. This article covers extracting geometry from the model as numbers, rendering a top ortho view as black lines on white, and letting a script place numbers and dimension lines without overlaps, with overrides for individual items.

Mapping a Building by Phone and Finding True North with GNSS
ARCore gives room-corner coordinates in meters accurately enough to use, but its world frame has an unknown orientation, so the resulting plan is always rotated by some angle. The fix is to collect pairs of (AR position, GNSS reading) while working, then fit a rotation using weighted 2D Kabsch, with weights based on each fix's accuracy, to find both north and the origin's coordinates.

Rebuilding an Off-Scale PDF Plan at Real Dimensions
Presentation plans are often drawn block by block, with different scales for the x and y axes and different scales again for each room. Calibrating the whole page once and tracing it gets everything wrong. This article covers extracting coordinates from paper into metres by recalculating the scale for every room, counting objects with colour-blob BFS instead of by eye, and drawing them back into a model at their real dimensions.

Shared Neutrals Across Transformers: Why Phase Balancing Is Not Enough
A case involving two transformers with interconnected neutrals and houses tapped into one side's main feeder, leaving phase A 30-40 A higher even on days off, plus a meter-reading trap that can suggest a 200 A difference if the CT ratio is not verified first, and a repair sequence that must be followed in order.

Sizing Main Cables and Breakers by Installation Method
Notes on choosing the main cable and breaker for a new 253 A feeder, why the same size CV cable can carry 227 A or 364 A depending on how it is installed, and the option of downsizing to 95 and compensating with operating rules, at the cost of the main breaker tripping if anyone breaks those rules.

Diagnosing Feeder Overload from Melted Insulation and Duty Cycles
My investigation of a 95 mm² main cable with insulation melting at scattered points even though the system seemed to work normally, from the nameplates of 6 washers and dryers totaling 234.7 kW to a minute-by-minute current model explaining why a 482 A load on a cable rated for 180 A had not caused a visible system failure.

A Single-Page PHP and SQLite Document Vault That Keeps Originals
A document photo storage app for government submissions, using photos taken on site with a phone. Each upload produces three files—the display image, the original, and saved crop settings—so adjustments can be made later without losing quality, with automatic migration from JSON to SQLite and web server restrictions on folders containing personal data.

Printing Dozens of Government Forms from HTML with Correct Margins
A government submission document system where users click Print in their browsers and every sheet must fit within its margins, from measuring the actual printable area in millimeters and repeating headers and footers without position fixed, to four image frame types for different documents and automated overflow checks with Playwright instead of inspecting every sheet.

News Stuck for Three Days Because the Feed Wasn't Sorted by Date
The news site's homepage showed the same day's stories for three days straight, even though scheduled jobs ran, translations finished, and every step reported success. The causes were an RSS feed sorted by relevance rather than date, string sorting of pubDate that actually sorted by weekday name, and requesting too few stories, leaving nothing after filtering before the rest even got a look.

Generating Thai PDF Quotes with Chromium and the Pitfalls I Hit
Building a system to generate PDF quotations from HTML with Chromium for multiple companies in a group and multiple templates, from an Executable doesn't exist error caused by looking for the wrong headless shell, to A4 layout and pagination, sanitizing Thai filenames, and a token-based document numbering system where an accidental slash broke the path.

Thai Steel Framing Conventions for Buildable Drawings
A steel frame model that looks good on screen but makes a fabricator shake their head usually gets a few conventions wrong—member order, stock sections, stacking instead of interweaving, purlins that must be open C sections, and bearing edges on sloping beams that cause steel to intersect when chosen incorrectly.

Import Land Parcel Boundaries from Government Maps into SketchUp
A SketchUp model with Add Location has satellite imagery but no parcel boundaries. This article covers fetching boundaries through OGC-standard WFS, where viewparams is required to avoid getting zero features, converting UTM47 coordinates to WGS84, and placing them in the model with latlong_to_point to line up with the imagery.

WAF Returns 406 for Thai Text in POST: Fixing It Without Root
ModSecurity on the host returns 406 for certain Thai sentences in the POST body, preventing forms from saving — but as a hosting tenant, I cannot change the rules myself. This article shows how to isolate the offending text through black-box testing, then work around it with JS encoding on submit + middleware decoding in Laravel.

Bulk Import Legacy .xls Files into Laravel with PhpSpreadsheet
Legacy .xls files with Thai headers encoded in tis-620 have unreadable column names, large files make PhpSpreadsheet exhaust memory and crash, and files users merge themselves contain duplicate rows — use column positions instead of names, add a read filter, and deduplicate with a natural key.

Charset Mismatch Silently Kills JOIN Indexes — an utf8mb4 Mirror
The old database uses tis620 and the new one uses utf8mb4. JOIN across databases, and every index immediately becomes decorative without a single error — how to prove it with EXPLAIN and build a mirror that converts tis620 to utf8mb4 during the dump, plus the sed trap that silently breaks tables.

Thai Data Migration Traps: VARCHAR, Idempotency, and OCR Vowels
Lessons from importing and migrating hundreds of thousands of Thai data rows — undersized VARCHAR columns silently truncating synthetic keys into collisions, idempotency requiring DELETE before INSERT to stop totals reaching 200%, collation treating su001 and SU001 as equal while storing both, and Thai vowels corrupted by OCR that need a normalization map before insert

Government ICT Computer Price Criteria + DIY Builds with Scripts
The December 2568 government ICT reference price criteria clearly define specifications for 20,000 baht office computers and 24,000 baht processing computers. In this article, I read the actual criteria item by item, then write a Python script to pull Advice prices and put together DIY builds to compare how much better the value is than buying prebuilt machines.

~30 Seconds Turns Tiny: Flarum's Litedown Subscript Trap
Write "~30 seconds" in a Flarum post and 30 turns into a tiny subscript — because Flarum's Litedown interprets ~ as a subscript opener. Thai users who use ~ to mean "approximately" run into this regularly. This article explains the cause, workarounds, and database fixes for content stored as s9e XML rather than raw markdown.

Generate PromptPay QR (EMVCo) in Pure Python — No External Libraries
Want to generate PromptPay payment QR codes in your own POS/web system without calling a bank API? In this article, I build the EMVCo TLV string + CRC16 myself in pure Python, producing a payload that matches the Thai QR specification and can be scanned for payment by any banking app, along with the pitfalls that stop apps from reading it.