# 创建协议支付订单


创建协议支付订单接口，用于开发者基于用户已签约的签约单发起代扣支付。调用成功后，平台将自动从用户签约的支付渠道中扣款，无需用户再次确认。适用于自动续费、周期性扣款等协议支付场景。

## 使用限制

- 调用频次限制：请遵守平台默认 QPS 限制，避免高频调用。
- 发起协议支付前，需确保签约单状态为 SIGN（已签约），否则将创建失败。
- out_pay_order_no（商户代扣单号）不可重复，重复提交将返回错误。

## 接口说明

- 业务场景：适用于开发者在用户签约后，基于签约关系自动发起代扣支付。常见场景包括：会员自动续费、周期性订阅扣款、定期服务费代扣等。
- 前提条件：调用方需已完成应用创建，并通过 get_client_token 接口获取到有效的应用级 AccessToken。用户需已完成签约（签约单状态为 SIGN）。
- 注意事项：
- auth_order_id 为平台侧签约单号，用于标识扣款对应的签约关系。
- pay_data 中包含代扣订单的详细信息，包括金额、商品列表、回调地址等。
- 创建成功后返回 pay_order_id（平台代扣单号），后续可用于查询或关闭代扣订单。
- 支付结果将通过 pay_notify_url 异步回调通知开发者。

## 基本信息

| 名称 | 描述 |
|-|-|
| HTTP Path | /api/trade_basic/v1/developer/create_sign_pay |
| HTTP Method | POST |
| Scope | trade.sign_pay.create |
| 权限要求 | - 需要申请权限 - 申请路径：豆包开放平台控制台 > 应用详情 > 能力 > 支付权限 - 需要应用级 AccessToken |

## 请求头

| 名称 | 类型 | 必填 | 描述 |
|-|-|-|-|
| content-type | string | 是 | 固定值 application/json |
| x-DB-AccessToken | string | 是 | 调用 get_client_token 接口生成的应用级访问凭证 |
| X-DB-SessionToken | string | 是 | 用户会话凭证 |

## 请求参数

### Body

| 名称 | 类型 | 是否必填 | 描述 | 示例值 |
|-|-|-|-|-|
| auth_order_id | string | 是 | 平台侧签约单的单号，长度不超过 64 byte | 80214322040407612\*\*\* |
| pay_data | object | 是 | 签约代扣订单数据，详见下方 pay_data 字段说明 | 见下方 pay_data 字段说明 |

### pay_data 字段说明

| 名称 | 类型 | 是否必填 | 描述 | 示例值 |
|-|-|-|-|-|
| out_pay_order_no | string | 是 | 商户代扣单号，长度不超过 64 byte，需保证唯一性 | SIGNPAY2024010100\*\*\* |
| order_name | string | 是 | 订单名称 | 月度会员自动续费 |
| order_desc | string | 否 | 订单描述 | 2024年1月会员自动续费 |
| total_amount | string | 是 | 订单总金额，单位：分 | 1000 |
| currency | string | 是 | 币种，固定值 CNY | CNY |
| pay_expire_seconds | string | 否 | 支付超时时间，单位：秒 | 3600 |
| pay_notify_url | string | 是 | 支付结果回调地址，用于接收支付结果异步通知 | [https://example.com/pay/notify](https://example.com/pay/notify) |
| sku_list | array | 否 | 商品列表，详见下方 sku_list 字段说明 | 见下方 sku_list 字段说明 |

### sku_list 字段说明

| 名称 | 类型 | 是否必填 | 描述 | 示例值 |
|-|-|-|-|-|
| sku_id | string | 是 | 商品 ID | SKU001 |
| title | string | 是 | 商品名称 | 月度会员 |
| price | string | 是 | 商品单价，单位：分 | 1000 |
| quantity | string | 是 | 商品数量 | 1 |
| total_amount | string | 是 | 商品总金额，单位：分 | 1000 |

## 请求示例

cURL

```shell
curl -X POST 'https://api.doubao-dev.com/api/trade_basic/v1/developer/create_sign_pay' \
  -H 'content-type: application/json' \
  -H 'x-DB-AccessToken: clt.943da17996fb5cebfbc70c044c3fc25a57T54DcjT6HNKGqn******' \
  -d '{
    "auth_order_id": "80214322040407612***",
    "pay_data": {
        "out_pay_order_no": "SIGNPAY2024010100***",
        "order_name": "月度会员自动续费",
        "order_desc": "2024年1月会员自动续费",
        "total_amount": "1000",
        "currency": "CNY",
        "merchant_uid": "MER_USER_001***",
        "pay_expire_seconds": "3600",
        "pay_notify_url": "https://example.com/pay/notify",
        "sku_list": [
            {
                "sku_id": "SKU001",
                "title": "月度会员",
                "price": "1000",
                "quantity": "1",
                "total_amount": "1000"
            }
        ]
    }
  }'
```

Go

```go
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)

func main() {
    url := "https://api.doubao-dev.com/api/trade_basic/v1/developer/create_sign_pay"
    reqBody := map[string]interface{}{
        "auth_order_id": "80214322040407612***",
        "pay_data": map[string]interface{}{
            "out_pay_order_no":  "SIGNPAY2024010100***",
            "order_name":        "月度会员自动续费",
            "order_desc":        "2024年1月会员自动续费",
            "total_amount":      "1000",
            "currency":          "CNY",
            "merchant_uid":      "MER_USER_001***",
            "pay_expire_seconds": "3600",
            "pay_notify_url":    "https://example.com/pay/notify",
            "sku_list": []map[string]string{
                {
                    "sku_id":       "SKU001",
                    "title":        "月度会员",
                    "price":        "1000",
                    "quantity":     "1",
                    "total_amount": "1000",
                },
            },
        },
    }
    jsonData, _ := json.Marshal(reqBody)

    req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
    req.Header.Set("content-type", "application/json")
    req.Header.Set("x-DB-AccessToken", "clt.943da17996fb5cebfbc70c044c3fc25a57T54DcjT6HNKGqn******")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer resp.Body.Close()
    body, _ := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))
}
```

Java

```java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class CreateSignPay {
    public static void main(String[] args) throws Exception {
        String url = "https://api.doubao-dev.com/api/trade_basic/v1/developer/create_sign_pay";
        String requestBody = "{"
            + "\"auth_order_id\":\"80214322040407612***\","
            + "\"pay_data\":{"
            + "\"out_pay_order_no\":\"SIGNPAY2024010100***\","
            + "\"order_name\":\"月度会员自动续费\","
            + "\"order_desc\":\"2024年1月会员自动续费\","
            + "\"total_amount\":\"1000\","
            + "\"currency\":\"CNY\","
            + "\"merchant_uid\":\"MER_USER_001***\","
            + "\"pay_expire_seconds\":\"3600\","
            + "\"pay_notify_url\":\"https://example.com/pay/notify\","
            + "\"sku_list\":[{\"sku_id\":\"SKU001\",\"title\":\"月度会员\",\"price\":\"1000\",\"quantity\":\"1\",\"total_amount\":\"1000\"}]"
            + "}}";

        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("content-type", "application/json")
                .header("x-DB-AccessToken", "clt.943da17996fb5cebfbc70c044c3fc25a57T54DcjT6HNKGqn******")
                .POST(HttpRequest.BodyPublishers.ofString(requestBody))
                .build();

        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(response.body());
    }
}
```

Node.js

```javascript
const axios = require('axios');

async function createSignPay() {
    const url = 'https://api.doubao-dev.com/api/trade_basic/v1/developer/create_sign_pay';
    const headers = {
        'content-type': 'application/json',
        'x-DB-AccessToken': 'clt.943da17996fb5cebfbc70c044c3fc25a57T54DcjT6HNKGqn******'
    };
    const data = {
        auth_order_id: '80214322040407612***',
        pay_data: {
            out_pay_order_no: 'SIGNPAY2024010100***',
            order_name: '月度会员自动续费',
            order_desc: '2024年1月会员自动续费',
            total_amount: '1000',
            currency: 'CNY',
            merchant_uid: 'MER_USER_001***',
            pay_expire_seconds: '3600',
            pay_notify_url: 'https://example.com/pay/notify',
            sku_list: [
                {
                    sku_id: 'SKU001',
                    title: '月度会员',
                    price: '1000',
                    quantity: '1',
                    total_amount: '1000'
                }
            ]
        }
    };

    try {
        const response = await axios.post(url, data, { headers });
        console.log(response.data);
    } catch (error) {
        console.error('Error:', error.message);
    }
}

createSignPay();
```

## 响应参数

| 名称 | 类型 | 是否必填 | 描述 | 示例值 |
|-|-|-|-|-|
| code | int32 | 是 | 错误码，0 表示成功，非 0 表示失败 | 0 |
| msg | string | 是 | 错误提示 | success |
| log_id | string | 是 | 请求日志 ID，用于问题排查时提供给技术支持 | 2023010128382726 |
| data | object | 否 | 创建结果对象，仅在创建成功时返回 | 见下方 data 字段说明 |

### data 字段说明

| 名称 | 类型 | 是否必填 | 描述 | 示例值 |
|-|-|-|-|-|
| pay_order_id | string | 是 | 平台代扣单号，可用于后续查询或关闭代扣订单 | 90214322040407612\*\*\* |

## 响应示例

### 正常示例

```json
{
    "data": {
        "pay_order_id": "90214322040407612***"
    },
    "code": 0,
    "msg": "success",
    "log_id": "2022092115392201020812109511046"
}
```

### 异常示例

```json
{
    "code": 500000001,
    "msg": "Parameter error",
    "log_id": "2022092115392201020812109511047",
    "data": null
}
```

## 错误码

### 通用错误码

| 错误码 | 错误名称 | 描述（msg） | 排查建议 |
|-|-|-|-|
| 0 | Success | success | 请求成功，无需处理 |
| 500000000 | OApiCommonInternalError | internal error | 系统内部错误，请稍后重试；若持续出现请携带 log_id 联系技术支持 |
| 500000001 | OApiCommonDeveloperParamError | Parameter error | 请求参数错误，请检查 auth_order_id、pay_data 各字段是否正确传入且格式合法 |
| 500000002 | OApiCommonDeveloperRateLimitError | Rate limit error | 请求触发限流，请降低调用频率后重试 |
| 500000003 | OApiCommonVerifySignFailError | Verify sign fail | 签名验证失败，请检查 x-DB-AccessToken 是否有效、是否过期，必要时重新调用 get_client_token 获取新 token |
