API接口使用

PaYphp码支付系统API接口使用指南

发布日期: 2024-01-23

API接口使用指南

PaYphp 码支付系统提供了完善的 API 接口,方便商户系统与支付系统进行对接。本文档将详细介绍 API 接口的使用方法和注意事项。

API 概述

接口规范

PaYphp 码支付系统的 API 接口采用 RESTful 风格设计,具有以下特点:

  • 请求方式:主要使用 POST 方法
  • 数据格式:请求和响应均使用 JSON 格式
  • 字符编码:统一使用 UTF-8 编码
  • 安全认证:采用签名机制确保请求的合法性
  • 错误处理:统一的错误码和错误信息格式

接口地址

API 接口的基础地址为:

https://您的域名/api/v1

例如,创建订单的接口地址为:

https://您的域名/api/v1/order/create

接口认证

所有 API 请求都需要进行签名认证,确保请求的合法性和安全性。认证信息包括:

  • app_id:商户 ID,在商户后台获取
  • timestamp:请求时间戳,精确到秒
  • nonce_str:随机字符串,用于防止重放攻击
  • sign:请求签名,根据请求参数和商户密钥生成

签名算法

签名生成步骤

  1. 将所有请求参数(除 sign 外)按照参数名 ASCII 码从小到大排序
  2. 将排序后的参数按照 "参数名=参数值" 的格式拼接成字符串,参数之间用 "&" 连接
  3. 在拼接好的字符串末尾追加 "&key=商户密钥"
  4. 对最终的字符串进行 MD5 加密,并转为大写

签名示例

假设请求参数如下:

{
  "app_id": "10001",
  "out_trade_no": "202401230001",
  "total_amount": "100.00",
  "subject": "测试商品",
  "timestamp": "1611123456",
  "nonce_str": "abcdef123456"
}

商户密钥为:a5f3f71efb96fe68b1b8f3791a1e2e1d

签名生成过程:

  1. 参数排序:app_id、nonce_str、out_trade_no、subject、timestamp、total_amount
  2. 拼接字符串:app_id=10001&nonce_str=abcdef123456&out_trade_no=202401230001&subject=测试商品&timestamp=1611123456&total_amount=100.00&key=a5f3f71efb96fe68b1b8f3791a1e2e1d
  3. MD5 加密并转大写:A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6

最终请求参数:

{
  "app_id": "10001",
  "out_trade_no": "202401230001",
  "total_amount": "100.00",
  "subject": "测试商品",
  "timestamp": "1611123456",
  "nonce_str": "abcdef123456",
  "sign": "A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6"
}

核心接口

1. 创建订单

接口说明

该接口用于创建支付订单,获取支付链接或二维码。

请求地址

POST /api/v1/order/create

请求参数

| 参数名 | 类型 | 必填 | 描述 | |-------|------|-----|------| | app_id | String | 是 | 商户ID | | out_trade_no | String | 是 | 商户订单号,需保证唯一性 | | total_amount | String | 是 | 订单金额,单位元,精确到小数点后两位 | | subject | String | 是 | 商品标题 | | body | String | 否 | 商品描述 | | notify_url | String | 是 | 支付结果通知地址 | | return_url | String | 否 | 支付完成后跳转地址 | | payment_method | String | 否 | 支付方式,不传则显示所有可用支付方式 | | expire_time | Integer | 否 | 订单有效期,单位分钟,默认30分钟 | | timestamp | String | 是 | 请求时间戳 | | nonce_str | String | 是 | 随机字符串 | | sign | String | 是 | 请求签名 |

请求示例

{
  "app_id": "10001",
  "out_trade_no": "202401230001",
  "total_amount": "100.00",
  "subject": "测试商品",
  "body": "这是一个测试商品",
  "notify_url": "https://www.example.com/notify",
  "return_url": "https://www.example.com/return",
  "payment_method": "wechat",
  "expire_time": 30,
  "timestamp": "1611123456",
  "nonce_str": "abcdef123456",
  "sign": "A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6"
}

响应参数

| 参数名 | 类型 | 描述 | |-------|------|-----| | code | Integer | 状态码,0表示成功,非0表示失败 | | message | String | 状态描述 | | data | Object | 响应数据 | | data.order_no | String | 系统订单号 | | data.out_trade_no | String | 商户订单号 | | data.total_amount | String | 订单金额 | | data.payment_url | String | 支付链接 | | data.qrcode_url | String | 二维码图片URL | | data.qrcode_data | String | 二维码内容 | | data.expire_time | String | 订单过期时间 |

响应示例

{
  "code": 0,
  "message": "success",
  "data": {
    "order_no": "P202401230001",
    "out_trade_no": "202401230001",
    "total_amount": "100.00",
    "payment_url": "https://pay.example.com/pay/P202401230001",
    "qrcode_url": "https://pay.example.com/qrcode/P202401230001",
    "qrcode_data": "https://pay.example.com/pay/P202401230001",
    "expire_time": "2024-01-23 12:30:00"
  }
}

2. 查询订单

接口说明

该接口用于查询订单状态。

请求地址

POST /api/v1/order/query

请求参数

| 参数名 | 类型 | 必填 | 描述 | |-------|------|-----|------| | app_id | String | 是 | 商户ID | | order_no | String | 否 | 系统订单号,与商户订单号二选一 | | out_trade_no | String | 否 | 商户订单号,与系统订单号二选一 | | timestamp | String | 是 | 请求时间戳 | | nonce_str | String | 是 | 随机字符串 | | sign | String | 是 | 请求签名 |

请求示例

{
  "app_id": "10001",
  "out_trade_no": "202401230001",
  "timestamp": "1611123456",
  "nonce_str": "abcdef123456",
  "sign": "A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6"
}

响应参数

| 参数名 | 类型 | 描述 | |-------|------|-----| | code | Integer | 状态码,0表示成功,非0表示失败 | | message | String | 状态描述 | | data | Object | 响应数据 | | data.order_no | String | 系统订单号 | | data.out_trade_no | String | 商户订单号 | | data.total_amount | String | 订单金额 | | data.status | Integer | 订单状态:0-待支付,1-支付成功,2-支付失败,3-已关闭,4-已退款 | | data.payment_method | String | 支付方式 | | data.trade_no | String | 支付平台交易号 | | data.pay_time | String | 支付时间 | | data.create_time | String | 创建时间 |

响应示例

{
  "code": 0,
  "message": "success",
  "data": {
    "order_no": "P202401230001",
    "out_trade_no": "202401230001",
    "total_amount": "100.00",
    "status": 1,
    "payment_method": "wechat",
    "trade_no": "4200001234202401231234567890",
    "pay_time": "2024-01-23 12:15:30",
    "create_time": "2024-01-23 12:00:00"
  }
}

3. 关闭订单

接口说明

该接口用于关闭未支付的订单。

请求地址

POST /api/v1/order/close

请求参数

| 参数名 | 类型 | 必填 | 描述 | |-------|------|-----|------| | app_id | String | 是 | 商户ID | | order_no | String | 否 | 系统订单号,与商户订单号二选一 | | out_trade_no | String | 否 | 商户订单号,与系统订单号二选一 | | timestamp | String | 是 | 请求时间戳 | | nonce_str | String | 是 | 随机字符串 | | sign | String | 是 | 请求签名 |

请求示例

{
  "app_id": "10001",
  "out_trade_no": "202401230001",
  "timestamp": "1611123456",
  "nonce_str": "abcdef123456",
  "sign": "A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6"
}

响应参数

| 参数名 | 类型 | 描述 | |-------|------|-----| | code | Integer | 状态码,0表示成功,非0表示失败 | | message | String | 状态描述 | | data | Object | 响应数据 | | data.order_no | String | 系统订单号 | | data.out_trade_no | String | 商户订单号 | | data.status | Integer | 订单状态:3-已关闭 |

响应示例

{
  "code": 0,
  "message": "success",
  "data": {
    "order_no": "P202401230001",
    "out_trade_no": "202401230001",
    "status": 3
  }
}

4. 申请退款

接口说明

该接口用于对已支付的订单申请退款。

请求地址

POST /api/v1/refund/apply

请求参数

| 参数名 | 类型 | 必填 | 描述 | |-------|------|-----|------| | app_id | String | 是 | 商户ID | | order_no | String | 否 | 系统订单号,与商户订单号二选一 | | out_trade_no | String | 否 | 商户订单号,与系统订单号二选一 | | out_refund_no | String | 是 | 商户退款单号,需保证唯一性 | | refund_amount | String | 是 | 退款金额,不能大于订单金额 | | refund_reason | String | 否 | 退款原因 | | notify_url | String | 否 | 退款结果通知地址 | | timestamp | String | 是 | 请求时间戳 | | nonce_str | String | 是 | 随机字符串 | | sign | String | 是 | 请求签名 |

请求示例

{
  "app_id": "10001",
  "out_trade_no": "202401230001",
  "out_refund_no": "R202401230001",
  "refund_amount": "100.00",
  "refund_reason": "商品质量问题",
  "notify_url": "https://www.example.com/refund_notify",
  "timestamp": "1611123456",
  "nonce_str": "abcdef123456",
  "sign": "A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6"
}

响应参数

| 参数名 | 类型 | 描述 | |-------|------|-----| | code | Integer | 状态码,0表示成功,非0表示失败 | | message | String | 状态描述 | | data | Object | 响应数据 | | data.refund_no | String | 系统退款单号 | | data.out_refund_no | String | 商户退款单号 | | data.order_no | String | 系统订单号 | | data.out_trade_no | String | 商户订单号 | | data.refund_amount | String | 退款金额 | | data.status | Integer | 退款状态:0-处理中,1-退款成功,2-退款失败 |

响应示例

{
  "code": 0,
  "message": "success",
  "data": {
    "refund_no": "R202401230001",
    "out_refund_no": "R202401230001",
    "order_no": "P202401230001",
    "out_trade_no": "202401230001",
    "refund_amount": "100.00",
    "status": 0
  }
}

5. 查询退款

接口说明

该接口用于查询退款状态。

请求地址

POST /api/v1/refund/query

请求参数

| 参数名 | 类型 | 必填 | 描述 | |-------|------|-----|------| | app_id | String | 是 | 商户ID | | refund_no | String | 否 | 系统退款单号,与商户退款单号二选一 | | out_refund_no | String | 否 | 商户退款单号,与系统退款单号二选一 | | timestamp | String | 是 | 请求时间戳 | | nonce_str | String | 是 | 随机字符串 | | sign | String | 是 | 请求签名 |

请求示例

{
  "app_id": "10001",
  "out_refund_no": "R202401230001",
  "timestamp": "1611123456",
  "nonce_str": "abcdef123456",
  "sign": "A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6"
}

响应参数

| 参数名 | 类型 | 描述 | |-------|------|-----| | code | Integer | 状态码,0表示成功,非0表示失败 | | message | String | 状态描述 | | data | Object | 响应数据 | | data.refund_no | String | 系统退款单号 | | data.out_refund_no | String | 商户退款单号 | | data.order_no | String | 系统订单号 | | data.out_trade_no | String | 商户订单号 | | data.refund_amount | String | 退款金额 | | data.status | Integer | 退款状态:0-处理中,1-退款成功,2-退款失败 | | data.refund_time | String | 退款时间 | | data.create_time | String | 创建时间 |

响应示例

{
  "code": 0,
  "message": "success",
  "data": {
    "refund_no": "R202401230001",
    "out_refund_no": "R202401230001",
    "order_no": "P202401230001",
    "out_trade_no": "202401230001",
    "refund_amount": "100.00",
    "status": 1,
    "refund_time": "2024-01-23 14:30:00",
    "create_time": "2024-01-23 14:00:00"
  }
}

通知接口

支付结果通知

通知说明

当订单支付成功后,系统会向商户提供的 notify_url 发送支付结果通知。

通知方式

  • 请求方式:POST
  • 数据格式:JSON
  • 字符编码:UTF-8

通知参数

| 参数名 | 类型 | 描述 | |-------|------|-----| | app_id | String | 商户ID | | order_no | String | 系统订单号 | | out_trade_no | String | 商户订单号 | | total_amount | String | 订单金额 | | status | Integer | 订单状态:1-支付成功 | | payment_method | String | 支付方式 | | trade_no | String | 支付平台交易号 | | pay_time | String | 支付时间 | | timestamp | String | 通知时间戳 | | nonce_str | String | 随机字符串 | | sign | String | 通知签名 |

通知示例

{
  "app_id": "10001",
  "order_no": "P202401230001",
  "out_trade_no": "202401230001",
  "total_amount": "100.00",
  "status": 1,
  "payment_method": "wechat",
  "trade_no": "4200001234202401231234567890",
  "pay_time": "2024-01-23 12:15:30",
  "timestamp": "1611123456",
  "nonce_str": "abcdef123456",
  "sign": "A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6"
}

响应要求

商户系统接收到通知后,需要返回以下格式的响应:

{
  "code": 0,
  "message": "success"
}

如果系统未收到正确的响应,将按照一定的时间间隔进行重试,重试次数和间隔可在后台配置。

退款结果通知

通知说明

当退款处理完成后,系统会向商户提供的退款通知地址发送退款结果通知。

通知方式

  • 请求方式:POST
  • 数据格式:JSON
  • 字符编码:UTF-8

通知参数

| 参数名 | 类型 | 描述 | |-------|------|-----| | app_id | String | 商户ID | | refund_no | String | 系统退款单号 | | out_refund_no | String | 商户退款单号 | | order_no | String | 系统订单号 | | out_trade_no | String | 商户订单号 | | refund_amount | String | 退款金额 | | status | Integer | 退款状态:1-退款成功,2-退款失败 | | refund_time | String | 退款时间 | | timestamp | String | 通知时间戳 | | nonce_str | String | 随机字符串 | | sign | String | 通知签名 |

通知示例

{
  "app_id": "10001",
  "refund_no": "R202401230001",
  "out_refund_no": "R202401230001",
  "order_no": "P202401230001",
  "out_trade_no": "202401230001",
  "refund_amount": "100.00",
  "status": 1,
  "refund_time": "2024-01-23 14:30:00",
  "timestamp": "1611123456",
  "nonce_str": "abcdef123456",
  "sign": "A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6"
}

响应要求

商户系统接收到通知后,需要返回以下格式的响应:

{
  "code": 0,
  "message": "success"
}

错误码说明

| 错误码 | 描述 | 解决方案 | |-------|------|---------| | 0 | 成功 | - | | 1001 | 参数错误 | 检查请求参数是否完整、格式是否正确 | | 1002 | 签名错误 | 检查签名算法和商户密钥是否正确 | | 1003 | 商户不存在 | 检查商户ID是否正确 | | 1004 | 商户已禁用 | 联系管理员处理 | | 2001 | 订单不存在 | 检查订单号是否正确 | | 2002 | 订单已支付 | 不能重复支付,可查询订单状态 | | 2003 | 订单已关闭 | 订单已关闭,需要重新创建订单 | | 2004 | 订单已过期 | 订单已过期,需要重新创建订单 | | 3001 | 支付渠道错误 | 检查支付渠道参数是否正确 | | 3002 | 支付渠道未开通 | 联系管理员开通相应支付渠道 | | 4001 | 退款金额错误 | 检查退款金额是否正确,不能大于订单金额 | | 4002 | 订单未支付,不能退款 | 确认订单已支付后再申请退款 | | 4003 | 退款单不存在 | 检查退款单号是否正确 | | 9999 | 系统错误 | 联系技术支持处理 |

SDK 使用

为了方便商户对接,PaYphp 码支付系统提供了多种语言的 SDK。

PHP SDK

安装

使用 Composer 安装:

composer require PaYphp/sdk

初始化

<?php
require 'vendor/autoload.php';

use PaYphp\SDK\Client;

$config = [
    'app_id' => '10001',
    'app_key' => 'a5f3f71efb96fe68b1b8f3791a1e2e1d',
    'api_url' => 'https://您的域名/api/v1',
];

$client = new Client($config);

创建订单

<?php
$params = [
    'out_trade_no' => '202401230001',
    'total_amount' => '100.00',
    'subject' => '测试商品',
    'body' => '这是一个测试商品',
    'notify_url' => 'https://www.example.com/notify',
    'return_url' => 'https://www.example.com/return',
    'payment_method' => 'wechat',
    'expire_time' => 30,
];

$result = $client->createOrder($params);
print_r($result);

查询订单

<?php
$result = $client->queryOrder([
    'out_trade_no' => '202401230001',
]);
print_r($result);

关闭订单

<?php
$result = $client->closeOrder([
    'out_trade_no' => '202401230001',
]);
print_r($result);

申请退款

<?php
$result = $client->applyRefund([
    'out_trade_no' => '202401230001',
    'out_refund_no' => 'R202401230001',
    'refund_amount' => '100.00',
    'refund_reason' => '商品质量问题',
]);
print_r($result);

查询退款

<?php
$result = $client->queryRefund([
    'out_refund_no' => 'R202401230001',
]);
print_r($result);

验证通知

<?php
$notifyData = $_POST; // 获取通知数据
$isValid = $client->verifyNotify($notifyData);

if ($isValid) {
    // 处理通知逻辑
    echo json_encode(['code' => 0, 'message' => 'success']);
} else {
    echo json_encode(['code' => 1002, 'message' => 'sign error']);
}

Node.js SDK

安装

npm install PaYphp-sdk

初始化

const PaYphp = require('PaYphp-sdk');

const client = new PaYphp.Client({
  appId: '10001',
  appKey: 'a5f3f71efb96fe68b1b8f3791a1e2e1d',
  apiUrl: 'https://您的域名/api/v1',
});

创建订单

const params = {
  outTradeNo: '202401230001',
  totalAmount: '100.00',
  subject: '测试商品',
  body: '这是一个测试商品',
  notifyUrl: 'https://www.example.com/notify',
  returnUrl: 'https://www.example.com/return',
  paymentMethod: 'wechat',
  expireTime: 30,
};

client.createOrder(params)
  .then(result => {
    console.log(result);
  })
  .catch(error => {
    console.error(error);
  });

查询订单

client.queryOrder({ outTradeNo: '202401230001' })
  .then(result => {
    console.log(result);
  })
  .catch(error => {
    console.error(error);
  });

最佳实践

安全建议

  1. 保护商户密钥:商户密钥是签名验证的关键,请妥善保管,不要泄露
  2. 验证通知签名:接收通知时,务必验证签名,防止伪造通知
  3. 使用 HTTPS:所有 API 请求和通知都应使用 HTTPS 加密传输
  4. 设置 IP 白名单:在商户后台设置 API 调用的 IP 白名单
  5. 定期更换密钥:建议定期更换商户密钥,提高安全性

开发建议

  1. 使用 SDK:推荐使用官方提供的 SDK,简化开发流程
  2. 处理重复通知:支付通知可能会重复发送,商户系统需要做好幂等性处理
  3. 日志记录:记录所有 API 请求和通知数据,便于问题排查
  4. 异常处理:妥善处理 API 调用过程中可能出现的异常情况
  5. 超时设置:设置合理的请求超时时间,避免长时间等待

接口调用频率

为了保证系统稳定性,API 接口有调用频率限制:

| 接口类型 | 限制频率 | |---------|---------| | 创建订单 | 100次/分钟 | | 查询订单 | 300次/分钟 | | 关闭订单 | 60次/分钟 | | 申请退款 | 60次/分钟 | | 查询退款 | 300次/分钟 |

超出限制频率的请求会被拒绝,返回错误码 1005(请求频率超限)。

常见问题

签名验证失败

可能原因:

  1. 商户密钥错误
  2. 参数排序不正确
  3. 参数值编码问题
  4. 签名算法不一致

解决方法:

  1. 检查商户密钥是否正确
  2. 确认参数按照 ASCII 码从小到大排序
  3. 确保参数值使用 UTF-8 编码
  4. 使用 MD5 算法并转为大写

订单创建失败

可能原因:

  1. 参数不完整或格式错误
  2. 商户订单号重复
  3. 金额格式不正确
  4. 商户状态异常

解决方法:

  1. 检查必填参数是否完整,格式是否正确
  2. 确保商户订单号唯一
  3. 金额格式为字符串,精确到小数点后两位
  4. 检查商户状态是否正常

通知接收问题

可能原因:

  1. 通知 URL 配置错误
  2. 服务器无法访问
  3. 响应格式不正确
  4. 处理超时

解决方法:

  1. 检查通知 URL 是否正确配置
  2. 确保服务器可以正常访问
  3. 返回正确的响应格式
  4. 优化通知处理逻辑,避免超时

接口更新日志

v1.2.0 (2024-01-20)

  • 新增批量查询订单接口
  • 新增交易统计接口
  • 优化签名算法,提高安全性
  • 修复部分已知问题

v1.1.0 (2023-12-15)

  • 新增退款接口
  • 新增退款查询接口
  • 新增退款通知功能
  • 优化订单查询性能

v1.0.0 (2023-11-01)

  • 首次发布
  • 支持基础支付功能
  • 提供订单创建、查询、关闭接口
  • 支持支付结果通知

联系与支持

如果您在使用 API 接口过程中遇到问题,可通过以下方式获取支持:

  1. 技术文档:查阅完整的 API 文档
  2. 开发者社区:加入开发者社区,与其他开发者交流
  3. 在线客服:工作时间内联系在线客服
  4. 邮件支持:发送邮件至 support@PaYphp.cn
  5. 问题反馈:在商户后台提交问题反馈

我们会在收到您的问题后,尽快为您解答。