Webhooks (notiUrl)

When a payment is completed, Hecto Financial's server sends the result directly to your server. This is called a webhook.

Webhook Integration is Required

Since nextUrl is delivered through the browser, it may be missed due to network errors. Actual order processing (inventory deduction, DB updates, etc.) must always be performed in the webhook handler (notiUrl).

How Webhooks Work

There are two ways to receive payment results.

Customer
Merchant
Hecto Financial
1Payment Request
2Launch Checkout
3Payment Processing
4Webhook (notiUrl)
5Result Page (nextUrl)
6Redirect
Delivery MethodDescriptionReliability
nextUrlBrowser redirectLow (network errors possible)
notiUrlDirect server-to-server communication (S2S)High (retry supported)
NOTE

Webhooks vs. Browser Redirect

Since notiUrl is sent directly from Hecto Financial's server to your server, results can be reliably received regardless of the customer's network status.

Communication Specification

All payment methods use the same specification.

ItemDetails
MethodPOST
Content-Typeapplication/x-www-form-urlencoded; charset=UTF-8
Response FormatPlain Text (OK or FAIL)
NOTE

Character Set Change Available

The character set can be provided as UTF-8 or EUC-KR. If you need a change, please contact our technical support at pgsupport@hecto.co.kr.

Response Handling

ResponseDescription
OKSuccess. Processed as webhook received.
FAIL or othersFailure. Resent up to the configured number of times.

Response Format Note

The response must be Plain Text 'OK' only. If spaces, line breaks, HTML tags, etc. are included, it will be considered a failure.

Hash Verification

Hash verification is required to prevent data tampering.

Hash Generation Rules

Webhook Hash VerificationpktHash

필드명파라미터
Transaction status codeoutStatCd
Transaction date (first 8 digits of trdDtm)trdDt
Transaction time (last 6 digits of trdDtm)trdTm
Merchant IDmchtId
Merchant order numbermchtTrdNo
Transaction amounttrdAmt
License keylicenseKey
SHA256(outStatCd + trdDt + trdTm + mchtId + mchtTrdNo + trdAmt (unencrypted) + licenseKey)
NOTE

Extracting trdDt / trdTm

The webhook payload includes trdDtm (14 digits). When generating the hash, extract trdDt (first 8 digits) and trdTm (last 6 digits) from it.

Verification Example (Node.js)

const crypto = require('crypto');

function verifyNoti(data, licenseKey) {
  const { outStatCd, trdDtm, mchtId, mchtTrdNo, trdAmt, pktHash } = data;

  // Split date/time from trdDtm
  const trdDt = trdDtm.substring(0, 8);   // YYYYMMDD
  const trdTm = trdDtm.substring(8, 14);  // HHmmss

  // Generate hash
  const hashString = outStatCd + trdDt + trdTm + mchtId + mchtTrdNo + trdAmt + licenseKey; // trdAmt must be the plaintext (unencrypted) amount
  const calculatedHash = crypto.createHash('sha256').update(hashString, 'utf8').digest('hex');

  return pktHash === calculatedHash;
}

// Usage example
app.post('/noti/hecto', (req, res) => {
  if (!verifyNoti(req.body, HECTO_LICENSE_KEY)) {
    console.error('Hash verification failed');
    return res.send('FAIL');
  }

  // Payment processing logic...

  res.send('OK');
});

After Successful Verification

Once hash verification passes, your webhook handler should:

  1. Check outStatCd0021 means payment succeeded; 0031 means payment failed. Always return OK for both outcomes to prevent re-delivery.
  2. Prevent duplicate processing — Check mchtTrdNo against your database before updating order status.
  3. Update order status — On 0021, mark the order as paid and trigger fulfillment (inventory, shipping, email confirmation).
  4. Handle failures gracefully — On 0031, update the order status to failed and notify the customer if needed.
app.post('/noti/hecto', (req, res) => {
  if (!verifyNoti(req.body, HECTO_LICENSE_KEY)) {
    console.error('Hash verification failed');
    return res.send('FAIL');
  }

  const { outStatCd, mchtTrdNo } = req.body;

  // Prevent duplicate processing
  if (await isAlreadyProcessed(mchtTrdNo)) {
    return res.send('OK');
  }

  if (outStatCd === '0021') {
    await markOrderAsPaid(mchtTrdNo);
    await triggerFulfillment(mchtTrdNo);
  } else {
    await markOrderAsFailed(mchtTrdNo);
  }

  // Always return OK to stop retry attempts
  res.send('OK');
});

notiUrl Requirements

  • HTTPS is required (HTTP is not supported)
  • URL must be accessible from external networks
  • Hecto Financial IPs must be allowed through the firewall

Frequently Asked Questions

Webhooks are not being received

  1. Verify that the notiUrl is accessible from external networks
  2. Verify that the HTTPS certificate is valid
  3. Check firewall settings
  4. Verify that OK is returned as Plain Text in the response

Receiving duplicate webhooks

If OK is not returned in the response, the webhook will be resent. Check the response format.

When are cancellation webhooks sent?

Cancellation webhooks are not sent by default.

Since the result is received immediately in the response when calling the cancellation API, a separate webhook is not needed.

However, when cancellation is performed directly from the merchant admin panel, your server has no way of knowing the payment status, so it is possible to configure cancellation webhooks to be sent. If you need to receive cancellation webhooks, please request the configuration from your sales representative.

When cancellation webhook delivery is configured, it is sent to the notiUrl of the original transaction by default. If notiUrl was not set for the original transaction, please also provide a URL for cancellation webhooks.

💬

Need technical support?