第12章 支付宝SDK
支付宝SDK(Software Development Kit)是一套由支付宝官方提供的软件开发工具包,开发者可以将支付宝的核心功能便捷地集成到各类应用或网站中。其核心作用是打通商业场景与支付宝平台的支付、营销及数据能力,例如实现App或网页中的收款、转账、账单查询等交易流程,以及会员认证、芝麻信用、生活缴费等扩展服务。通过调用封装好的接口,开发者无需从零构建支付系统,即可安全高效地接入支付宝的生态服务。
支付宝的SDK支持多平台使用,包括iOS、Android、Web及多种后端语言版本(如Java、PHP、Python等),提供清晰的接口文档、示例代码和安全加固方案。开发者通过集成SDK,不仅能快速实现支付功能,还可利用支付宝的实名验证、风险监控等能力保障交易安全。典型应用场景涵盖电商购物、线下扫码、订阅扣费、公共服务等领域,大幅降低了企业接入移动支付的技术门槛与运维成本。
接下来,我们就学习如何接入支付宝SDK。需要从npm官网平台安装alipay-sdk,地址:www.npmjs.com/package/ali…
![]()
图12-1 支付宝SDK接入文档
## 12.1 初始化项目对支付宝SDK有一个初步的了解后,我们开始初始化对应的项目,需要如下两步:
(1)创建SDK项目文件夹,在该文件夹下创建index.ts文件(用于编写本次示例的逻辑代码)。
(2)npm安装alipay-sdk,并在package.json文件中设置ES模块。
# 安装命令
npm install alipay-sdk --save
安装好alipay-sdk库之后,package.json文件如下所示:
{
"type": "module",
"dependencies": {
"alipay-sdk": "^4.14.0"
}
}
12.2 初始化SDK
在支付宝SDK的接入文档中,初始化SDK有普通公钥模式和证书模式,选择普通公钥模式就可以。
import { AlipaySdk } from 'alipay-sdk';
// 实例化客户端
const alipaySdk = new AlipaySdk({
// 设置应用 ID
appId: 'your-APPID',
// 设置应用私钥
privateKey: fs.readFileSync('/path/to/private-key.pem', 'ascii'),
// 设置支付宝公钥
alipayPublicKey: fs.readFileSync('/path/to/alipay-public-key.pem', 'ascii'),
// 密钥类型,请与生成的密钥格式保持一致,参考平台配置一节
// keyType: 'PKCS1',
// 设置网关地址,默认是 https://openapi.alipay.com
// endpoint: 'https://openapi.alipay.com',
});
在接入文档所提供的示例中,需要应用私钥和支付宝公钥,需要先申请这两者。
应用私钥:opendocs.alipay.com/common/02ki…
通过点击上方应用私钥对应的地址链接,进入支付宝开放平台的密钥工具下载文档,如图12-2所示。在Windows和MacOS系统中,选择适配自己电脑的系统选项。
![]()
图12-2 密钥下载文档
安装好支付宝开放平台密钥工具如下所示,选择运行支付宝开放平台密钥工具,如图12-3所示。然后点击完成进入下一步。
![]()
图12-3 支付宝开放平台密钥工具安装
进入支付宝开放平台密钥工具后,选择生成密钥,其中加签方式和加密算法都不需要变动,直接生成密钥,如图12-4所示。
![]()
图12-4 支付宝开放平台密钥生成
生成密钥之后,会生成应用公钥和应用私钥,如图12-5所示。先复制应用公钥,等下会使用到。
![]()
图12-5 密钥工具生成应用公钥
支付宝公钥:openhome.alipay.com/develop/san…
通过点击上方支付宝公钥对应的地址链接,进入支付宝开放平台的控制条(用支付宝登录扫码),如图12-6所示。
![]()
图12-6 支付宝开放平台-控制台
点击左侧边栏的沙箱应用,在界面展示中有开发信息选项,下方是接口加签方式,如图12-7所示。
![]()
图12-7 支付宝开放平台-接口加签方式
在加签方式中选择自定义密钥,再选择公钥模式,进入设置并查看,会要求我们填写应用公钥,如图12-8所示。把图12-5的应用公钥粘贴到图12-8所示的位置。
![]()
图12-8 加签内容配置
填入应用公钥并保存之后,会进入加签内容完成环节,通过应用公钥,生成对应的支付宝公钥。
![]()
图12-9 加签内容完成
到目前为止,我们就通过密钥工具生成了应用公钥和应用私钥,然后通过应用公钥加签,得到支付宝公钥。则初始化SDK所需的应用私钥和支付宝公钥都已经获取到。
但应用私钥不能直接使用,需要对应用私钥进行转换,非Java环境(Node.js环境)的加密方式不太一样。点击如图12-5所示的打开文件位置,会有一个密钥+时间戳的文件夹,点击该文件夹内的应用私钥RSA2048,把应用私钥内部的内容复制一下,回到支付宝开放平台密钥工具的左侧边栏的格式转换,将应用私钥粘贴进去,转换成PKCS1格式的应用私钥,如图12-10所示。
![]()
图12-10 应用私钥格式转换
## 12.3 案例搭建现在可以回到项目中的index.ts文件中开始编写代码。其中appid不能随意填写,需要从支付宝开放平台的沙箱应用中,也就是如图12-6所在的位置,找到应用信息选项,在应用信息的基本信息中有APPID内容,如图12-11所示。将该内容复制到初始化SKD所需的appid中。
![]()
图12-11 APPID获取方式
其次还需要支付宝网关地址,获取位置在应用信息下方的开发信息的支付宝网关地址中,这部分都是一致的,但之后是有可能发生变化的,所以如果使用下方的支付宝网关地址不行的话,就需要自行去支付宝开放平台获取。
如果项目要上线的话,需要将支付宝网关地址换成线上的,目前的网关地址是沙箱环境的测试地址(有很多的钱可以模拟测试)。
import { AlipaySdk } from 'alipay-sdk'
// 初始化SDK
const alipay = new AlipaySdk({
// 设置应用ID
appId: "",
// 支付宝网关地址
gateway: "https://openapi-sandbox.dl.alipaydev.com/gateway.do",
// 设置应用私钥
privateKey: "",
// 设置应用公钥
alipayPublicKey: ""
})
接下来,我们主要调用支付宝用于网站支付接口请求连接生成,传入前台访问输入密码完成支付的接口。在支付宝接口文档中有对应信息,示例内容如下。
const bizContent = {
out_trade_no: "ALIPfdf1211sdfsd12gfddsgs3",
product_code: "FAST_INSTANT_TRADE_PAY",
subject: "abc",
body: "234",
total_amount: "0.01"
};
// 支付页面接口,返回 HTML 代码片段,内容为 Form 表单
const html = alipaySdk.pageExecute('alipay.trade.page.pay', 'POST', {
bizContent,
returnUrl: 'https://www.taobao.com'
});
我们需要做出如下修改:
(1)支付宝页面接口从alipaySdk切换为我们的alipay。
(2)将POST请求切换为GET请求,因为用不到表单。
const bizContent = { // 定义业务参数对象,包含订单核心信息
// 订单编号,通过算法生成(需确保唯一性)
out_trade_no: "ALIPfdf1211sdfsd12gfddsgs3", // 商户自定义订单号,用于支付宝系统识别
product_code: "FAST_INSTANT_TRADE_PAY", // 产品码,代表即时到账支付类型
subject: "abc", // 订单标题,显示在支付页面
body: "234", // 订单描述,可填写商品详情等附加信息
total_amount: "0.01" // 订单总金额(单位:元,需为字符串格式)
};
// 支付页面接口,返回 HTML 代码片段,内容为 Form 表单
const html = alipay.pageExecute('alipay.trade.page.pay', 'GET', { // 调用支付宝SDK生成支付页面表单
bizContent, // 传入上述业务参数对象
returnUrl: 'https://www.taobao.com' // 设置支付完成后,用户会同步跳转的返回地址
});
console.log(html);
修改完成后,使用Node.js运行index.ts文件,会输出html信息,说明SDK搭建完成,如图12-12所示。
![]()
图12-12 SDK搭建完成
SDK搭建完成之后,输出的html是一个URL地址,点击该地址进入浏览器,会进入支付宝即时到账交易界面,如图12-13所示。
![]()
图12-13 支付宝即时到账交易界面
那么这次即时到账交易所需的支付宝账户名和支付密码从哪里获取?回到支付宝开放平台的控制台中,左侧边栏有沙箱账号,点击之后,会弹出商家信息和买家信息。我们复制买家账号和支付密码,回到即时到账交易界面进行填写,其中密码不能粘贴,需要手动输入。
![]()
图12-14 支付宝沙箱账号
此时填写好信息之后,会进入收银台界面,如图12-15所示。需要再次输入支付宝支付密码,从而确定付款。
![]()
图12-15 支付宝收银台
输入支付宝支付密码并确认付款之后,会显示交易付款成功,并且开始跳转至商户页面。支付宝交易付款成功如图12-16所示。
![]()
图12-16 支付宝交易付款成功
跳转商户页面,实际会跳转到淘宝网页中,这是因为在代码中returnUrl字段信息所填写的是'www.taobao.com'(淘宝网页端)。
12.4 案例修改
但一般单页应用不需要重定向到商户页面,所以会使用异步通知的方式。
在单页应用(SPA)架构中,页面通过JavaScript动态更新内容而非整页刷新,若使用returnUrl进行同步跳转,会导致整个应用重新加载,破坏SPA的无刷新体验和前端路由状态。更重要的是,returnUrl的跳转依赖用户浏览器,可能因网络中断、页面关闭或拦截而丢失结果,且该方式仅作为支付完成后的引导跳转,其携带的URL参数易被篡改,不适合作为可信的业务状态变更依据。
异步通知(notify_url)由支付宝服务器在支付完成后主动回调商户后端接口,不依赖前端环境,保证了支付结果送达的可靠性。商户后端可独立验证签名、处理业务逻辑(如更新订单状态),再通过WebSocket、轮询或状态推送机制通知SPA前端更新界面,实现支付状态与业务数据的强一致性。这种前后端解耦的设计,既保持了SPA流畅的用户体验,也符合支付系统安全可靠的设计原则。
接下来回到index.ts文件,开始修改案例代码。
我们使用notify_url字段,但它只能接受一个公网地址,因为阿里服务器是没办法通知到我们电脑本地的。所以我们只有两种方式可以实现异步通知:
(1)将代码部署到服务器上。
(2)使用内网穿透。
// 支付页面接口,返回 HTML 代码片段,内容为 Form 表单
const html = alipay.pageExecute('alipay.trade.page.pay', 'GET', { // 调用支付宝SDK生成支付页面表单
bizContent, // 传入上述业务参数对象
notify_url:"",
// returnUrl: 'https://www.taobao.com' // 设置支付完成后用户同步跳转的返回地址
});
在内网开发的情况中,使用内网穿透是会更方便一些。
首先需要先提供一个接口地址,因此需要在本地起一个服务,我们通过express来操作。
npm i express
npm i --save-dev @types/express
编写如下express初始化代码,因为阿里的回调时通过Unicode的方式去回调,而不是通过JSON格式,所以需要通过express.urlencoded()方法去解析一下post请求。
import express from "express"
const app = express()
app.use(express.json())
app.use(express.urlencoded({ extended: true })) // 解析post请求
然后编写接口请求,如果不知道要通过post请求还是get请求,则可以使用all(同时支持post与get请求),其实使用post请求就可以。因为支付宝的支付结果是异步返回的,即用户支付成功后,支付宝服务器会主动向商户的后台服务器发送一个POST请求,通知支付结果。这个通知是异步的,不依赖于用户浏览器跳转(即使用户关闭浏览器,支付宝也会发送这个通知)。
具体来说,分以下3步:
(1)我们在发起支付请求时,通过notify_url参数指定支付宝服务器发送异步通知的地址(例如:yourdomain.com/alipay/noti…
(2)当支付完成后,支付宝服务器会向这个地址发送一个POST请求,携带支付结果的信息。
(3)我们的服务器接收到这个通知后,需要验证这个通知的合法性(验证签名),然后根据支付结果更新我们自己的订单状态,并返回一个成功响应给支付宝。
最后,监听本地3000端口。
app.all('/alipay/notify', (req, res) => {
console.log(req.body);
// 返回成功响应给支付宝
res.send('success');
})
app.listen(3000, () => {
console.log('Server is running on port 3000');
})
接下来需要内网穿透,然后将公网地址填写到notify_url字段中,启动express服务。重复支付宝的付款操作,当成功付款后,支付宝会回调一系列参数信息给我们。我们只需要把这些参数放入数据库中就可以。