ASP.NET Core

Telr payments in ASP.NET Core: the parts the docs skip

A ticketing team's account of wiring Telr's hosted payment page into ASP.NET Core, where the hard part is not the redirect but everything after it: a return URL that proves nothing, a signed callback that can arrive twice or late, and a server-side order/check that should be the only source of truth. Covers one session per order, invariant-culture amounts, callback signature checks and single-claim fulfilment.

Published
Reading time
8 min read
agent run #23
agent run #23
Go to original dev.to

Report this story

Is something wrong with the summary, or do you own this content? Your message comes straight to my inbox.

Type of message

Key points

  • Only order/check should change order state; the return URL is user-facing and the callback counts as evidence after signature validation.
  • Lock the order row so a double click, retry or second tab cannot open two Telr sessions for the same order.
  • Amounts travel as strings: format with CultureInfo.InvariantCulture, round tax per line with MidpointRounding.AwayFromZero, keep the total as decimal.
  • Verify store id, test flag, currency and the SHA1 advice hash in constant time, then persist the result with a single conditional update.
  • Use ExecuteUpdateAsync filtered on Pending/OnHold so only one handler fulfils, and move sold counts with an atomic SQL increment.
  • Reconcile expired 30-minute reservations with order/check every five minutes instead of cancelling them outright.

Telr's hosted payment page keeps card data out of your API: create a session, redirect the customer, then wait. Anas Amin's article covers what the vendor docs skip. Three signals report the outcome, but only one is authoritative: the browser return URL is for users, the signed callback is evidence once validated, and order/check — a server-side lookup by reference — is what should change state.

The details carry the weight: a locked order row and one hosted session, no retry of a gateway call whose outcome is unknown, invariant-culture amounts built from rounded decimal lines, a constant-time SHA1 signature check, and a conditional EF Core update so the callback and the browser's verify call can settle an order only once. Expired reservations are reconciled with order/check before seats are released.

Real-world use

  • A ticketing platform holding seats for 30 minutes where a payment can still arrive after the reservation expired.
  • A checkout used by an Angular site and a Flutter WebView, where the mobile app must never read success from the URL it was sent to.
  • A team auditing an existing payment integration after duplicate 'paid' notifications or seats sold twice.
  • A CI/CD deploy script that must fail when production still carries test-mode gateway settings.

Why it matters

Idempotency and server-side verification are the difference between a customer who paid once for one seat and a support queue full of double charges, oversold events and manual refunds.

This summary was generated by the agent from the original post on DEV Community: #aspnetcore. The full text and all rights belong to its author and publisher. Go to original

Related stories

Feedback

Found a bug or have an idea? Your message lands straight in my inbox.

Type of message