Skip to content

Custom Payment Provider

Pro edition

This section introduces a Pro edition feature.

In addition to the payment providers already supported by Cloudreve, you can also integrate your own payment platform by implementing Cloudreve's payment interface, or bridge other third-party platforms.

To implement a custom payment interface, you need an independent HTTP service that provides:

  • An API endpoint to:
    • Handle Cloudreve's payment creation requests and return a payment page URL;
    • Handle Cloudreve's requests to query the payment status of an order;
  • After the customer completes the payment, send an HTTP request to a specified URL to notify Cloudreve of the payment completion.

Implementing the Payment Interface

Implement your payment interface according to the specifications in this chapter, deploy the interface, and ensure it can communicate with Cloudreve over the network.

Warning

The custom payment API for version 3 is not compatible with version 4.

Create Order POST <your-payment-endpoint>

When a new order is created, Cloudreve sends a request to your payment interface.

Request Headers

NameTypeDescription
AuthorizationStringA signature calculated using the Communication key you set in the backend. See Verify Signature for details.
X-Cr-VersionStringCloudreve version number
X-Cr-Site-IdStringCloudreve site ID, which can be used to distinguish different sites
X-Cr-Site-UrlStringThe main site URL of Cloudreve.

Request Body

The request body is sent in JSON format and includes the following fields:

NameTypeDescription
nameStringPayment name
order_noStringOrder number
notify_urlStringCallback notification URL
amountNumberPayment amount, using the smallest unit of currency
currencyStringISO 4217 code of the currency

Request Example

http
POST /order
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-Version: 4.0.0

{
   "name": "Unlimited Storage",
   "order_no": "20230209190648343421",
   "notify_url": "http://demo.cloudreve.org/api/v4/callback/custom/20230209190648343421",
   "amount": 8900,
   "currency": "CNY"
}

Expected Response

Regardless of whether the order creation is successful, the HTTP response code should be 200, with success or failure determined by the code field in the response body.

http
HTTP/1.1 200 OK

{
    // A successful response is always 0
    "code": 0,
    // The URL of the payment checkout page, which will be generated as a QR code for the user to scan, or they can choose to open this URL directly
    "data": "https://examplepayment.com/checkout/26544743"
}

Query Order Status GET <your-payment-endpoint>

When Cloudreve needs to query the order status, it sends a request to your endpoint.

Request Headers

NameTypeDescription
AuthorizationStringA signature calculated using the Communication key you set in the backend. See Verify Signature for details.
X-Cr-VersionStringCloudreve version number
X-Cr-Site-IdStringCloudreve site ID, which can be used to distinguish different sites
X-Cr-Site-UrlStringThe main site URL of Cloudreve.

Request Parameters

Request parameters are sent as URL parameters and include the following fields:

NameTypeDescription
order_noStringOrder number

Request Example

http
GET /order?order_no=20230209190648343421
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-Version: 4.0.0

Expected Response

http
HTTP/1.1 200 OK

{
    "code": 0,
    // PAID - Paid
    // Other values - Not paid
    "data": "PAID"
}

Verify Signature

You can set a communication key in the Cloudreve payment settings. Cloudreve's payment creation requests will use this key for signing and place it in the Authorization header. You can verify this signature using the following algorithm:

  1. Extract the part after Bearer in the Authorization value, split the string by :, and the second part is the expiration timestamp of the signature, noted as timestamp. Verify that it is greater than the current timestamp. The part before : is noted as signature;

  2. Iterate over all request headers, filter out those prefixed with X-Cr-, convert them to key=value format, then sort and join the results with & to form the string signedHeaderStr.

go
var signedHeader []string
for k, _ := range r.Header {
	if strings.HasPrefix(k, "X-Cr-") {
		signedHeader = append(signedHeader, fmt.Sprintf("%s=%s", k, r.Header.Get(k)))
	}
}
sort.Strings(signedHeader)
signedHeaderStr := strings.Join(signedHeader, "&")
  1. Encode the request URL's Path part, request body, and signedHeaderStr as a JSON string signContent.
go
type RequestRawSign struct {
	Path   string
	Header string
	Body   string
}

signContent, err := json.Marshal(RequestRawSign{
	Path:   r.URL.Path,
	Header: signedHeaderStr,
	Body:   string(r.Body),
})
  1. Concatenate signContent and timestamp with : to form the string signContentFinal, and use the HMAC algorithm and Communication key to calculate the signature for signContentFinal, noted as signActual.
go
signContentFinal := fmt.Sprintf("%s:%s", signContent, timestamp)
signActual := hmac.New(sha256.New, []byte(Communication key)).Sum([]byte(signContentFinal))
  1. Compare signActual with signature to check for consistency.

Send Callback

After the user completes the payment, you need to send a GET request to the notify_url specified when the payment was created to notify Cloudreve that the user has completed the payment. If the callback request fails, retry with exponential backoff unless the response explicitly returns an error message and code. An example response from Cloudreve is as follows:

http
HTTP/1.1 200 OK

{
    // A successful response is always 0
    "code": 0
}