沙箱环境配置
打开‘支付宝开发者中心’并登录,点击->进入我的控制台
配置秘钥
点击 RSA2(SHA256)密钥 设置,
node API 配置
首先安装 Alipay SDK:
npm install alipay-sdk -S sdk 配置语法 alipaySdk.exec(method, params, options);
- method:字符串类型,调用的 Api,比如 alipay.trade.page.pay ;
- params:可选参数,对象结构,Api 的请求参数;
- options:包含
- validateSign:布尔值,是否对返回值验签,需要依赖支付宝公钥;
- formData:对象结构,文件上传类接口的请求参数;
- log:对象结构,存在时会调用 info、error 方法写日志。
由于每次调用 AlipaySdk 的 API 都是同一个对象,所以该对象只需要实例化一次:
// alipay.js 这里单独存放一个文件中,需要时引入即可 const AlipaySdk = require('alipay-sdk').default; // 引入 SDK const alipaySdk = new AlipaySdk({ appId: 'appId', // 开放平台上创建应用时生成的 appId signType: 'RSA2', // 签名算法,默认 RSA2 gateway: 'https://openapi.alipaydev.com/gateway.do', // 支付宝网关地址 ,沙箱环境下使用时需要修改 alipayPublicKey: 'public_key', // 支付宝公钥,需要对结果验签时候必填 privateKey: 'private_key', // 应用私钥字符串 }); module.exports = alipaySdk;
要完成支付,需要以下几个步骤,
- 服务器端需要调用支付 API alipay.trade.page.pay 来获取支付页面的地址;
- 服务器端需要调用支付 API alipay.trade.page.pay 来获取支付页面的地址;
先来看看服务端接口的实现:
var express = require('express'); var router = express.Router(); const alipaySdk = require('../utils/alipay'); const AlipayFormData = require('alipay-sdk/lib/form').default; // alipay.trade.page.pay 返回的内容为 Form 表单 router.post('/pcpay', (req, res) => { (async () => { // 调用 setMethod 并传入 get,会返回可以跳转到支付页面的 url const formData = new AlipayFormData(); formData.setMethod('get'); // 通过 addField 增加参数 // 在用户支付完成之后,支付宝服务器会根据传入的 notify_url,以 POST 请求的形式将支付结果作为参数通知到商户系统。 formData.addField('notifyUrl', 'http://www.com/notify'); // 支付成功回调地址,必须为可以直接访问的地址,不能带参数 formData.addField('bizContent', { outTradeNo: req.body.outTradeNo, // 商户订单号,64个字符以内、可包含字母、数字、下划线,且不能重复 productCode: 'FAST_INSTANT_TRADE_PAY', // 销售产品码,与支付宝签约的产品码名称,仅支持FAST_INSTANT_TRADE_PAY totalAmount: '0.01', // 订单总金额,单位为元,精确到小数点后两位 subject: '商品', // 订单标题 body: '商品详情', // 订单描述 }); // 如果需要支付后跳转到商户界面,可以增加属性"returnUrl" const result = await alipaySdk.exec( 'alipay.trade.page.pay', // 统一收单下单并支付页面接口 {}, // api 请求的参数(包含“公共请求参数”和“业务参数”) {formData: formData},); // result 为可以跳转到支付链接的 url res.json({url: result}); })(); });
然后就是前端页面,这个比较简单,就是点击支付按钮,向服务器发起请求,拿到返回的支付页面地址后进行跳转:
$.ajax({ method: 'POST', url: '/alipay/pcpay', data: { outTradeNo // 商户订单号,必须保证唯一,生成方法有很多,可以去看我的代码 }}).done(function(res) { window.open(res.url, '_blank'); }). fail(function (err) { console.log(err); });
如果上诉没有问题,我们应该能看到这样的页面:
可以通过前端发送订单号到服务器进行查询,服务器向支付宝服务器查询该订单号支付的相关信息,通过交易状态来确定是否已经完成支付,具体服务器配置如下:
const axios = require('axios'); const alipaySdk = require('../utils/alipay'); const AlipayFormData = require('alipay-sdk/lib/form').default; router.get('/query', function (req, res) { (async function () { const {outTradeNo} = req.query; const formData = new AlipayFormData(); formData.setMethod('get'); formData.addField('bizContent', { outTradeNo }); // 通过该接口主动查询订单状态 const result = await 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('交易创建,等待买家付款'); break; case 'TRADE_CLOSED': res.send('未付款交易超时关闭,或支付完成后全额退款'); break; case 'TRADE_SUCCESS': res.send('交易支付成功'); break; case 'TRADE_FINISHED': res.send('交易结束,不可退款'); break; } } else if (r.code === '40004') { res.send('交易不存在'); } }).catch(err => { res.json({ msg: '查询失败', err }); }); })(); }) ;