Wachirawith Yadee / backend

● Open for small jobs · remote / async · Thailand time (UTC+7)

Find where the data goes wrong, then fix it

Junior backend / API developer. I investigate backend bugs, connect APIs, and review an existing system before it is redesigned. I always write down what I understood, so you can check it first.

01

Try it:webhook signatures

A payment system must be sure a request really came from the provider. Edit the message a little and see why I check the raw bytes before reading any content.

1 · Sender: signature of the original message

…

2 · Receiver: the message that arrived (editable)

3 · Receiver: signature computed from what arrived

…

4 · Compare (constant time)

The bytes differ from what was signed, so the content is never read.

Try "Add one space" or "Re-format the JSON": the meaning of the JSON does not change, but the signature no longer matches, because a signature is computed over bytes. The receiver must check the raw body before parsing, then read the values. My system works in that order.

This example computes HMAC-SHA256 in your browser with a made-up key, demo-secret-key. It has nothing to do with any real system's key.

02

Try it:the many ways a webhook arrives

Real situations a payment system must survive: retries, paying twice through two channels, wrong amounts, a QR that expires before the money arrives. Pick one and watch each decision step.

Incoming request · POST /beam/webhook

x-beam-signature: valid
body: SUCCEEDED · THB · 15000 satang

    Before the webhook

    Bill total
    ฿150.00
    payment
    pending
    order
    served
    Note
    —

    After the webhook

    Press "Send webhook" to see the result

    A simulation of the real code in rice-shop-pos (promptpay.rs · webhook / settle). It is not connected to Beam or any live system.

    03

    rice-shop-pos

    A personal project: a multi-branch POS PWA for rice shops. The code is public. It is not work from my employer, and I make no claims about users or revenue.

    Money
    Stored in satang as whole numbers. No decimals.
    Financial history
    Orders and payments are append-only. A cancellation or refund is a status with a reason. Nothing is deleted.
    PromptPay payments
    A QR code is created through Beam, then the system waits for a webhook whose signature is checked on the raw bytes. A bill closes only when Beam reports success for exactly the right amount. Staff have no button to close it by hand.
    Many shops
    Every table has a shop_id. The owner signs in through Cloudflare Access. Staff use a PIN, with a lockout after repeated wrong tries.
    Reading slips
    Slips go to a reader on the owner's PC first. If that is offline, Workers AI is the fallback. A job sweeps the queue every minute.
    Shipping
    CI runs on every push and PR. A deploy only happens when you push a tag that is on main.
    • Rust (axum)
    • Cloudflare Workers
    • D1
    • R2
    • React PWA
    • GitHub Actions
    04

    How I work

    • Write down what I understood, for you to check firstA summary of the problem, my assumptions and open questions, confirmed by you before I start.
    • Walk through edge cases that touch money and stateDouble presses, cancelling halfway, data arriving twice or out of order.
    • AI is my assistant, not the owner of the workI use it to analyse, compare options and review. The logic and the checking are my responsibility.
    • Deliver in steps you can acceptPayments are split into milestones. If the first step is not right, you do not have to continue.

    What I don't take on

    • Senior-level work, or owning a production architecture
    • DevOps / running live systems around the clock
    • Design-heavy frontend work or native mobile apps
    • Real work without pay
    05

    Tell me aboutthe problem

    I have a full-time job, so I work asynchronously in the evenings and on weekends. I reply within 1 working day.

    Emailvote1995 [at] gmail [dot] comLINEvote1995LinkedInWachirawith YadeeGitHubgithub.com/vote1995