# Thiết lập Webhook thủ công

{% hint style="success" %}
Nếu như Bạn cần giải pháp Xác nhận thanh toán, hãy dùng [payOS by Casso](https://payos.vn).

**payOS** là một giải pháp của Casso chuyên dụng dành cho việc xác nhận thanh toán, được phát triển bằng sự kết hợp các công nghệ VietQR , Virtual Account Number và Open Banking API.
{% endhint %}

## Mô hình hoạt động

Casso sử dụng webhook để thông báo cho ứng dụng của bạn khi có một giao dịch tiền vào hoặc tiền ra tài khoản ngân hàng của bạn.

Tích hợp Casso vào ứng dụng của bạn bằng webhook chỉ bao gồm 3 bước đơn giản

1. [**Lập trình** một webhook ](https://developer.casso.vn/webhook/gia-lap-giao-dich-den)endpoint để xử lý sự kiện webhook trên server của bạn
2. Giả lập giao dịch mới từ ngân hàng để **Test** và đảm bảo webhook endpoint của bạn chạy đúng.
3. Đăng kí URL của Webhook endpoint vào Casso và **Go live**.

![](https://1031644972-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-McgqoGaNKiqy_6nDeJw%2F-MfTsuVFgCWygkzhBrjN%2F-MfTt-1ZvnJb0f78pD1p%2Fmo%CC%82%20hi%CC%80nh%20webhook%20\(1\).png?alt=media\&token=2a399467-0cd7-4a19-852b-ec901f2d6b16)

## Trước khi bắt đầu

Bạn cần phải:

* Tạo một tài khoản tại [Casso](https://casso.vn)
* Liên kết một tài khoản ngân hàng vào Casso

## Thiết lập webhook trong Casso

Đăng nhập vào tài khoản tại [casso.vn](https://casso.vn)&#x20;

Truy cập vào **Kết nối** > **Tích hợp** và ấn vào nút **Thêm tích hợp**

<figure><img src="https://1031644972-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-McgqoGaNKiqy_6nDeJw-3789850253%2Fuploads%2FPIqeAUP8EKBB8uWWeB7O%2Fimage.png?alt=media&#x26;token=fe4a9897-ebab-4d86-b438-7b8b57470d42" alt=""><figcaption></figcaption></figure>

Trong danh sách **Chọn ứng dụng để tích hợp ,** chọn **Webhook** hoặc **Webhook V2.** Sẽ mở ra giao diện **Thêm tích hợp Webhook**:&#x20;

<figure><img src="https://1031644972-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-McgqoGaNKiqy_6nDeJw-3789850253%2Fuploads%2FStli24Vcmr1X5vR9DyIK%2Fimage.png?alt=media&#x26;token=4f493185-8fd1-4e6c-a184-ef8bab26e273" alt=""><figcaption></figcaption></figure>

Ở mục **1. Chọn ngân hàng** :

* Bạn chọn tài khoản ngân hàng sẽ được theo dõi để bắn thông tin giao dịch.&#x20;
* Bạn có thể chọn Tất cả để Hệ thống **Casso** bắn giao dịch của tất cả các tài khoản ngân hàng đã liên kết.

Bạn nhấn nút **Tiếp tục** để chuyển sang bước **Thiết lập Webhook nhận dữ liệu:**

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

<figure><img src="https://1031644972-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-McgqoGaNKiqy_6nDeJw-3789850253%2Fuploads%2F41ErLluED7LmxkJ8HWKg%2Fimage.png?alt=media&#x26;token=2b8e1f6a-88d6-4345-bade-b0026963619b" alt=""><figcaption></figcaption></figure>

Ở bước **Thiết lập :**

* Thông số **Webhook URL** sẽ là đường dẫn tới API endpoint của **hệ thống xử lý sự kiện webhook** trên web server của bạn.
* Thông số **Key bảo mật** là một chuỗi các ký tự ngẫu nhiên do Casso tự sinh ra cho mỗi tích hợp. Key bảo mật này sẽ dùng để tạo chữ ký số đối với dữ liệu của Webhook và một số thông tin khác. Bạn có thể kiểm tra header lấy thông tin chữ ký số để xác thực việc gọi vào Webhook URL là hợp lệ.

{% hint style="info" %}

* Nếu bạn cảm thấy Key bảo mật hiện tại không an toàn, bạn có thể nhấn nút rotate ở bên phải trường Key bảo mật để làm mới và Lưu lại tích hợp.&#x20;
* Tuy nhiên, hãy đảm bảo rằng tất cả sự kiện của Tích hợp Webhook V2 đã được xử lý thành công trước khi làm mới Key bảo mật. Nếu bạn làm mới Key bảo mật trong khi vẫn còn sự kiện chưa được xử lý, các sự kiện này vẫn sẽ dùng Key bảo mật cũ tạo chữ ký số.
  {% endhint %}
  {% endtab %}

{% tab title="Webhook" %}

<figure><img src="https://1031644972-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-McgqoGaNKiqy_6nDeJw-3789850253%2Fuploads%2FqH4iz1GCSqpMv7a8LmrM%2Fimage.png?alt=media&#x26;token=13129332-eb64-4e51-9071-86bc00813b23" alt=""><figcaption></figcaption></figure>

Ở bước **Thiết lập :**

* Thông số **Webhook URL** sẽ là đường dẫn tới API endpoint của **hệ thống xử lý sự kiện webhook** trên web server của bạn.
* Thông số **Key bảo mật** chứa một mã bí mật  mà mỗi lần gọi vào **Webhook URL**, Casso sẽ đính kèm key bảo mật này vào trong HTTP Header. Bạn có thể kiểm tra header lấy thông tin mã bí mật để xác thực việc gọi vào Webhook URL là hợp lệ.
  {% endtab %}
  {% endtabs %}

{% hint style="danger" %}
Không sử dụng Webhook URL là **đường dẫn chỉ có thể truy cập tư mạng nội bộ** hoặc **localhost, 127.0.01, 192.160.1.x ...** Webhook URL buộc phải là một đường dẫn public trên Internet.
{% endhint %}

<figure><img src="https://1031644972-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-McgqoGaNKiqy_6nDeJw-3789850253%2Fuploads%2FvoMt017n5RhHja4nNUru%2Fimage.png?alt=media&#x26;token=04b4a8e8-2b31-4c9e-ac43-031d16e73abb" alt=""><figcaption></figcaption></figure>

Ở bước **Cấu hình dữ liệu**, bạn cần thiết lập các tùy chọn **Gửi kèm thông tin số dư, Gửi kèm thông tin mã giao dịch, Strict mode** để Casso có thể gửi đầy đủ thông tin mà bạn cần qua webhook đồng thời xử lý phản hồi từ hệ thống của bạn một cách chính xác.

Bấm vào nút **Tiếp tục** để tới bước tiếp theo.

<figure><img src="https://1031644972-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-McgqoGaNKiqy_6nDeJw-3789850253%2Fuploads%2FnqEyvexYrMkJOZWAeAaz%2Fimage.png?alt=media&#x26;token=8c6ebd3d-90a1-457a-abeb-f600fc5f3dd2" alt=""><figcaption></figcaption></figure>

Bấm vào nút **Gọi thử**, để hệ thống Casso bắn một giao dịch test vào Webhook URL.&#x20;

Nếu Casso bắn Webhook URL thành công, tức là cấu hình của bạn đã hợp lệ. Lúc này bạn có thể bấm vào nút **Lưu** để hệ thống lưu lại cấu hình này.

{% hint style="info" %}
**Strict mode**: là bước kiểm tra nâng cao kết quả trả về, khi kết quả trả về status code là 200, thì Casso sẽ kiểm tra thêm 1 bước nữa trong JSON trả về **success : 1** hoặc **success: true**. Nếu là **0**/**false** thì hệ thống sẽ hiểu là fail và Casso sẽ gửi lại webhook. \
Nếu không bật strict mode thì khi nhận phản hồi status code 200 thì Casso sẽ hiểu là đã gửi webhook thành công.
{% endhint %}

{% hint style="success" %}
**MẸO** : Trong quá trình lập trình tích hợp, bên cạnh Webhook tùy chỉnh trỏ tới website của bạn, bạn có thể đăng kí thêm 1 webhook tùy chỉnh khác sử dụng các dịch vụ như **pipedream.com**, **webhook.site**, **ngrok.com** để debug nội dung Casso gửi vào Webhook URL
{% endhint %}

## Yêu cầu của Webhook URL

Casso sẽ thực hiện việc gọi API vào Webhook URL mỗi khi có giao dịch mới. Webhook URL sẽ cần phải đáp ứng các yêu cầu sau:

### Khả năng truy cập

* Phải là đường dẫn công khai có thể truy cập từ internet
* Đường dẫn sử dụng giao thức bảo mật **HTTPS**
* Nếu website sử dụng Cloudflare hoặc các dịch vụ ngăn chặn DDOS, lưu ý bạn phải whitelist IP của Casso.&#x20;

### Phản hồi khi thành công

Sau khi xử lý, webhook của bạn phải phản hồi với status code là **200 OK**. Và đáp ứng thời gian phản hồi dưới 5 giây ( Casso sẽ thiết lập timeout cho request POST bắn webhook là 5s)

### Xử lý các trường hợp thất bại.

Nếu quá trình bắn webhook thất bại vì một lý do nào đó, Casso sẽ gọi lại liên tục webhook trong 24 giờ sau đó, lần đầu gọi sẽ sau 1 phút và thời gian chờ này sẽ tăng lên thành giá trị [**Fibonacci**](https://vi.wikipedia.org/wiki/D%C3%A3y_Fibonacci) kế tiếp sau mỗi lần gọi lại thất bại.&#x20;

Tổng cộng, Casso sẽ gọi lại 1 sự kiện webhook nhiều nhất là 17 lần. Sau đó mới bỏ qua và chuyển sự kiện webhook qua trạng thái **Thất Bại** (FAIL).

Sau 24 giờ liên tục gọi webhook toàn thất bại, Casso sẽ chuyển cấu hình webhook sang trạng thái **Tạm Dừng** (PAUSED). Khi cấu hình webhook bị tạm dừng mà có giao dịch mới phát sinh, các sự kiện webhook này sẽ không được thực hiện mà được lưu lại với trạng thái là **Tạm Giữ** (HOLDING). Khách hàng sau khi fix lỗi của hệ thống xử lý sự kiện webhook thì có thể truy cập vào giao diện Casso để **thực hiện lại** (Replay) các sự kiện webhook này.

Sau 7 ngày cấu hình webhook bị tạm dừng mà không được xử lý, Casso sẽ chuyển cấu hình webhook sáng trạng thái Tắt (DISABLE). Các giao dịch xảy ra khi cấu hình webhook bị tắt sẽ không có khả năng thực hiện lại.

### Chống trùng lắp

Để chống lại phương pháp tấn công **Replay Attack**, Hệ thống xử lý sự kiện Webhook của bạn cần phải được xử lý chống trùng lặp thông qua kiểm tra xem một giao dịch mới đã được xử lý trước đây hay chưa? Mỗi giao dịch của Casso được định danh bởi một `id`. Với một webhook mới đến, bạn hãy kiểm tra xem `id` của giao dịch này đã được xử lý trước đây hay chưa, nếu đã có thì tức là giao dịch này đã bị Replay bởi một lý do nào đó, hãy bỏ qua nó.

### Xử lý hậu kiểm

Dù tỉ lệ có thể sẽ rất thấp, nhưng sẽ luôn có khả năng webhook thất bại, để tránh trường hợp bị sót giao dịch. Nhà phát triển có thể cân nhắc cung cấp tính năng **Tra soát toàn bộ giao dịch** bắng cách sử dụng API để tải về các giao dịch và kiểm tra xem có giao dịch nào sót không. Xem thêm ở mục [Tạo Auth code thủ công](https://developer.casso.vn/casso-api/chung-thuc/tao-api-key-thu-cong).

## Cấu trúc dữ liệu gửi qua Webhook

Casso sẽ bắn dữ liệu vào Webhook URL mà bạn đã khai báo, Dữ liệu định dạng JSON, trong đó trường data sẽ lưu thông tin giao dịch mới.

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

```json
{
    "error": 0,
    "data": {
        "id": 0, // Mã định danh duy nhất của giao dịch (Casso quy định)
        "reference": "BANK_REF_ID", // Mã giao dịch từ phía ngân hàng
        "description": "giao dich thu nghiem",  // Nội dung giao dịch
        "amount": 599000, // Số tiền giao dịch
        "runningBalance": 25000000, // Số dư sau giao dịch
        "transactionDateTime": "2025-02-12 15:36:21", // Thời gian giao dịch
        "accountNumber": "88888888", // Số tài khoản mà giao dịch thuộc về
        "bankName": "VPBank", // Tên ngân hàng
        "bankAbbreviation": "VPB", // Viết tắt tên ngân hàng
        "virtualAccountNumber": "", // Tài khoản ảo
        "virtualAccountName": "", // Tên tài khoản ảo
        "counterAccountName": "", // Tên tài khoản đối ứng
        "counterAccountNumber": "", // Tài khoản đối ứng
        "counterAccountBankId": "", // Mã ngân hàng đối ứng
        "counterAccountBankName": "" // Tên ngân hàng đối ứng
    }
}
```

{% endtab %}

{% tab title="Webhook" %}

```json
{
    "error": 0,
    "data": [
        {
            "id": 6785,        // Mã định danh duy nhất của giao dịch (Casso quy định)
            "tid": "BANK_REF_ID", // Mã giao dịch từ phía ngân hàng
            "description": "giao dich thu nghiem", // Nội dung giao dịch
            "amount": 79000, // Số tiền giao dịch
            "cusum_balance": 20079000,  // Số tiền còn lại sau giao dịch                 
            "when": "2020-10-14 00:34:57",    // Thời gian ghi có giao dịch ở ngân hàng
            "bank_sub_acc_id": "123456789",   // Mã tài khoản ngân hàng mà giao dịch thuộc về
            "subAccId" :  "123456789"       // Tương tự field bank_sub_acc_id, nhằm tương thích với code cũ
            "bankName" : "VPBank", // Tên ngân hàng
            "bankAbbreviation" : "VPB", // Viết tắt tên ngân hàng 
            "virtualAccount": "", // Tài khoản ảo
            "virtualAccountName": "", // Tên tài khoản ảo
            "corresponsiveName": "", // Tên tài khoản đối ứng
            "corresponsiveAccount": "", // Tài khoản đối ứng
            "corresponsiveBankId": "", // Mã ngân hàng đối ứng
            "corresponsiveBankName": "" // Tên ngân hàng đối ứng
        },
    
    ]
}
```

{% hint style="warning" %}
Lưu ý : Nếu có một giao dịch mới, Casso vẫn sẽ gửi qua một mảng chứa 1 phần tử giao dịch mới.&#x20;
{% endhint %}
{% endtab %}
{% endtabs %}

## Lập trình webhook

Một số tài nguyên ban có thể tham khảo để lập trình Module xử lý webhook **Webhook Event Handler.**

| STT | Tên                                                                                                              | Link                                                                                                   |
| --- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| 1   | Mã nguồn **Webhook Event Handler** sample viết bằng PHP                                                          | <https://github.com/CassoHQ/casso-webhook-handler-sample>                                              |
| 2   | Mã nguồn **Webhook Event Handler** sample viết bằng Java                                                         | *Đang cập nhật. Liên hệ chúng tôi*                                                                     |
| 3   | Mã nguồn **Webhook Event Handler** sample viết bằng NodeJS                                                       | *Đang cập nhật. Liên hệ chúng tôi*                                                                     |
| 4   | Mã nguồn chính thức của Plugin Woocommerce `Casso – Tự động xác nhận thanh toán chuyển khoản ngân hàng`          | <https://plugins.trac.wordpress.org/browser/casso-tu-dong-xac-nhan-thanh-toan-chuyen-khoan-ngan-hang/> |
| 5   | Mã nguồn **hướng dẫn tạo và xác thực chữ ký số Webhook V2** viết bằng Java, C#, JavaScript, PHP, Python, Golang. | <https://github.com/CassoHQ/casso-webhook-v2-verify-signature>                                         |

Hãy bắt đầu&#x20;
