diff --git a/apps/upi_core/lib/upi_core/upi_xml_schema.ex b/apps/upi_core/lib/upi_core/upi_xml_schema.ex
index 8904e9f..108f86b 100644
--- a/apps/upi_core/lib/upi_core/upi_xml_schema.ex
+++ b/apps/upi_core/lib/upi_core/upi_xml_schema.ex
@@ -1533,17 +1533,38 @@ def parse_req_hbt(xml_string) do
       Floki.attribute(doc, "txn", "note") |> List.first() ||
       Floki.attribute(doc, "ns2:txn", "note") |> List.first()
 
+    # [RespHbt Txn.refId] CHANGED: Floki lowercases attribute names, so Floki.attribute(doc, "txn", "refId") never matched and ref_id was always nil - the manager then sent a generated REF<ms> (precert: REF1787303895328). Also look up the lowercase "refid".
+    # TSD Table 8: RespHbt Txn refId = refId received in ReqHbt
+    # OLD:     ref_id =
+    # OLD:       Floki.attribute(doc, "Txn", "refId") |> List.first() ||
+    # OLD:       Floki.attribute(doc, "ns2:Txn", "refId") |> List.first() ||
+    # OLD:       Floki.attribute(doc, "txn", "refId") |> List.first() ||
+    # OLD:       Floki.attribute(doc, "ns2:txn", "refId") |> List.first()
     ref_id =
       Floki.attribute(doc, "Txn", "refId") |> List.first() ||
+      Floki.attribute(doc, "Txn", "refid") |> List.first() ||
       Floki.attribute(doc, "ns2:Txn", "refId") |> List.first() ||
+      Floki.attribute(doc, "ns2:Txn", "refid") |> List.first() ||
       Floki.attribute(doc, "txn", "refId") |> List.first() ||
-      Floki.attribute(doc, "ns2:txn", "refId") |> List.first()
-
+      Floki.attribute(doc, "txn", "refid") |> List.first() ||
+      Floki.attribute(doc, "ns2:txn", "refId") |> List.first() ||
+      Floki.attribute(doc, "ns2:txn", "refid") |> List.first()
+
+    # [RespHbt Txn.refUrl] CHANGED: same attribute-name lowercasing problem - also look up "refurl"
+    # OLD:     ref_url =
+    # OLD:       Floki.attribute(doc, "Txn", "refUrl") |> List.first() ||
+    # OLD:       Floki.attribute(doc, "ns2:Txn", "refUrl") |> List.first() ||
+    # OLD:       Floki.attribute(doc, "txn", "refUrl") |> List.first() ||
+    # OLD:       Floki.attribute(doc, "ns2:txn", "refUrl") |> List.first()
     ref_url =
       Floki.attribute(doc, "Txn", "refUrl") |> List.first() ||
+      Floki.attribute(doc, "Txn", "refurl") |> List.first() ||
       Floki.attribute(doc, "ns2:Txn", "refUrl") |> List.first() ||
+      Floki.attribute(doc, "ns2:Txn", "refurl") |> List.first() ||
       Floki.attribute(doc, "txn", "refUrl") |> List.first() ||
-      Floki.attribute(doc, "ns2:txn", "refUrl") |> List.first()
+      Floki.attribute(doc, "txn", "refurl") |> List.first() ||
+      Floki.attribute(doc, "ns2:txn", "refUrl") |> List.first() ||
+      Floki.attribute(doc, "ns2:txn", "refurl") |> List.first()
 
     txn_timestamp =
       Floki.attribute(doc, "Txn", "ts") |> List.first() ||
@@ -1557,11 +1578,21 @@ def parse_req_hbt(xml_string) do
       Floki.attribute(doc, "txn", "type") |> List.first() ||
       Floki.attribute(doc, "ns2:txn", "type") |> List.first()
 
+    # [RespHbt Txn.custRef] CHANGED: same attribute-name lowercasing problem - also look up "custref"
+    # OLD:     cust_ref =
+    # OLD:       Floki.attribute(doc, "Txn", "custRef") |> List.first() ||
+    # OLD:       Floki.attribute(doc, "ns2:Txn", "custRef") |> List.first() ||
+    # OLD:       Floki.attribute(doc, "txn", "custRef") |> List.first() ||
+    # OLD:       Floki.attribute(doc, "ns2:txn", "custRef") |> List.first()
     cust_ref =
       Floki.attribute(doc, "Txn", "custRef") |> List.first() ||
+      Floki.attribute(doc, "Txn", "custref") |> List.first() ||
       Floki.attribute(doc, "ns2:Txn", "custRef") |> List.first() ||
+      Floki.attribute(doc, "ns2:Txn", "custref") |> List.first() ||
       Floki.attribute(doc, "txn", "custRef") |> List.first() ||
-      Floki.attribute(doc, "ns2:txn", "custRef") |> List.first()
+      Floki.attribute(doc, "txn", "custref") |> List.first() ||
+      Floki.attribute(doc, "ns2:txn", "custRef") |> List.first() ||
+      Floki.attribute(doc, "ns2:txn", "custref") |> List.first()
 
     # Extract HbtMsg attributes
     hbt_type =
@@ -1659,7 +1690,10 @@ end
   """
   def generate_resp_hbt_request(request_data) do
     # Use UTC/GMT timestamp in ISO8601 format with Z suffix
-    timestamp = DateTime.utc_now() |> DateTime.to_iso8601()
+    # [RespHbt Head.ts / Txn.ts] CHANGED: IST via NpciFormat.ist_now/0 (was UTC with microseconds and a Z, e.g. ...328148Z)
+    # TSD Table 8: ts in IST, seconds only, +05:30
+    # OLD:     timestamp = DateTime.utc_now() |> DateTime.to_iso8601()
+    timestamp = NpciFormat.ist_now()
 
     xml = """
     <?xml version="1.0" encoding="UTF-8"?>
diff --git a/apps/upi_core/test/upi_core/resp_hbt_test.exs b/apps/upi_core/test/upi_core/resp_hbt_test.exs
new file mode 100644
index 0000000..97e50cf
--- /dev/null
+++ b/apps/upi_core/test/upi_core/resp_hbt_test.exs
@@ -0,0 +1,55 @@
+defmodule UpiCore.RespHbtTest do
+  use ExUnit.Case, async: true
+
+  import SweetXml
+
+  alias UpiCore.UpiXmlSchema
+
+  @req_hbt """
+  <ns2:ReqHbt xmlns:ns2="http://npci.org/upi/schema/">
+    <Head ver="2.0" ts="2026-10-27T10:00:00+05:30" orgId="NPCI" msgId="NPCIHBTMSG000000000000000000000001"/>
+    <Txn id="NPCIHBTTXN000000000000000000000001" note="ReqHbt" refId="REFNPCI0099" refUrl="www.test.co.in" ts="2026-10-27T10:00:00+05:30" type="Hbt" custRef="CUST0099"/>
+    <HbtMsg type="ALIVE" value="NA"/>
+  </ns2:ReqHbt>
+  """
+
+  defp attr(xml, path), do: xpath(xml, ~x"#{path}"s)
+
+  describe "parse_req_hbt/1" do
+    test "keeps refId / refUrl / custRef of the ReqHbt (Floki lowercases attribute names)" do
+      assert {:ok, parsed} = UpiXmlSchema.parse_req_hbt(@req_hbt)
+      assert parsed.ref_id == "REFNPCI0099"
+      assert parsed.ref_url == "www.test.co.in"
+      assert parsed.cust_ref == "CUST0099"
+      assert parsed.msg_id == "NPCIHBTMSG000000000000000000000001"
+      assert parsed.txn_id == "NPCIHBTTXN000000000000000000000001"
+    end
+  end
+
+  describe "generate_resp_hbt_request/1" do
+    test "Head ts and Txn ts are IST (+05:30, whole seconds), refId is the ReqHbt refId" do
+      {:ok, parsed} = UpiXmlSchema.parse_req_hbt(@req_hbt)
+
+      {:ok, xml} =
+        UpiXmlSchema.generate_resp_hbt_request(%{
+          msg_id: "MER00000000000000000000000000000001",
+          org_id: "MER101",
+          req_msg_id: parsed.msg_id,
+          txn_id: parsed.txn_id,
+          ref_id: parsed.ref_id,
+          ref_url: parsed.ref_url
+        })
+
+      ts_re = ~r/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+05:30$/
+      assert attr(xml, "//Head/@ts") =~ ts_re
+      assert attr(xml, "//Txn/@ts") =~ ts_re
+      refute xml =~ "Z\""
+      refute xml =~ ~r/ts="[^"]*\.\d+/
+      assert attr(xml, "//Txn/@refId") == "REFNPCI0099"
+      assert attr(xml, "//Txn/@id") == "NPCIHBTTXN000000000000000000000001"
+      assert attr(xml, "//Resp/@reqMsgId") == "NPCIHBTMSG000000000000000000000001"
+      assert attr(xml, "//Resp/@result") == "SUCCESS"
+      refute xml =~ ~r/refId="REF\d{10,}"/
+    end
+  end
+end
diff --git a/apps/upi_dynamic/lib/upi_dynamic/upi_transaction_manager.ex b/apps/upi_dynamic/lib/upi_dynamic/upi_transaction_manager.ex
index bf91774..2e566e7 100644
--- a/apps/upi_dynamic/lib/upi_dynamic/upi_transaction_manager.ex
+++ b/apps/upi_dynamic/lib/upi_dynamic/upi_transaction_manager.ex
@@ -2587,7 +2587,9 @@ end
       org_id: get_psp_org_id(),
       req_msg_id: parsed_req_data.msg_id,
       txn_id: parsed_req_data.txn_id,
-      ref_id: parsed_req_data.ref_id || generate_reference_id(),
+      # [RespHbt Txn.refId] CHANGED: echo the ReqHbt refId, no generated REF<ms> fallback
+      # OLD:       ref_id: parsed_req_data.ref_id || generate_reference_id(),
+      ref_id: parsed_req_data.ref_id,
       ref_url: parsed_req_data.ref_url || get_psp_ref_url()
     }
 
@@ -2818,10 +2820,11 @@ end
   # OLD:     "MERC" <> (:crypto.strong_rand_bytes(8) |> Base.encode16())
   # OLD:   end
 
-  defp generate_reference_id do
-    timestamp = System.system_time(:millisecond)
-    "REF#{timestamp}"
-  end
+  # [RespHbt Txn.refId] REMOVED: generate_reference_id (clause) is unused now - no generated REF<ms> refId any more - RespHbt echoes the ReqHbt refId
+  # OLD:   defp generate_reference_id do
+  # OLD:     timestamp = System.system_time(:millisecond)
+  # OLD:     "REF#{timestamp}"
+  # OLD:   end
 
   defp generate_transaction_id do
     "MER" <> (:crypto.strong_rand_bytes(16) |> Base.encode16())
@@ -3983,9 +3986,10 @@ end
     txn_id
   end
 
-  defp generate_reference_id do
-    "REF" <> (:crypto.strong_rand_bytes(6) |> Base.encode16())
-  end
+  # [RespHbt Txn.refId] REMOVED: generate_reference_id (clause) is unused now - no generated REF<ms> refId any more - RespHbt echoes the ReqHbt refId
+  # OLD:   defp generate_reference_id do
+  # OLD:     "REF" <> (:crypto.strong_rand_bytes(6) |> Base.encode16())
+  # OLD:   end
 
   defp generate_invoice_number do
     "INV" <> (:crypto.strong_rand_bytes(4) |> Base.encode16())
diff --git a/apps/upi_static/lib/upi_static/static_qr_transaction_manager.ex b/apps/upi_static/lib/upi_static/static_qr_transaction_manager.ex
index 84f2747..852deac 100644
--- a/apps/upi_static/lib/upi_static/static_qr_transaction_manager.ex
+++ b/apps/upi_static/lib/upi_static/static_qr_transaction_manager.ex
@@ -2671,8 +2671,11 @@ defmodule UpiStatic.StaticQrTransactionManager do
       org_id: @static_org_id,
       req_msg_id: parsed_req_data.msg_id,
       txn_id: parsed_req_data.txn_id,
-      ref_id: parsed_req_data.ref_id || generate_reference_id(),
-      ref_url: parsed_req_data.ref_url || "https://mercury.upi.in"
+      # [RespHbt Txn.refId / Txn.refUrl] CHANGED: echo the ReqHbt refId and refUrl, no generated REF<ms> and no invented https://mercury.upi.in
+      # OLD:       ref_id: parsed_req_data.ref_id || generate_reference_id(),
+      # OLD:       ref_url: parsed_req_data.ref_url || "https://mercury.upi.in"
+      ref_id: parsed_req_data.ref_id,
+      ref_url: parsed_req_data.ref_url
     }
 
     case UpiCore.UpiXmlSchema.generate_resp_hbt_request(resp_hbt_data) do
@@ -2776,10 +2779,11 @@ defmodule UpiStatic.StaticQrTransactionManager do
     Application.get_env(:upi_static, :npci_heartbeat_endpoint, "https://precert.nfinite.in/iupi/ReqHbt/2.0/urn:txnid:")
   end
 
-  defp generate_reference_id do
-    timestamp = System.system_time(:millisecond)
-    "REF#{timestamp}"
-  end
+  # [RespHbt Txn.refId] REMOVED: generate_reference_id (clause) is unused now - no generated REF<ms> refId any more - RespHbt echoes the ReqHbt refId
+  # OLD:   defp generate_reference_id do
+  # OLD:     timestamp = System.system_time(:millisecond)
+  # OLD:     "REF#{timestamp}"
+  # OLD:   end
 
   defp record_heartbeat_success(msg_id, ack_data) do
     Logger.info("Recording heartbeat success: #{msg_id}")
