Node接入支付宝开放平台的沙箱实现支付功能
一些重要的支付宝沙箱文档及网址
- 支付宝开放平台:https://open.alipay.com/
- 简单介绍:https://www.yuque.com/chenqiu/alipay-node-sdk/guide
- 支付宝开放平台API:https://open.alipay.com/api
- 支付宝开放平台文档:https://opendocs.alipay.com/home
支付流程介绍
图片来自支付宝开放平台。
上面的流程图,已经大致描述了发起支付的过程,这里笔者用自己的语言,详细地转化一下:
下单。这里的下单,在项目中往往表现为用户确认了订单、然后选择支付方式、点击立即支付,即当用户点击“立即支付”时才产生的动作。 这一步要发送一个请求到我们的服务器,假如说系统中立即支付的API路径是/pay,参数一般就是订单包含的订单项,如商品id、购买数量、优惠券id等。
服务器端处理用户的下单请求。在这一步,是业务比较多的一步,也是关键步骤。我们根据客户端传来的商品id、数量、优惠券等参数,计算出每一个商品的单价、订单的总金额等(金额是不应该由客户端直接传的,应该由服务器端计算,更安全)。再生成一个订单号。然后调用一个接口,把这些参数(如商品名称、支付金额、订单号等)打包传给支付宝,也就是对应上图中的1.1。
依然是处理用户的下单请求,只是我嫌段落太长,换一段。在图中的1.1,我们调用了支付宝的接口。其实图中还少了一步1.2,那就是支付宝会返回一段html文档,就是大家经常看到的带二维码的PC端支付页面。请注意,到这一步,对客户端来说依然是在访问/pay接口,因为我们还没有对请求作出响应,只是一直在和支付宝交互罢了。所以,我们把支付宝返回的html文档作为响应信息,返回给客户端,客户端直接加载这一段html文档,用户就看到了一个支付页面。
到了这里,对应上图中的2、3、4、5步,和我们的服务器就没关系了,完全是用户在进行支付的过程。
到了第6步,用户支付完成,支付宝会跳转到一个我们指定的网页,这个网页一般是我们自定义的页面,比如在网页上显示“您已成功购买xxx商品,感谢您的支持”等。注意,此处的returnUrl只是跳转到我们自定义的友好页面,告诉用户支付成功了,只做展示用途,并非真正的支付回调。
到了第7步,支付宝会调用我们指定的回调API接口,将一些参数传给我们,如交易流水号、订单号,我们可以根据这些信息查询交易是否真的成功了(第8步),从而执行后续的业务,比如将订单状态变为已支付、给用户增加积分、扣减优惠券……等。
沙箱环境简介与配置
支付宝有一个供开发者测试使用的沙箱环境,会提供一个沙箱版的支付宝app、一个商家账户、一个买家账户。有了这个,可以让我们跳过商家入驻、企业资质审核等过程,开箱即用,降低了学习成本。
现在,让我们简单的配置沙箱环境。
1、进入到支付宝支付官网,用你自己的支付宝扫码登录,再点击进入管理中心。
2、点击进入沙箱应用。
此时就到了沙箱应用的控制台,进入之后要创建一个应用。
3、生成安全密钥
此部分的官方文档为:https://opendocs.alipay.com/common/02kipl。
进入该网址下载支付宝官方的密钥生成工具应用。
进入应用后,根据开发语言选择密钥格式和密钥长度。注意此处要选择RSA2。
然后点击生成密钥,工具会自动生成商户应用公钥(public_key)和应用私钥(private_key)。
这里有几个密钥要注意一下:
- 应用公钥(public key):需提供给支付宝账号管理者上传到支付宝开放平台。
- 应用私钥(private key):由开发者自己保存,需填写到代码中供签名时使用。
- 支付宝公钥:支付宝提供的公钥,用于接入服务。
还有要注意的事情为:
- 生成的私钥需妥善保管,避免遗失,不要泄露。
- 密钥和应用(APPID)一一对应,即开发者需要为名下的每个应用分别设置密钥,且不同应用的密钥不能混用。
4、配置安全密钥
用上述的工具生成密钥之后,要把应用公钥上传到支付宝开发者平台,如图点击切换为自定义密钥。
在弹出的窗口,把刚才生成的应用公钥复制粘贴进去,点击确定,就可以看到这个界面了,注意这里的支付宝公钥:
5、下载支付宝沙箱APP及账号管理
“支付宝沙箱APP”可以在官网找到,直接下载即可。
在沙箱控制台当中,点击“沙箱账号”,就可以看到当前应用对应的沙箱账号,用来登录我们的沙箱版支付宝APP进行测试。
上面的是商家的账号,下面是买家的测试账号。
6、学会看文档
在支付宝开放平台,点击文档,即可查看文档。如果要查看API就点击API,如果要查看技术的总体介绍,就点击文档。
比如点击API,然后选择场景:
比如说选择电脑网站支付,就可以查看到这些API列表。点击后面的查看文档就可以查看到这些API详细的参数。
其实不同场景的API是差不多的,例如“下单并支付页面”的接口,电脑网站支付的API接口路径为“alipay.trade.page.pay”,而手机端的则为“alipay.trade.wap.pay”。
7、开始写代码
下载依赖
npm install alipay-sdk
封装SDK
appId在上面进入沙箱控制台的时候就可以看到了。
注意下面的支付宝公钥和应用私钥,都是步骤二里的。
const AlipaySdk = require('alipay-sdk').default; // 引入 SDK
const alipaySdk = new AlipaySdk({appId: '此处要修改', // 开放平台上创建应用时生成的 appIdsignType: 'RSA2', // 签名算法,默认 RSA2gateway: 'https://openapi.alipaydev.com/gateway.do', // 支付宝网关地址 ,沙箱环境下使用时需要修改 正式线上的时候换成 https://openapi.alipay.com/gateway.doalipayPublicKey: '此处要修改', // 支付宝公钥,需要对结果验签时候必填privateKey: '此处要修改', // 应用私钥字符串
});
module.exports = alipaySdk;//正式环境只要把上述换成正式的就可以了
创建提交交易信息的表单
注意这里要编写的参数是在上面的API文档里可以查看到。
const AlipayFormData = require("alipay-sdk/lib/form").default;
const formData = new AlipayFormData();
formData.setMethod('get');
formData.addField('bizContent', {outTradeNo: '15693801273225', // 商户订单号,64个字符以内、可包含字母、数字、下划线,且不能重复productCode: 'FAST_INSTANT_TRADE_PAY', // 销售产品码,与支付宝签约的产品码名称,仅支持FAST_INSTANT_TRADE_PAYtotalAmount: '0.01', // 订单总金额,单位为元,精确到小数点后两位subject: '商品', // 订单标题body: '商品详情', // 订单描述
});
// 表示异步通知回调,
formData.addField('notifyUrl', 'https://www.baidu.com');
// 付款成功的跳转页面
formData.addField('returnUrl', 'https://www.bilibili.com');
这里的notifyUrl和returnUrl要做一个区分:
- notifyUrl:消息回调的接口,当付款成功,支付宝会发送成功信息到我们的项目当中,告诉我们付款成功了,即我们项目自己定义的接口,需要公网能够访问到的地址,即**项目要上线。**如果是自己本地的测试项目,可以配置内网穿透。
- returnUrl:付款成功之后,页面会自动跳转的嘛,returnUrl就表示这个跳转的地址。
发送交易请求:调用SDK的exec()方法
该方法有三个参数:
const result = await alipaySdk.exec(method, params, options);
- method:String 调用的 Api,比如 alipay.system.oauth.token
- params:Api 的请求参数(包含“公共请求参数”和“业务参数”)
- options:可以传入我们的formData
- 更详细请查看:https://www.yuque.com/chenqiu/alipay-node-sdk/exec
具体实例:
// 付款API:https://opendocs.alipay.com/apis/api_1/alipay.trade.pay?scene=32
async function test() {const result = await alipaySdk.exec( // result 为可以跳转到支付链接的 url'alipay.trade.page.pay', // 统一收单下单并支付页面接口{}, // api 请求的参数(包含“公共请求参数”和“业务参数”){formData: formData},);console.log(result)
}
test()
到这里,我们查看一下这个result是什么?
把这个复制到浏览器里,咱们就来到了支付界面啦,这里就可以登录我们的沙箱买家测试账号进行付款了:
代码跳转的话代码如下:
goPay() {let data = {orderId: 't454545212121' //随机生成唯一的就行了这个 自己找吧}var instance = this.$axios.create({headers: {'content-type': 'application/x-www-form-urlencoded'}});// 代理到 http://localhost:3000/api/pcpayinstance.post(`http://localhost:3000/api/pcpay`, this.$qs.stringify(data)).then(res =>{this.data=res;window.open(res.data.result)});}
付款完毕之后,就会跳转到returnUrl的网址喽。
有没有发现method就是API文档里的接口名称?没错!
咱们上面调用了“alipay.trade.page.pay”这个接口来下单与付款,下面我们再来看看如何用“alipay.trade.query”查看这个订单的状态。
async function check() {let outTradeNo = "15693801273225";const formData = new AlipayFormData();formData.setMethod('get');formData.addField('bizContent', {outTradeNo});// 通过该接口主动查询订单状态// 查询订单状态:https://opendocs.alipay.com/apis/api_1/alipay.trade.query?scene=23let result = await alipaySdk.exec('alipay.trade.query', {}, {formData: formData},);
console.log(result)}check()
这里的result还是一个网址,我们需要axios请求这个网址,才能查看订单状态:
/*** 添加购物车提交订单支付宝支付后查询订单状态是否成功 */
router.post('/api/member/queryOrderAlipay', (req, res) => {let orderId=req.body.orderIdconst formData = new AlipayFormData();formData.setMethod('get');formData.addField('bizContent', {orderId});// 通过该接口主动查询订单状态const result = alipaySdk.exec('alipay.trade.query',{},{ formData: formData },);axios({method: 'GET',url: result}).then(data => {let r = data.data.alipay_trade_query_response;if(r.code === '10000') { // 接口调用成功switch(r.trade_status) {case 'WAIT_BUYER_PAY':res.send({"success": true,"message": "success","code": 200,"timestamp": (new Date()).getTime(),"result": {"status":0,"massage":'交易创建,等待买家付款'}})break;case 'TRADE_CLOSED':res.send({"success": true,"message": "success","code": 200,"timestamp": (new Date()).getTime(),"result": {"status":1,"massage":'未付款交易超时关闭,或支付完成后全额退款'}})break;case 'TRADE_SUCCESS':res.send({"success": true,"message": "success","code": 200,"timestamp": (new Date()).getTime(),"result": {"status":2,"massage":'交易支付成功'}})break;case 'TRADE_FINISHED':res.send({"success": true,"message": "success","code": 200,"timestamp": (new Date()).getTime(),"result": {"status":3,"massage":'交易结束,不可退款'}})break;}} else if(r.code === '40004') {res.send('交易不存在');}}).catch(err => {res.json({msg: '查询失败',err});});})
状态码可以通过上面API文档查看:
参考链接
- https://blog.csdn.net/rapguys/article/details/115763799
- https://blog.51cto.com/lllomh/3037337
Node接入支付宝开放平台的沙箱实现支付功能相关推荐
- Go语言接入支付宝开放平台
首先登录支付宝开放平台 https://open.alipay.com/platform/home.htm 身份验证什么的按照提示来就行 选择 开发中心-网页&移动应用,选择应用类型 ,写名字 ...
- 【精华贴】支付宝开放平台简介
一.支付宝开放平台是什么? 支付宝开放平台将强大的支付.营销.数据能力,通过接口等形式开放给自研商家与服务商(ISV),帮助商家创建更具竞争力的应用.还可协助商家进行推广营销. 商家接入开放平台后,基 ...
- 支付宝支付_支付宝开放平台_API _SpringBoot_沙箱环境
文章目录 一.支付宝接口 1-1]官网中设置 配置信息 1-2]创建项目 1-3]测试 及 Bug 排除 一.支付宝接口 1-1]官网中设置 配置信息 注:未登录方式 -- 百度[支付宝开放平台]-[ ...
- 支付宝开放平台—开发中心—沙箱环境—详细步骤与操作说明
支付宝开放平台-沙箱环境详细配置步骤 沙箱环境配置文档参考:https://docs.open.alipay.com/200/105311/ 应用开发文档参考:https://docs.open.al ...
- 支付宝开放平台开发助手_支付宝:如何创建和接入支付宝电脑网站支付-新手必备...
1.登录支付宝 1.打开支付宝官网,以"我是支付宝商家"用户登录 https://www.alipay.com/ 2.进入"产品中心",选择并申请支付类型 2. ...
- 支付宝开放平台C++方式接入
链接:https://github.com/ArthasModern/AlipayOpenapiCpp 如果你想以C\C++方式接入支付宝开放平台调用支付宝的各种开放接口(比如收款等),那么你可以参考 ...
- c语言 支付宝接口开发平台,支付宝开放平台的C++版接入代码
该项目为C++项目,包含访问支付宝开放平台(Openapi)网关的源码: /** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ...
- php对接支付宝当面付对接,支付宝开放平台当面付对接网站
最近才发现当面付这个支付宝官方审核不严格,不审核网站有没有备案,比直接对接支付宝的电脑手机支付好. 先去支付宝商家用户中心签约下当面付功能,不过据说现在当面付签约要求挺严格的,需要门头照啥的,我们旗下 ...
- android支付宝开放平台开发,支付宝开放平台支付更新升级全解析
由于支付宝增加开放平台的概念,支付申请和调用有了较大的更新和升级,本篇文章会带你介绍开放平台的支付申请方式和新支付接口和之前的区别. 0 系列文章 1 背景介绍 支付宝现在开始着重推开发平台这个概念, ...
最新文章
- 数组方法关于任意数字类型的数组求最大值解决办法
- react-native 安卓支持 gif动态图
- centos 关闭防火墙
- 深度学习-机器学习(5.1支持向量机)
- android自定义图片加载,Android自定义ProgressDialog加载图片
- MATLAB中的for循环
- echo print printf() sprintf()区别
- Android编程入门很简单pdf
- 关于我玩单片机学习路线(个人总结)
- NCBI中Entrez Direct的使用
- Java中常见的5种WEB服务器介绍以及性能配置要点总结
- SQL(Oracle) 日期转换为英文年月格式
- react 实现tab切换 三角形筛选样式
- node安装不能正常使用 Error: ENOENT: no such file or directory, mkdir ‘D:\‘
- PMP备考之路 - 敏捷实践第五讲(实施敏捷:在敏捷环境中交付)
- 软件设计·用户界面设计
- Unity(十七) 在Unity中Android使用FTP进行上传、下载、文件创建(客户端部分)
- android 滑动手势处理,Android实现手势滑动的方法
- Big.js基本用法
- loadrunner监控iis指标
热门文章
- java中addrange_java elasticsearch 桶聚合(bucket)
- python中wraps作用
- C语言实现单片机整点蜂鸣器报时
- error C2447: “{”: 缺少函数标题(是否是老式的形式表?)(转)
- 高通音频调试 以及系统属性介绍
- 英语中元音辅音-持续更新中
- SQL中的distinct的使用方法
- 语音合成(speech synthesis)方向二:鲁棒TTS(Robust TTS)
- Xamarin ListView Dynamic ItemTemplate
- 编码技巧——验签加密算法工具及支付下单签名