Madi Otel: a booking system, built and measured
The hotel had a site built in 2014 with no prices, no availability and an enquiry form that only sent an email. We replaced it with a new site in Turkish and English and a booking system where the amount is always calculated on the server and card details never reach our servers. Before it went live it was measured against fourteen security requirements. Published with the owner's permission.
Every number on this page is a measurement with a date. Where something was not measured, it says so.
What was there before
Measured on the live site and in the hosting panel on 18 September 2026.
- A site built in 2014 on a custom PHP system, moved to its current hosting in February 2026
- Three room types, a gallery, reviews, Turkish and English, a map and WhatsApp
- No prices and no availability. The reservation form only sent an email, and there was no payment
- PHP 5.3, whose support ended in 2014. Payment libraries need a much newer version, and upgrading would have broken the old site
- Seven addresses worth keeping, so they were mapped to the new site with permanent redirects
A site plus a booking system
The hotel wanted to take bookings and payment directly, without the guest leaving for a portal.
- A new site in Turkish and English
- Booking: room types, calendar, availability, a nightly price rule, a guest form, payment and confirmation
- A hotel panel: list, calendar, close a room, cancel and refund
- Legal pages for distance selling, pre-purchase information, cancellation and data protection
- One rule above all: card details must not reach our servers
Fourteen requirements, checked before launch
Measured by our own audit on 19 September 2026 on an installed copy, not on promises in a document.
The amount cannot be faked
A false amount was sent from the browser on purpose. The server ignored it and wrote its own calculated figure: three nights at the rate in its own table.
A payment notice cannot be replayed
The same payment notification was sent three times. The result was one booking, one paid record and one stored notice.
The same room cannot be sold twice
The availability count is locked while a booking is written. Twenty simultaneous attempts produced one booking and nineteen clean refusals; fifty attempts produced one and forty nine, with no errors.
The rest of the audit
The parts that are less visible but decide whether a system is safe to run.
- No card, CVV or expiry field exists anywhere in the form. The count measured was zero
- Payment notices are verified with a constant time signature check, then confirmed with the provider, then compared against the stored amount
- Twenty nine automated tests passed on the database version used in production
- The backup chain was extended to this system, then a restore was tested: all eight tables matched
- Logs keep an event type and a booking code only. No personal data is written to them
- Personal data is anonymised after thirty days, and the timer that does this was installed and observed running
- Panel access uses a hashed password, a signed cookie restricted to the panel path, an origin check and an attempt limit
- The first audit found three issues, including one high severity default that would have let the system start without proper settings. It was fixed by refusing to start at all, and that refusal was then attacked with four broken configurations and held
A thirty percent saving, and an honest limit
The images were taken from the old site and converted, and the result was measured rather than estimated.
- Thirty nine images converted: 3619.8 KB became 2544.0 KB, a reduction of thirty percent
- Two hundred and sixteen image references in the generated pages, with none missing
- The limit is the source material: the largest original is 1024 pixels wide. New photographs from the hotel would raise the saving further. The compression is not what is holding it back
Installed and running
Measured on 27 September 2026 at file level on our own server: the service is active, the web server entries for the site and the booking subdomain are enabled, and a certificate is present. The three hostnames resolve to the server.
What is not claimed here: we have not published visitor numbers, booking counts or revenue. Those belong to the hotel, and we have not measured them.
Questions about this project
Do card details pass through your servers?
No. There is no card field in the form at all, and payment happens on the payment provider's own page.
How do you know the amount cannot be changed?
Because it was attacked. A false amount was sent from the browser and the server kept its own calculated figure.
What stops a double booking?
A lock held while the booking is written. Twenty simultaneous attempts produced one booking and nineteen refusals, and fifty produced one and forty nine.
Was the old site thrown away?
No. Seven addresses worth keeping were mapped to the new site with permanent redirects.
Can we see visitor or revenue numbers?
We do not publish them. They belong to the hotel and we have not measured them.
Tell us what you want built
You get a written scope with the price within one working day. Nothing is stored on our server: your details turn into a WhatsApp message and sending stays your choice.
