Skip to main content

Go live

When your integration works end to end in development, a few steps move it to production: link your real bank account, connect your real e-invoice account, switch keys and environment, make sure your handlers are strict, then test with a small real transfer. This page walks through each step and ends with what to watch once you are live.

Before you start​

Make sure the whole flow works in development:

  • A payment created from your checkout reaches paid after a simulated transfer.
  • Your IPN handler verifies the signature, updates the order once, and answers 2xx.
  • Partial payments, overpayments, expiry and late money behave the way you want (see the test scenarios).
  • If you issue invoices, a sandbox invoice reaches issued.

Nothing carries over between environments: bank accounts, matching settings, payments, invoice providers and integration keys all have to exist in production too.

Switch the dashboard to production (the environment bar on top of the Payments pages, Switch to production), then open Payments settings → Bank accounts → Add bank account and pick your bank:

BankWhat you need
MB BankThe account number, the holder's name as MB has it, and the national ID or tax code the account was opened with. MB texts a code to the holder's registered phone
BIDVRegister BIDV's balance notification service for the account at BIDV, then add the account. It activates when BIDV sends its first message
ACBThe account number. The holder then consents on ACB's page; the consent lasts up to 180 days
Pay2SThe account linked on Pay2S, a Hook pointing at the URL shown in the form, and the Hook's token

The details are in Bank connections. Then set the matching settings for the production account again: the payment code prefix, your own order code format, and which transfers transaction.received reports.

caution

The person who receives the bank's code or consents on the bank's page must be the account holder, or someone they authorized. Plan the link for a time they are available.

2. Connect your e-invoice provider​

If you issue invoices, open Payments settings → Invoice providers in production and connect your real Mắt Bão account: the tax code, API user and password from "Cấu hình API" in the Mắt Bão portal. Pick the template and series registered for your business, and choose what happens when a paid order asks for an invoice: stop at the draft, or send it for approval.

Then send the connection's callback URL to Mắt Bão support, so that changes made on their side reach Ha Tang at once. See E-invoices.

3. Switch keys and environment​

SettingDevelopmentProduction
EnvironmentHatang-Environment: development or SDK environment: "development"Remove the header and the option (or send production)
IPN secret keysk_test_…sk_… from Payments settings → Integration keys in production
Webhook secretwhsec_…The same endpoint serves both environments; keep its secret
API keyht_… with payments:read, payments:writeThe same key works; create a separate one per server if you prefer

Keep these values in configuration, not in code:

HATANG_API_KEY=ht_123...
HATANG_SECRET_KEY=sk_123... # production secret key, for IPN
HATANG_WEBHOOK_SECRET=whsec_123... # webhook endpoint secret
# HATANG_ENVIRONMENT unset in production

4. Check your endpoints​

  • Your ipn_url and webhook endpoint are https on the public internet, answer 2xx within 10 seconds (15 for webhooks), and do not redirect.
  • They read the raw body for verification (no JSON middleware before it).
  • The webhook endpoint is subscribed to the events you need, for example payment.succeeded, payment.overpaid, transaction.received, bank_connection.revoked, invoice.failed.
  • Trust the signature, not the caller's IP address.

5. Make your handlers strict​

Your handler must:

  1. Verify the signature with the production key, and reject anything that does not verify.
  2. Check environment is production; a development payment must never unlock a real order.
  3. Compare paid_amount with the order total.
  4. Dedupe on the IPN id or the webhook svix-id.
  5. Move the order forward only, whatever order the calls arrive in.

Before you hand over goods after the payer returns to return_url, confirm on the server with GET /payments/{id} or the SDK's payments.verify().

6. Test with a small real transfer​

  1. Create a payment in production for a small amount, for example 10,000 VND, with your real ipn_url.
  2. Pay it from your own banking app by scanning the QR.
  3. Check that the payment becomes paid (for ACB, allow up to 10 minutes: Ha Tang reads its history on that cycle), that your IPN arrived (GET /payments/{id}/ipn-deliveries), and that the transfer is listed under Payments → Transactions.
  4. If the order asked for an invoice, check it reaches issued and has a number.
  5. Then test the mistakes: pay a second small payment without the code and confirm that transaction.received arrives with payment_id: null.

The money lands in your own account; nothing needs refunding through Ha Tang.

7. Watch it once you are live​

What to watchWhere
IPN calls that keep failingGET /payments/{id}/ipn-deliveries (status: "exhausted"), and the payment page
Webhook deliveries that failGET /webhooks/{id}/deliveries, and Webhooks in the dashboard
A bank account that stops workingbank_connection.revoked and bank_connection.needs_reauth webhooks; the account's status and last transaction under Bank accounts
ACB consent expiryThe connection's consent.expires_at; link the account again before it passes
Stuck calls to banks or the invoice providerPayments → Integration health
Invoices that failed or were rejectedinvoice.failed, invoice.tax_rejected webhooks, and the alert emails Ha Tang sends to owners and admins
Money in without an invoicePayments → Invoice reconciliation, and the daily email at 08:00
Transfers the bank never reportedImport a statement for the missing days

Launch checklist​

  • The real bank account is linked and active in production.
  • The production account's matching settings are set.
  • The e-invoice provider is connected in production, with the right template, and Mắt Bão has the callback URL.
  • The production secret key and the webhook secret are configured on your server.
  • The Hatang-Environment: development header (or the SDK option) is gone from production.
  • Your handlers check the signature, environment, the amount and duplicates, and move orders forward only.
  • The IPN and webhook URLs are public https and answer 2xx within 10 seconds.
  • A small real transfer went through end to end.
  • Someone watches failed deliveries, bank_connection.* events and invoice alerts.

Next steps​

View this page as Markdown