How PDP reserves apartments through bank payment links
In PDP, we connected an acquiring bank for online apartment reservations: payment links with TTL, a redirect to the bank page, and a callback with digital signature verification.

“A reservation should not live forever.”
A user selects an apartment in PDP, chooses a financing type — mortgage, installment plan, or full payment — and clicks to pay for the reservation. From there, the flow should be boring: the bank page opens, the payment goes through, and the reservation is confirmed. Without the feeling that the money went into one system while the apartment stayed in another.
The engineering part starts the moment PDP generates a payment link. The link is valid for a limited time: it has a TTL. That matters for reservations, because an apartment cannot wait forever for a user who went to get coffee, closed the tab, or decided to come back tomorrow.
What the user sees
In the user flow, there is no card form inside PDP. After selecting the reservation terms, the user is sent to the acquiring bank’s page. There they enter payment details, confirm the transaction, and return back.
This route looks familiar: the bank is responsible for the payment page, and PDP is responsible for the reservation state. The boundary of responsibility is clear for both the user and the implementation.
But there is an important detail here: a user returning from the bank page cannot be treated as proof of payment. The tab may be closed. The redirect may never arrive. The user may click Back. That is why PDP makes the final reservation decision not based on the return to the UI, but on the bank callback.
The lifecycle of a payment link
For every payment attempt, PDP creates a payment link with the acquiring bank. The link includes a time limit for how long it can live. As long as the TTL has not expired, the user can follow the link and complete the payment on the bank’s side.
Once the TTL expires, the link should no longer hold the reservation. That is the part users usually do not spell out, but clearly feel: if the link has expired, the system should not pretend that the old attempt is still payable.
The most unpleasant class of errors in this setup is status mismatch. For example, the user pays on the bank page but does not return to PDP. Or the opposite: they return, but the payment has not been confirmed yet. That is why the redirect was kept as a user flow, not as the source of truth.
Callback and the bank signature
The acquiring bank sends a callback to PDP after a payment event. At this step, it is not enough to trust that an HTTP request reached the right endpoint. PDP verifies the bank’s digital signature in the callback.
The point of the check is simple: PDP must make sure the payment status came from the bank, not from someone who knows the handler URL. Only after signature verification can the reservation state be changed.
There was a real but useful discussion here: where to draw the line between “the user sees a success screen” and “the reservation is actually confirmed.” We decided to rely on the bank callback. The screen after the return can indicate that the payment is being processed, but the reservation status changes only on a signed message from the acquirer.
Mortgage, installment plan, and full payment
PDP had to account for three financing types: mortgage, installment plan, and full payment. For the user, these are different ways to buy an apartment, but for the integration with the acquirer they converge in one place: paying for the reservation through a payment link.
We did not mix the business logic for choosing the financing type with handling the bank callback. The financing type is fixed in the reservation flow, while the payment integration handles its own responsibilities: create a link with TTL, send the user to the bank, accept the callback, verify the digital signature, and update the status.
This setup has fewer hidden dependencies. If the rules for mortgages or installment plans change later, the bank callback handler does not turn into a place where half the product logic suddenly lives.
The next area to watch in integrations like this is the user-facing texts and states: the link has expired, the payment is pending confirmation, the reservation is confirmed, the payment failed. These statuses are what turn a bank integration from a set of endpoints into a clear reservation flow.