API接口使用
PaYphp码支付系统API接口使用指南
2024年1月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:请求签名,根据请求参数和商户密钥生成
签名算法
签名生成步骤
- 将所有请求参数(除 sign 外)按照参数名 ASCII 码从小到大排序
- 将排序后的参数按照 "参数名=参数值" 的格式拼接成字符串,参数之间用 "&" 连接
- 在拼接好的字符串末尾追加 "&key=商户密钥"
- 对最终的字符串进行 MD5 加密,并转为大写
签名示例
假设请求参数如下:
{
"app_id": "10001",
"out_trade_no": "202401230001",
"total_amount": "100.00",
"subject": "测试商品",
"timestamp": "1611123456",
"nonce_str": "abcdef123456"
}
商户密钥为:a5f3f71efb96fe68b1b8f3791a1e2e1d
签名生成过程:
- 参数排序:app_id、nonce_str、out_trade_no、subject、timestamp、total_amount
- 拼接字符串:
app_id=10001&nonce_str=abcdef123456&out_trade_no=202401230001&subject=测试商品×tamp=1611123456&total_amount=100.00&key=a5f3f71efb96fe68b1b8f3791a1e2e1d - 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);
});
最佳实践
安全建议
- 保护商户密钥:商户密钥是签名验证的关键,请妥善保管,不要泄露
- 验证通知签名:接收通知时,务必验证签名,防止伪造通知
- 使用 HTTPS:所有 API 请求和通知都应使用 HTTPS 加密传输
- 设置 IP 白名单:在商户后台设置 API 调用的 IP 白名单
- 定期更换密钥:建议定期更换商户密钥,提高安全性
开发建议
- 使用 SDK:推荐使用官方提供的 SDK,简化开发流程
- 处理重复通知:支付通知可能会重复发送,商户系统需要做好幂等性处理
- 日志记录:记录所有 API 请求和通知数据,便于问题排查
- 异常处理:妥善处理 API 调用过程中可能出现的异常情况
- 超时设置:设置合理的请求超时时间,避免长时间等待
接口调用频率
为了保证系统稳定性,API 接口有调用频率限制:
| 接口类型 | 限制频率 | |---------|---------| | 创建订单 | 100次/分钟 | | 查询订单 | 300次/分钟 | | 关闭订单 | 60次/分钟 | | 申请退款 | 60次/分钟 | | 查询退款 | 300次/分钟 |
超出限制频率的请求会被拒绝,返回错误码 1005(请求频率超限)。
常见问题
签名验证失败
可能原因:
- 商户密钥错误
- 参数排序不正确
- 参数值编码问题
- 签名算法不一致
解决方法:
- 检查商户密钥是否正确
- 确认参数按照 ASCII 码从小到大排序
- 确保参数值使用 UTF-8 编码
- 使用 MD5 算法并转为大写
订单创建失败
可能原因:
- 参数不完整或格式错误
- 商户订单号重复
- 金额格式不正确
- 商户状态异常
解决方法:
- 检查必填参数是否完整,格式是否正确
- 确保商户订单号唯一
- 金额格式为字符串,精确到小数点后两位
- 检查商户状态是否正常
通知接收问题
可能原因:
- 通知 URL 配置错误
- 服务器无法访问
- 响应格式不正确
- 处理超时
解决方法:
- 检查通知 URL 是否正确配置
- 确保服务器可以正常访问
- 返回正确的响应格式
- 优化通知处理逻辑,避免超时
接口更新日志
v1.2.0 (2024-01-20)
- 新增批量查询订单接口
- 新增交易统计接口
- 优化签名算法,提高安全性
- 修复部分已知问题
v1.1.0 (2023-12-15)
- 新增退款接口
- 新增退款查询接口
- 新增退款通知功能
- 优化订单查询性能
v1.0.0 (2023-11-01)
- 首次发布
- 支持基础支付功能
- 提供订单创建、查询、关闭接口
- 支持支付结果通知
联系与支持
如果您在使用 API 接口过程中遇到问题,可通过以下方式获取支持:
- 技术文档:查阅完整的 API 文档
- 开发者社区:加入开发者社区,与其他开发者交流
- 在线客服:工作时间内联系在线客服
- 邮件支持:发送邮件至 support@PaYphp.cn
- 问题反馈:在商户后台提交问题反馈
我们会在收到您的问题后,尽快为您解答。