Alipay OpenAPI SDK
简介
Alipay OpenAPI SDK for Node.js / 用于给 Node.js 服务器提供调用支付宝开放平台的能力。
包括向支付宝服务器发起 OpenAPI 请求、订单信息生成,以及配套的证书、加签和验签能力。
基于支付宝 API v3 接口规范实现。
同时支持 Commonjs 和 ESM 两种模块依赖方式引入,通过 TypeScript 实现,HTTP Client 使用 urllib。
环境要求
安装依赖
npm install alipay-sdk --save
平台配置
- 先前往支付宝开发平台-开发者中心完成开发者接入的一些准备工作,包括创建应用、为应用添加功能包、设置应用的接口加签方式等。
- 可以使用 支付宝开放平台秘钥工具 获取所需的公私钥,并在平台上上传公钥。
- 本 SDK 默认采用
PKCS1
的格式解析密钥,与密钥工具的默认生成格式不一致。
请使用密钥工具【格式转换】功能转为 PKCS1
,或在本 SDK 初始化时显式指定 keyType: 'PKCS8'
。
- 在设置加签方式结束之后,记录必要信息用于初始化 SDK。
- 公钥证书模式(推荐):
appId
、应用私钥
、应用公钥证书文件
、支付宝公钥证书文件
、支付宝根证书文件
- 公钥模式:
appId
、应用私钥
、应用公钥
、支付宝公钥
初始化 SDK
- 代码示例中的路径和文件名仅做示范,请根据项目实际读取文件所在的位置
- 请保存好私钥文件,避免信息泄露
普通公钥模式
import { AlipaySdk } from 'alipay-sdk';
const alipaySdk = new AlipaySdk({
appId: '2016123456789012',
privateKey: fs.readFileSync('private-key.pem', 'ascii'),
alipayPublicKey: fs.readFileSync('alipay-public-key.pem', 'ascii'),
});
证书模式
import { AlipaySdk } from 'alipay-sdk';
const alipaySdk = new AlipaySdk({
appId: '2016123456789012',
privateKey: fs.readFileSync('private-key.pem', 'ascii'),
alipayRootCertPath: path.join(__dirname, 'alipayRootCert.crt'),
alipayPublicCertPath: path.join(__dirname, 'alipayCertPublicKey_RSA2.crt'),
appCertPath: path.join(__dirname, 'appCertPublicKey.crt'),
});
验证配置
可以使用如下基础接口请求服务端,以验证配置正确。
const result = await alipaySdk.curl('POST', '/v3/alipay/user/deloauth/detail/query', {
body: {
date: '20230102',
offset: 20,
limit: 1,
},
});
console.log(result);
只要接口调用返回 responseHttpStatus 200,即代表验证配置成功
{
data: {},
responseHttpStatus: 200,
traceId: '06033316171731016275628924348'
}
其余情况,如代码报错,则说明未配置成功。
快速使用
curl 示例接口
用于向支付宝服务器发起请求,与具体接口相关的业务参数。
下面以 统一收单交易支付接口 为示例
const result = await alipay.curl('POST', '/v3/alipay/trade/pay', {
body: {
notify_url: 'http://www.your-notify.com/notify',
out_trade_no: '商家的交易码,需保持唯一性',
total_amount: '0.1',
subject: '测试订单',
}
});
console.log(result);
使用 AlipayFormData
表单上传文件
部分接口需要上传文件。
SDK 内部封装了一个 Form
对象,用以在发起 multipart/form-data
请求时使用。
以 支付宝文件上传接口 为例:
import { AlipayFormData } from 'alipay-sdk';
const form = new AlipayFormData();
form.addFile('file_content', '图片.jpg', path.join(__dirname, './test.jpg'));
const uploadResult = await sdkStable.curl<{
file_id: string;
}>('POST', '/v3/alipay/open/file/upload', {
form,
body: {
biz_code: 'openpt_appstore',
},
});
console.log(uploadResult);
pageExec 示例接口
pageExec
方法主要是用于网站支付接口请求链接生成,传入前台访问输入密码完成支付,
如电脑网站支付 alipay.trade.page.pay 等接口。
表单示例:
const bizContent = {
out_trade_no: "ALIPfdf1211sdfsd12gfddsgs3",
product_code: "FAST_INSTANT_TRADE_PAY",
subject: "abc",
body: "234",
total_amount: "0.01"
};
const html = sdk.pageExec('alipay.trade.page.pay', {
method: 'POST',
bizContent,
returnUrl: 'https://www.taobao.com'
});
<form action="https://openapi.alipay.com/gateway.do?method=alipay.trade.app.pay&app_id=2021002182632749&charset=utf-8&version=1.0&sign_type=RSA2×tamp=2023-02-28%2011%3A48%3A28&app_auth_token=202302BBbcfad868001a4df3bbfa99e8a6913F10&sign=j9DjDGgxLt3jbOQZy7q7Qu8baKWTl4hZlxOHa%2B46hC1djmFx%2FIyBqzQntPMurzz3f8efXJsalZz3nqZ9ClowCCxBfBvqE0cdzCDAeQ1GMgjd7dbWgjfNNcqKgmJPsIkLaHnP5vTvj%2BA27SqkeZCMbeVfv%2B4nYurXaFB9dNBtA%3D%3D" method="post" name="alipaySDKSubmit1677556108819" id="alipaySDKSubmit1677556108819">
<input type="hidden" name="alipay_sdk" value="alipay-sdk-nodejs-3.3.0" />
<input type="hidden" name="biz_content" value="{"out_trade_no":"ziheng-test-eeee","product_code":"QUICK_MSECURITY_PAY","subject":"订单标题","total_amount":"0.01","body":"订单描述"}" />
</form>
<script>document.forms["alipaySDKSubmit1677556108819"].submit();</script>
支付链接示例:
const url = sdk.pageExec('alipay.trade.page.pay', {
method: 'GET',
bizContent,
returnUrl: 'https://www.taobao.com'
});
sdkExec 示例接口
sdkExec
方法主要是服务端生成请求字符串使用的,不会直接支付扣款,需传值到客户端进行调用收银台输入密码完成支付,
如 App 支付接口 alipay.trade.app.pay。
const orderStr = sdk.sdkExec('alipay.trade.app.pay', {
bizContent: {
out_trade_no: "ALIPfdf1211sdfsd12gfddsgs3",
product_code: "FAST_INSTANT_TRADE_PAY",
subject: "abc",
body: "234",
total_amount: "0.01"
},
returnUrl: 'https://www.taobao.com'
});
console.log(orderStr);
my.tradePay({
orderStr,
success: (res) => {
my.alert({
content: JSON.stringify(res),
});
},
fail: (res) => {
my.alert({
content: JSON.stringify(res),
});
}
});
exec 示例接口(已废弃,请使用 curl 代替)
用于向支付宝服务器发起请求。与具体接口相关的业务参数,需要放在 bizContent
中。
const result = await alipay.exec('alipay.trade.pay', {
notify_url: 'http://www.your-notify.com/notify',
bizContent: {
out_trade_no: '商家的交易码,需保持唯一性',
total_amount: '0.1',
subject: '测试订单',
}
});
⚠️⚠️⚠️ 注意:部分接口的请求参数不在 bizContent
中,
如 alipay.system.oauth.token
,
具体可参考官网各接口定义。
通知验签
部分接口会设置回调地址,用于支付宝服务器向业务服务器通知业务情况(如交易成功)等。
此时业务服务应该验证该回调的来源安全性,确保其确实由支付宝官方发起。
SDK 提供了对应的通知验签能力。
const queryObj = {
sign_type: 'RSA2',
sign: 'QfTb8tqE1BMhS5qAn.....',
gmt_create: '2019-08-15 15:56:22',
other_biz_field: '....',
}
const signResult = sdk.checkNotifySign(queryObj);
如果遇到验签失败,请尝试使用 checkNotifySignV2()
方法代替,它默认不会对 value 进行 decode
如 https://github.com/alipay/alipay-sdk-nodejs-all/issues/45 提到的常见问题。
const postData = {
sign_type: 'RSA2',
sign: 'QfTb8tqE1BMhS5qAn.....',
gmt_create: '2019-08-15 15:56:22',
other_biz_field: '....',
}
const signResult = sdk.checkNotifySignV2(postData);
alipay-sdk v3 到 v4 的升级说明
从 v3 到 v4 有以下不兼容变更,请参考示例代码进行更新
-
Node.js 需要升级到 >= 18.20.0 及以上版本,可以到 Node.js 官方网站下载更新
-
Commonjs 通过 require('alipay-sdk')
引入细微变化
v3 是会直接导出到 module.exports
下
const AlipaySdk = require('alipay-sdk');
v4 是导出到 exports.AlipaySdk
下
const { AlipaySdk } = require('alipay-sdk');
-
exec()
方法如果传递 options.formData
不包含文件,会抛出 TypeError
异常 提示使用 pageExec()
方法代替
打印调试日志的方式
通过 NODE_DEBUG 环境变量打印 alipay-sdk 相关的调试日志
NODE_DEBUG=alipay-sdk* node your-script.js
问题反馈
如您在使用 Alipay SDK for Node.js 过程中遇到问题,
欢迎前往 支付宝开放社区 发帖与支付宝工作人员和其他开发者一起交流,
或联系 支付宝开放平台客服 协助解决。
API
new AlipaySdk(config)
Param | Type | Description |
---|
config | AlipaySdkConfig | 初始化 SDK 配置 |
AlipaySdkConfig
参数 | 说明 | 类型 | 必填 |
---|
appId | 应用ID | string | 是 |
privateKey | 应用私钥字符串。RSA 签名验签工具 | string | 是 |
signType | 签名种类,默认值是 "RSA2" | "RSA2" | "RSA" | 否 |
alipayPublicKey | 支付宝公钥(需要对返回值做验签时候必填,不填则会忽略验签) | string | 否 |
gateway | 网关 | string | 否 |
timeout | 网关超时时间(单位毫秒),默认值是 5000 | number | 否 |
camelcase | 是否把网关返回的下划线 foo_bar 转换为驼峰写法 fooBar ,默认值是 true | boolean | 否 |
keyType | 指定 privateKey 类型, 默认值是 "PKCS1" | "PKCS1" | "PKCS8" | 否 |
appCertPath | 应用公钥证书文件路径 | string | 否 |
appCertContent | 应用公钥证书文件内容 | string | Buffer | 否 |
appCertSn | 应用公钥证书sn | string | 否 |
alipayRootCertPath | 支付宝根证书文件路径 | string | 否 |
alipayRootCertContent | 支付宝根证书文件内容 | string | Buffer | 否 |
alipayRootCertSn | 支付宝根证书sn | string | 否 |
alipayPublicCertPath | 支付宝公钥证书文件路径 | string | 否 |
alipayPublicCertContent | 支付宝公钥证书文件内容 | string | Buffer | 否 |
alipayCertSn | 支付宝公钥证书sn | string | 否 |
encryptKey | AES 密钥,调用 AES加 解密相关接口时需要 | string | 否 |
wsServiceUrl | 服务器地址 | string | 否 |
alipaySdk.curl<T = any>(httpMethod, path, options?) ⇒ Promise<AlipayCommonResult<T>>
curl 方式调用支付宝 API v3 协议接口
Returns: Promise<AlipayCommonResult<T>>
- 请求执行结果
Param | Type | Description | Required |
---|
httpMethod | string | HTTP 请求方式,支持 GET, POST, PUT, DELETE 等 | 是 |
path | string | HTTP 请求 URL | 是 |
options | AlipayCURLOptions | 可选参数 | 否 |
options.query | Record<string, string | number> | 指该参数需在请求 URL 传参 | 否 |
options.body | Record<string, any> | 指该参数需在请求 JSON 传参 | 否 |
options.form | AlipayFormData | AlipayFormStream | 表单方式提交数据 | 否 |
options.requestId | string | 调用方的 requestId,不填会默认生成 uuid v4 | 否 |
options.needEncrypt | boolean | 自动 AES 加解密,默认值是 false | 否 |
AlipayCommonResult<T>
响应结果
参数 | 说明 | 类型 | 必须 |
---|
data | HTTP 接口响应返回的 JSON 数据 | T | 是 |
responseHttpStatus | HTTP 接口响应状态码 | number | 是 |
traceId | HTTP 接口响应 trace id | string | 是 |
alipaySdk.sdkExec(method, params) ⇒ string
生成请求字符串,用于客户端进行调用
Returns: string
- 请求字符串
Param | Type | Description |
---|
method | string | 方法名 |
params | IRequestParams | 请求参数 |
params.bizContent | object | 业务请求参数 |
alipaySdk.pageExec(method, params) ⇒ string
生成网站接口请求链接 URL 或 POST 表单 HTML
Returns: string
- 请求链接 URL 或 POST 表单 HTML
Param | Type | Description |
---|
method | string | 方法名 |
params | IRequestParams | 请求参数 |
params.bizContent | object | 业务请求参数 |
params.method | string | 后续进行请求的方法。如为 GET,即返回 http 链接;如为 POST,则生成表单 html |
deprecated
alipaySdk.exec(method, params, option) ⇒ Promise<AlipaySdkCommonResult>
执行请求,调用支付宝 API v2 协议接口
注意:此方法是为了让 alipay-sdk@3
尽量平滑升级到 alipay-sdk@4
保留,请尽快使用 alipaySdk.curl()
代替,走 API v3 协议。
Returns: Promise<AlipaySdkCommonResult>
- 请求执行结果
Param | Type | Description |
---|
method | string | 调用接口方法名,比如 alipay.ebpp.bill.add |
params | IRequestParams | 请求参数 |
params.bizContent | object | 业务请求参数 |
option | IRequestOption | 选项 |
option.validateSign | Boolean | 是否验签 |
args.log | object | 可选日志记录对象 |
AlipaySdkCommonResult
响应结果
IRequestParams
请求参数
参数 | 说明 | 类型 | 必须 |
---|
bizContent | 业务请求参数 | object | 否 |
needEncrypt | 自动 AES 加解密 | boolean | 否 |
alipaySdk.checkNotifySignV2(postData)
通知验签,默认不会对 value 进行 decode
Returns: Boolean
- 是否验签成功
Param | Type | Description |
---|
postData | JSON | 服务端的消息内容 |
alipaySdk.checkNotifySign(postData, raw)
通知验签
Returns: Boolean
- 是否验签成功
Param | Type | Description |
---|
postData | JSON | 服务端的消息内容 |
raw | Boolean | 是否使用 raw 内容而非 decode 内容验签 |
License
MIT
Contributors
Made with contrib.rocks.