# Xử lý sự kiện Webhook

Tích hợp phương pháp webhook rất đơn giản, **tất cả mọi thứ bạn cần làm là lập trình một API xử lý sự kiện Webhook.** Sau khi bạn đã đăng kí URL của API này vào một [mục tích hợp webhook](https://developer.casso.vn/webhook/thiet-lap-webhook-thu-cong) trong Casso.

Mỗi khi Casso phát hiện tài khoản ngân hàng liên kết có một giao dịch mới, Casso sẽ gọi vào API này.

Hiện tại, Casso cung cấp 2 giải pháp nhận thông tin giao dịch là Webhook và Webhook V2. Chúng tôi khuyến khích bạn sử dụng tích hợp Webhook V2 để tăng khả năng bảo mật khi xác thực tính toàn vẹn của dữ liệu mà Casso gửi qua hệ thống của bạn cũng như đảm bảo rằng dữ liệu này được gửi trực tiếp từ Casso.

Đặc tả của API này là :&#x20;

## Xử lý giao dịch được gửi từ Casso

### Webhook V2

<mark style="color:green;">`POST`</mark> `https://websitecuaban.com/api/webhook-event-handler`

#### Headers

| Name              | Type   | Description                                                                                                                                                                                                                  |
| ----------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| X-Casso-Signature | string | Chữ ký số được tạo bởi dữ liệu webhook và một số thông tin khác (Sample code tạo và kiểm tra chữ ký số tại bài viết [#lap-trinh-webhook](https://developer.casso.vn/thiet-lap-webhook-thu-cong#lap-trinh-webhook "mention")) |

#### Request Body

| Name  | Type   | Description                          |
| ----- | ------ | ------------------------------------ |
| error | string | Mã lỗi.                              |
| data  | string | Object chứa thông tin giao dịch mới. |

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

```json
{
    "error": 0,
    "data": {
        "id": 0,
        "reference": "MA_GIAO_DICH_THU_NGHIEM",
        "description": "giao dich thu nghiem",
        "amount": 599000,
        "runningBalance": 25000000,
        "transactionDateTime": "2025-02-12 15:36:21",
        "accountNumber": "88888888",
        "bankName": "VPBank",
        "bankAbbreviation": "VPB",
        "virtualAccountNumber": "",
        "virtualAccountName": "",
        "counterAccountName": "NGUYEN VAN A",
        "counterAccountNumber": "8888888888",
        "counterAccountBankId": "970415",
        "counterAccountBankName": "VietinBank"
      }
}
```

{% endtab %}
{% endtabs %}

### Webhook

<mark style="color:green;">`POST`</mark> `https://websitecuaban.com/api/webhook-event-handler`

#### Headers

<table><thead><tr><th width="250">Name</th><th width="255">Type</th><th>Description</th></tr></thead><tbody><tr><td>secure-token</td><td>string</td><td>Key bảo mật để xác thực Webhook được gọi từ Casso</td></tr></tbody></table>

#### Request Body

| Name  | Type   | Description                       |
| ----- | ------ | --------------------------------- |
| error | string | Mã lỗi.                           |
| data  | string | Mảng danh sách các giao dịch mới. |

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

```json

{
    "error": 0,
    "data": [
        {
            "id": 6785,
            "tid": "BANK_REF_ID",
            "description": "giao dich thu nghiem",
            "amount": 79000,
            "cusum_balance": 2007900,                
            "when": "2020-10-14 00:34:57",
            "bank_sub_acc_id": "123456789",
            "subAccId" :  "123456789",
            "bankName" : "VPBank",
            "bankAbbreviation" : "VPB", 
            "virtualAccount": "",
            "virtualAccountName": "",
            "corresponsiveName": "",
            "corresponsiveAccount": "",
            "corresponsiveBankId": "",
            "corresponsiveBankName": ""
        },
    
    ]
}



```

{% endtab %}
{% endtabs %}

## Code

Bạn có thể sử dụng bất kì ngôn ngữ nào hỗ trợ xây dựng  restful API để Code.

Quá trình code có thể chỉ mất vài giờ nếu bạn đã quen với việc viết API. Bạn có thể làm theo kịch bản sau:&#x20;

* Tạo dự án Restful API mới (Nodejs Express / Java Spring Boot / PHP single file, ...)
* Test in ra được helloword!
* Tạo controller mới xử lý một Post tên là /webhook-event-handler&#x20;
* Test : Dùng Curl Post một giao dịch mô phỏng lên /webhook-event-handler  và chỉnh code để in ra đúng được nội dung gửi lên (xem thêm phần Test bên dưới)
* Rút trích nội dung giao dịch
* Xử lý nội dung giao dịch
* Phản hồi HTTP status code 200 OK

Ví dụ bên dưới viết bằng NodeJS, log ra số giao dịch Webhook Api nhận dc. Bằng cách chỉnh sửa vài dòng  [ Hello World Sample của Node JS Express](https://expressjs.com/en/starter/hello-world.html)

{% code title="app.js" %}

```javascript
const express = require('express')
const app = express()
const port = 8080

app.use(express.json());
app.post('/api/webhook-event-handler', (req, res) => {
    let error = req.body.error;
    if (error != 0) {
        //Không làm gì cả.
        return;
    }
    
    //mảng chứa danh sách các giao dịch
    let transactions = req.body.data;
    
    console.log(`Received ${transactions.length} transactions`);
    
    //thêm code xử lý giao dịch ở đây.
    
    res.end("OK");
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})
```

{% endcode %}

Bạn có thể xem thêm cách code một [API xử lý sự kiện webhook cho tính năng Tích hợp xác nhận thanh toán](https://developer.casso.vn/tai-nguyen-khac/tich-hop-xac-nhan-thanh-toan)

## Tạo sự kiện webhook để test

Có 5 cách để giả lập giao dịch gửi vào API xử lý webhook bạn đang code như sau:

| STT | Môi trường     | Phương pháp                                                           |
| --- | -------------- | --------------------------------------------------------------------- |
| 1   | Local          | Tự gọi API bằng Curl  / Postman                                       |
| 2   | Local          | Sử dụng ngrok để dẫn (pipe) webhook về local                          |
| 3   | Dev \| Staging | Nút Gọi Thử Trong giao diện setup Webhook                             |
| 4   | Dev \| Staging | Nút đồng bộ giao dịch ngay trong giao diện 1 Tài khoản ngân hàng Demo |
| 5   | Live           | Link tài khoản thật & tạo 1 lệnh chuyển tiền                          |

Tuy nhiên, chúng tôi khuyến cáo bạn hãy viết và test thật kĩ trên Local trước , và test nhanh bằng Postman hoặc Curl.&#x20;

### Sử dụng ngrok để public Webhook ở Local

[Ngrok](https://ngrok.com/) là một ứng dụng tạo ra một đường hầm từ máy bạn (desktop, localhost) đi qua hệ thống Firewall/Nat, giúp từ internet có thể truy cập vào máy trạm.

Nếu như bạn đang chạy server ở local port **8080**, ở **terminal**, bạn nhập: **ngrok http 8080**.

{% hint style="info" %}
Một url có thể khả dụng trong 8 giờ.

Chỉ sử dụng **https\://**

Bạn có thể sử dụng giao diện web của [Ngrok](https://ngrok.com/) để xêm lưu lượng HTTP request và response qua hệ thống của bạn: <http://localhost:8080>
{% endhint %}

### Sử dụng Curl để test

Copy nội dung bên dưới, sau khi đã fix lại đường dẫn API xử lý webhook

Mở terminal&#x20;

{% tabs %}
{% tab title="Webhook V2 Curl" %}

```bash
curl --location --request POST 'http://localhost:8080/api/webhook-event-handler' \
--header 'X-Casso-Signature: t=1727948258788,v1=ed0a4bd2e826d5cb69988cdb141e6c1a080e21f3b57eb72cd78192220042b9e7dde0868fc667faea8e224900fa7904e7c88dfa098032fb2d6b6996856e8b7ff3' \
--header 'Content-Type: application/json' \
--data-raw '{
    "error": 0,
    "data": {
        "id": 0,
        "reference": "MA_GIAO_DICH_THU_NGHIEM",
        "description": "giao dich thu nghiem",
        "amount": 599000,
        "runningBalance": 25000000,
        "transactionDateTime": "2024-10-03 15:06:37",
        "accountNumber": "88888888",
        "bankName": "VPBank",
        "bankAbbreviation": "VPB",
        "virtualAccountNumber": "",
        "virtualAccountName": "",
        "counterAccountName": "NGUYEN VAN A",
        "counterAccountNumber": "8888888888",
        "counterAccountBankId": "970415",
        "counterAccountBankName": "VietinBank"
    }
}'
```

Paste & Enter

{% hint style="info" %}
Đây là dữ liệu mẫu để bạn có thể hình dung cách mà Casso sẽ truyền thông tin giao dịch, chữ ký số khi gọi API sang hệ thống xử lý sự kiện Webhook của bạn. Header X-Casso-Signature được tạo dựa trên thông tin giao dịch trong data-raw và Key bảo mật của Tích hợp Webhook V2. Để tìm hiểu thêm về phương pháp tạo và xác thực chữ ký số, vui lòng tham khảo [#lap-trinh-webhook](https://developer.casso.vn/thiet-lap-webhook-thu-cong#lap-trinh-webhook "mention")
{% endhint %}

{% hint style="info" %}
Lưu ý: \
Trường transactionDateTime có thể có hoặc không có giờ phút giây, tùy thuộc vào ngân hàng.

Ví dụ : ACB thì transactionDateTime sẽ là "2020-11-02 00:00:00", còn VietinBank thì transactionDateTime sẽ là "2020-11-02 11:50:30"
{% endhint %}
{% endtab %}

{% tab title="Webhook Curl" %}

```bash
curl --location --request POST 'http://localhost:8080/api/webhook-event-handler' \
--header 'secure-token: eogrBiWqaq' \
--header 'Content-Type: application/json' \
--data-raw '{
    "error": 0,
    "data": [
        {
            "id" : 1, 
            "when": "2020-11-02 11:50:30",
            "amount": 200500,
            "description": "DH35",
            "cusum_balance": 15900500,
            "tid": "TF80307914",
            "subAccId": "123456789",
            "bank_sub_acc_id": "123456789",
            "virtualAccount": "",
            "virtualAccountName": "",
            "corresponsiveName": "",
            "corresponsiveAccount": "",
            "corresponsiveBankId": "",
            "corresponsiveBankName": ""
        }
    ]
}'
```

Paste & Enter

{% hint style="info" %}
Lưu ý: \
Trường when có thể có hoặc không có giờ phút giây, tùy thuộc vào ngân hàng.

Ví dụ : ACB thì when sẽ là "2020-11-02 00:00:00", còn vietinbank thì when sẽ là "2020-11-02 11:50:30"
{% endhint %}
{% endtab %}
{% endtabs %}

## Phát hành

* Release dự án lên internet
* Cập nhật lại Webhook URL trong cấu hình webhook
* Link môt tài khoản ngân hàng thật
* Chuyển tiền vào tài khoản ngân hàng (5,000 , 10,000 thôi)
* Xác nhận rằng Casso đã gọi qua Webhook và xử lý thành công

Và \
... Xin chúc mừng. **Bạn đã hoàn tất!!!!**\
\
Chúng tôi ở đây để làm cho thế giới đơn giản hơn. ^^
