# Set up a webhook

#### Use the i'mport webhook to synchronize payment information on the i'mport server with the merchant server to compensate for data loss due to device or network instability.

![](https://2814812280-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhTv8JEzyM5h4cYcL5StH%2Fuploads%2FkGYhqC093FOcmnwWnf2M%2Fwebhook-service.png?alt=media\&token=479a0502-f8b6-48c7-ba00-dcad550c3318)

{% hint style="info" %}
**What is a webhook?**

A webhook is a mechanism for sending notifications to other services or applications when a specific event occurs. The webhook provider sends event information to the callback URL (endpoint) by creating an `HTTP POST` request when the event occurs. Webhooks are much more efficient in terms of resources and communication as they can only receive information related to desired events without polling data periodically. Using webhooks, you can extend functionality by integrating with custom functions or other applications.
{% endhint %}

{% hint style="success" %}
**Is webhook integration required?**

When the i'mport server sends a response to the client, the client may not receive the response after the payment process is complete for reasons, such as Wi-Fi disconnection or automatic browser reload. In this case, the i'mport server sends a webhook event to the server so that the payment information can be synchronized.
{% endhint %}

i'mport webhook is called when:

> * **Payment is approved (all payment methods)** (status : `paid`)
> * **Virtual account is issued** (status : `ready`)
> * **Payment is deposited into virtual account** (status : `paid`)
> * **Scheduled payment is attempted** (status : `paid` or `failed`)
> * **Refund is processed from Admin console** (status : `cancelled`)

{% hint style="danger" %}
**A webhook is not invoked when payment fails!**
{% endhint %}

Webhook URL can be set in the following two ways:

{% tabs %}
{% tab title="Admin console" %}
![](https://2814812280-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhTv8JEzyM5h4cYcL5StH%2Fuploads%2FydTANKQpYtp5MJG0SaDp%2Fimage.png?alt=media\&token=544ab722-f23d-472b-817e-cb1ab065235d)

To set the webhook's notification URL to send the payment information to, log in to the **Admin console** and then go to [**Payments->Live Settings**](https://admin.iamport.kr/integration?tab=production) tab and set the URL in the **Endpoint URL** field to receive the webhook data.&#x20;

**Content-Type** can be specified as `application/json` or `application/x-www-form-urlencoded`. To test the URL, click the **Test Webhook** button to the right of the Notification URL field.
{% endtab %}

{% tab title="Parameter" %}
Set the <mark style="color:blue;">**notice\_url**</mark> parameter when calling the JavaScript SDK **request\_pay** function to receive a webhook notification. Use this method to specify a different webhook URL for each payment request.

(If this parameter is specified, the Admin console's <mark style="color:red;">**webhook setting is ignored**</mark>.)

{% code title="client-side" %}

```javascript
function requestPay() {
    // IMP.request_pay(param, callback) call payment window
    IMP.request_pay({
        ...            // Omitted
        notice_url : 'https://Webhook URL',   // Set Webhook URL
        ...            // Omitted
    }, function (rsp) { // callback
        if (rsp.success) {
            console.log(rsp);
        } else {
            console.log(rsp);
        }
    });
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="info" %}
**You cannot set multiple webhook URLs.**
{% endhint %}

### Verify webhook request <a href="#webhook" id="webhook"></a>

Since an i'mport webhook endpoint is a public URL, you must **verify that the request's client IP is an i'mport IP**. An i'mport webhook request must originate from one of the following static IPs.

> * <mark style="color:red;">**52.78.100.19**</mark>
> * <mark style="color:red;">**52.78.48.223**</mark>
> * <mark style="color:red;">**52.78.5.241**</mark>**&#x20;(when invoked via Test Webhook button)**

When a webhook event is called, the following `POST` request is generated for the notification URL endpoint.

{% tabs %}
{% tab title="cURL" %}

```url
curl -H "Content-Type: application/json" -X POST -d '{ "imp_uid": "imp_1234567890", "merchant_uid": "order_id_8237352", "status": "paid" }' { NotificationURL }
```

{% endtab %}
{% endtabs %}

> The body of the webhook `POST` request contains the following information. The server can get the information and use it to query the payment information from the i'mport server and verify and store the payment information.
>
> * <mark style="color:red;">**`imp_uid`**</mark><mark style="color:red;">**: payment ID**</mark>
> * <mark style="color:red;">**`merchant_uid`**</mark><mark style="color:red;">**: order ID**</mark>
> * <mark style="color:red;">**`status`**</mark><mark style="color:red;">**: payment result**</mark>

Sample code of receiving a POST request to webhook endpoint URL

{% tabs %}
{% tab title="Node.js" %}
Create an endpoint to receive the webhook event's `POST` request as follows and then parse, verify, and save the payment information.

{% code title="server-side" %}

```javascript
app.use(bodyParser.json());
  ...
  // Route POST request to "/iamport-webhook"
  app.post("/iamport-webhook", async (req, res) => {
    try {
        const { imp_uid, merchant_uid } = req.body; // Get imp_uid and merchant_uid from req.body
        // Get access token
        /* ...Omitted... */
        // Get payment info from i'mport server using imp_uid
        /* ...Omitted... */
        const paymentData = getPaymentData.data.response; // Save payment info
        ...
        // Query for original requested amount from the database
        const order = await Orders.findById(paymentData.merchant_uid);
        const amountToBePaid = order.amount; // Original requested amount
        ...
        // Verify payment amount
        const { amount, status } = paymentData;
        if (amount === amountToBePaid) { // Amounts match. Processed amount === Original requested amount
          await Orders.findByIdAndUpdate(merchant_uid, { $set: paymentData }); // Save payment info in DB
          switch (status) {
            case "ready": // Issue virtual account
              // Save virtual account info in DB
              const { vbank_num, vbank_date, vbank_name } = paymentData;
              await Users.findByIdAndUpdate("/* customer id */", { $set: { vbank_num, vbank_date, vbank_name }});
              // Send virtual account issuance text message
              SMS.send({ text: \`Virtual account has been issued. Account information \${vbank_num} \${vbank_date} \${vbank_name}\`});
              res.send({ status: "vbankIssued", message: "Virtual account issued successfully" });
              break;
            case "paid": // Payment complete
              res.send({ status: "success", message: "Payment successful." });
              break;
          }
        } else { // Amount mismatch. Forged/falsified payment.
          throw { status: "forgery", message: "Forged/falsified payment attempted" };
        }
    } catch (e) {
      res.status(400).send(e);
    }
  });
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="danger" %}
**i'mport does not guarantee the order of payment information delivery**

In general, after i'mport server calls webhook, it does not guarantee the order in which the payment information arrives at the server. This is because i'mport sends a 302 redirect response to the client without waiting for a webhook response from the server. However, you can submit a special request to configure i'mport to wait for a webhook response before sending a 302 redirect or callback response to the client so that the server always receives payment information from i'mport first. To make a request to guarantee the prioritized delivery of webhooks, contact <support@iamport.kr> with the merchant ID.&#x20;
{% endhint %}

{% hint style="info" %}
**Can you re-send a webhook?**

By default, a webhook can only be sent once. However, it can be re-sent up to 5 times as per merchant's request. Webhooks are re-sent every 1 minute until a successful response is received from the merchant (**up to 5 times**).
{% endhint %}
