# 自定义支付渠道

除了 Cloudreve 已经支持的支付平台以外，你也可以通过实现 Cloudreve 的付款接口来对接你自己的支付平台，或是桥接其他第三方平台。

自定义支付接口你实现需要一个独立的 HTTP 服务，并提供：

* 暴露一个 API 端点，用于处理 Cloudreve 的创建订单请求，并返回支付页面 URL；
* 客户完成支付后，发送 HTTP 请求到指定的 URL 以通知 Cloudreve 支付完成。

## 支付接口定义

按照本章规范实现你的支付接口，部署接口并确保其能与 Cloudreve 相互进行网络通信。

### 创建订单

## 当有新订单创建时，Cloudreve 向支付你的接口发送的请求。

<mark style="color:green;">`POST`</mark> `<你的支付接口>`

#### Headers

| Name                   | Type   | Description                                                          |
| ---------------------- | ------ | -------------------------------------------------------------------- |
| Authorization          | String | <p>使用您在后台设定的</p><p><code>通信密钥</code></p><p>计算的签名，详情请参阅“验证请求签名”小节</p> |
| X-Cr-Cloudreve-Version | String | Cloudreve 主程序的版本                                                     |
| X-Cr-Site-Id           | String | Cloudreve 的站点 ID，可用于区分不同站点                                           |
| X-Cr-Site-Url          | String | Cloudreve 的站点 URL                                                    |

#### Request Body

| Name                                          | Type   | Description                                  |
| --------------------------------------------- | ------ | -------------------------------------------- |
| name<mark style="color:red;">\*</mark>        | String | 订单标题                                         |
| order\_no<mark style="color:red;">\*</mark>   | String | 订单编号                                         |
| notify\_url<mark style="color:red;">\*</mark> | String | 支付成功的回调通知 URL，详情请参考后续“支付成功回调”章节。请存储此项以便后续使用。 |
| amount<mark style="color:red;">\*</mark>      | String | 订单总金额，单位：分                                   |

{% tabs %}
{% tab title="200: OK 订单创建成功时" %}

```javascript
{
    // 成功的响应固定为 0
    "code": 0,
    // 付款收银台页面的 URL，默认会被生成为二维码展示给用户，用户也可选择直接
    // 打开此 URL
    "data": "https://examplepayment.com/checkout/26544743"
}
```

{% endtab %}

{% tab title="200: OK 订单创建失败时" %}

```javascript
{
    // 任意非0代码表示订单创建失败
    "code": 500,
    // 错误的详细描述
    "error": "Failed to create a payment."
}
```

{% endtab %}
{% endtabs %}

请求实例：

```http
POST /order/create
Host: examplepayment.com
Authorization: Bearer Vep6hl1x8fiQLasEauMEUqxFKyEqSXb9D_BBQpOiTd8=:1676027218
X-Cr-Site-Url: https://demo.cloudreve.org
X-Cr-Site-Id: b7de8bba-8f86-40fe-8171-c2625b6c4a61
X-Cr-Cloudreve-Version: 3.6.2

{
   "name":"Cloudreve - 10 GB 容量包",
   "order_no":"20230209190648343421",
   "notify_url":"http://demo.cloudreve.org/api/v3/callback/custom/20230209190648343421/363f8866-6d0a-4dbf-a560-0c17de2eb7f9?sign=F-AdeTf7cR1uwmV1dqJ1kN_POGivKk_awMRPZUCZyhA%3D%3A1676027208",
   "amount":100
}
```

#### 验证请求签名

你可以在 Cloudreve 后台设定`通信密钥`，Cloudreve 创建订单的请求会使用此密钥进行加密并放在`Authorization` header 中，你可以通过以下算法验证这一签名：

1. 将 `Authorization` 值中 `Bearer` 之后的部分取出，使用`:`分割字符串，其第二部分是签名过期的时间戳，验证确保其大于当前时间戳。将`:`前一部分记为`SIGNATURE`；
2. 参考 [getSignContent](https://github.com/cloudreve/Cloudreve/blob/b441d884f61d59da86d861b14d1302ec25bbea40/pkg/auth/auth.go#L71) 对请求正文及 header进行编码，并使用 HMAC 算法对编码内容及过期时间戳计算签名：[Sign](https://github.com/cloudreve/Cloudreve/blob/b441d884f61d59da86d861b14d1302ec25bbea40/pkg/auth/hmac.go#L20)；
3. 对比签名后的内容和`SIGNATURE`是否一致。

### 支付成功回调

当用户完成支付后，你需要向此订单被创建时制定的 `notify_url` 发送一个 GET 请求以通知 Cloudreve 用户完成支付。如果回调请求失败，请以指数后退间隔进行重试，除非响应中明确返回了错误信息及代码。

## 用户完成支付后，向订单关联的 \`notify\_url\` 发送请求通知 Cloudreve 支付成功。

<mark style="color:blue;">`GET`</mark> `<notify_url>`

{% tabs %}
{% tab title="200: OK 请求成功" %}

```javascript
{
    "code": 0
}
```

{% endtab %}

{% tab title="200: OK 订单处理失败" %}

```javascript
{
    // 任意非0代码表示订单创建失败
    "code": 500,
    // 错误的详细描述
    "error": "Failed to fulfill a payment."
}
```

{% endtab %}
{% endtabs %}

## 添加支付接口

实现并部署支付接口后，请在 Cloudreve 后台 - 增值服务 - 自定义支付渠道 中开启并填写接口地址。

## 第三方实现

| 支付平台 | 许可    | 文档                                                |
| ---- | ----- | ------------------------------------------------- |
| 易支付  | 开放源代码 | <https://github.com/topjohncian/cloudreve-epay>   |
| 爱发电  | MIT许可 | <https://github.com/essesoul/Cloudreve-AfdianPay> |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docsv3.cloudreve.org/use/pro/pay.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
