AUTOXSPARE Docs
API reference

Curlec

The payment provider — amounts, signatures, and the FPX redirect.

apps/backend/src/modules/curlec/ — registered as a provider of the payment module, not as a module of its own. Provider identifier: curlec.

Curlec is Razorpay's Malaysian entity, so the API is Razorpay's, and the Razorpay docs apply.

Flow

Order-first, which is Razorpay's model:

  1. Backend creates a Curlec order for the cart total.
  2. Storefront opens Curlec's checkout with that order id.
  3. Customer pays by FPX or card.
  4. Curlec returns the customer to the return route.
  5. Backend verifies the signature and authorises the payment session.

Amounts

Sent in sen — multiply by 100.

const amount = Math.round(cartTotal * 100)

The provider refuses any currency other than MYR outright. Curlec settles MYR only, and an amount in another currency would be passed through as sen regardless, charging a number that means nothing.

Signature verification

HMAC-SHA256 over order_id|payment_id, keyed with the webhook secret:

const expected = crypto
  .createHmac("sha256", secret)
  .update(`${razorpay_order_id}|${razorpay_payment_id}`)
  .digest("hex")

Compare against razorpay_signature. A mismatch means the callback is not trustworthy and the payment must not be authorised.

FPX needs a redirect

FPX will not work as an inline modal. The checkout must be opened with:

{ callback_url: "<return route>", redirect: true }

The storefront's payment button loads https://checkout.razorpay.com/v1/checkout.js on demand and deliberately passes no handler — FPX redirects away, so a handler callback never fires and relying on it silently loses the payment.

Test and live

CURLEC_MODE selects which key pair medusa-config.ts reads:

const CURLEC_MODE = (process.env.CURLEC_MODE ?? 'live') as 'test' | 'live'
const curlecKeyId = (CURLEC_MODE === 'live'
  ? process.env.CURLEC_LIVE_KEY_ID
  : process.env.CURLEC_TEST_KEY_ID) ?? process.env.CURLEC_KEY_ID

Currently live. Changing it is a Railway variable change plus a redeploy.

Webhook

Configured in the Curlec dashboard against the backend. The signing secret is separate from the API key secret — verification uses the webhook secret.

On this page