配置支付宝支付
一.场景
二、实现效果
1.发起支付订单


2.确认支付订单并进行扫码支付



3.确认订单支付状态


4.退款申请


三.具体配置
1.准备工作
- 登录支付宝开放平台:https://open.alipay.com

- 进行后台,创建网页应用

- 绑定产品—【当面付】,并进行开通

- 接口加签方式设置

2.获取调用接口所需具体公共参数
以扫码付接口为例:
https://opendocs.alipay.com/open/f540afd8_alipay.trade.precreate?pathHash=d3c84596&ref=api&scene=19

- appid:应用ID

其余参数根据文档要求来进行获取
3.表单设计
3.1支付宝订单预创建并支付


其中【生成支付链接】与【确认支付状态】为代码块
3.1.1生成支付链接
3.1.1.1 代码注释
具体调用接口文档:
https://opendocs.alipay.com/open/f540afd8_alipay.trade.precreate?pathHash=d3c84596&ref=api&scene=19
注意:所生成的二维码有效时间为2小时

field_id获取方式https://exiao.yuque.com/rlf3k1/oanb79/ml0u7lgb3wa0vhiz?singleDoc# 《如何在代码块中分辨表格的不同列》


const axios = require('axios');
const crypto = require('crypto');
const { format } = require('date-fns');
const currentDate = new Date();
const formattedDate = format(currentDate, 'yyyy-MM-dd HH:mm:ss');
// 原始数据
const data = {
"timestamp":formattedDate,
"method": "alipay.trade.precreate",
"app_id": "2021003155650***",
"sign_type": "RSA2",
"version": "1.0",
"charset": "UTF-8"
};
const table = qf_field.{商品列表信息$$17B54DD0C$$};
const goodsDetail = table.map(item => {
const newItem = {
"quantity": item.field_169208787,
"goods_name": item.field_169208786,
"goods_id": item.field_169208785,
"price": item.field_169208788
};
return newItem;
});
//将新的 goods_detail 赋值给 data 中的 biz_content
data.biz_content =`{"out_trade_no": qf_field.{商户订单号$$17B54DD0A$$},"total_amount":qf_field.{订单总金额(单位为元)$$17B54DD0B$$},"subject":qf_field.{订单标题$$17B44C092$$},"goods_detail":${JSON.stringify(goodsDetail)}}`;
// 第一步:剔除sign字段
const { sign, ...dataWithoutSign } = data;
// 第二步:剔除值为空的参数
const filteredData = Object.fromEntries(Object.entries(dataWithoutSign).filter(([key, value]) => value !== ''));
// 第三步:按键的ASCII码值递增排序
const sortedParams = Object.keys(filteredData).sort();
// 第四步:将排序后的参数与其对应的值按照"参数=参数值"的格式组合起来
const concatenatedParams = sortedParams.map(key => `${key}=${filteredData[key]}`).join('&');
// 第五步:生成待签名字符串
const signString = concatenatedParams;
// 使用私钥对待签名字符串进行加密
const privateKey = `-----BEGIN PRIVATE KEY-----
MI****DANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCSDlNKcCP4F68iQFV4ytD5yQ0BI4med+ol2rKOKG3Zy8QKJlmUqMSaOM6zBIGknf8BsWwFuj48MC7KPuRusENpk5A9FJ01qr+yQo1JuAvm+VMTqXPHfDAYhl0HW6vYuwJ/i35Utca+r3q9nn6QmLp9mtigFLj3kwWewz5mEkPacx5p4XhXtUcWCpKJ+Fluu8Y3x0/SoodoIu+7w/gjFpFi4d/eXBsAb/7uS2ko8Q3i02RilR7SSqBHJ9WkHTDlDia2/JHmwBeqgLW60ipLG9cUpLrE2DIVPUw5Sf94FQKfJOju7HWDlDM/WvhlLhB8cRhsaV9BOlafdaoGPYMKnCRDAgMBAAECggEAKRa4nddgdxoKngMlSH8ePTcvXmOmApvPlmipFM8Q4FWvx/8z8ltsO8rBc6FP64S7SbmlHxNfEMWpVCJPV0hlHp1x1Y0oEQIBPd/1KYkKaCc6FOz18mfgi/W41CoY9TbfJAyVNLWSvPBXAmNFTd55kH5wdNB/nL6StTBOLJ700c5h5vjhcY0rZrEhmD4QChlmghHXSeFTyAHaLy1hUKVhIACWQNnSSwlg3WOjS4ddonwdXRi3L203FxlmyJBM1Gb3fv7KFZPnNjLfU8szuvL8SzJSLnRqfnafiA5x7ulxByst/KqoGArYWV37zOAzHj9YMckYGG6S00C8LLPwGrx0yQKBgQD/4AD1e2r1uzvbda70lLO2y0CsBXye7WYTRbYVX3u5Z8D++I3b2beebSPflS9wWWsw2urYj8AKSzGiUuVh8/Gy3hcWZ2GyPdNlywe8UkmgN4BjVcj5THoW5VPi+o1FbfPitKLsL9ccXYKTBnwNTuVMyblEGzWZx3uSoBNUqHImTwKBgQCSIJbRKqZAeOq7OcgCKvnDlztSbK35H4DxuAdMI04sV3fvRs5bE4H9hUySy2mfgrCrewdQkxjmtTzrRJFHVHnU1doDH0/HMDE2ry0I0RX79esaEJAartZerqxW+8EyTgAQL3nG1BfyvH1c38kMRDbMaUhmVEK0EheefsgSU35ZzQKBgQCa8gTiopgEshrvLHaDuUCSosZI5RGwE8ZKSV6X1rhPb9rZC56r0U117FVa4TZW7G8SqJ6qAXKjSSGHUHeDN3vXetG0SWpJy1KmQ6otig73rGRcwufuvzb3gmun+V1u+8RCNmyqZdX3YVDew4B/dpU4SLed3HQ66SeVhMXv8Akf1QKBgEPuBm5iBzs9etFigQoQ9F7qdNdSUmXXMVgtFqdcWkDewJBpOBC6ttkmGHy9NvLCDGMLJFFesFq/sfwkueyQ5rn8WAbPjYSpcJddQ/AvUqr4nTxWqsbctCb7yH3/Nsat3/WmPFQj0KY03YpJNesP4vGPl+qKDSAssPIrOdLbIYeZAoGADyKnem0BQK2dTRETTcH2AlYw3E4gVZipqmge2FziMM+QKwzKUa2w0m7ReamForpwoVD/rjPnhP8kf/wtM2R8BnQD25tEN9uplZfJguHEvhDrt9xKkshntFQz0Qcwk7CiHvQH2+zOJLykcu0HU2K9oEoxTkZzsoHLAbzI7CLKF4k=
-----END PRIVATE KEY-----`;
const signer = crypto.createSign('RSA-SHA256');
signer.update(signString, 'utf8');
const signature = signer.sign(privateKey);
const sig=signature.toString('base64');
const encodedSig = encodeURIComponent(sig);
let config = {
method: 'get',
maxBodyLength: Infinity,
url: `https://openapi.alipay.com/gateway.do?timestamp=${formattedDate}&method=${data.method}&app_id=${data.app_id}&sign_type=${data.sign_type}&sign=${encodedSig}&version=${data.version}&charset=${data.charset}&biz_content=${data.biz_content}`
};
axios(config).then(function (res) {
qf_output={'data':res.data}
});
3.1.1.2代码测试

3.1.1.3解析配置

######1.1.4.字段接受配置

3.1.2生成支付密码
该字段为Q_Linker,调用接口将支付链接转为支付二维码
具体接口文档:
https://www.mxnzp.com/doc/detail?id=2
- 需要点击申请appid,去获取对应的app_id和app_srcret

3.1.2.1
Q-Linker配置

- URL:https://www.mxnzp.com/api/qrcode/create/single
- QueryParam:

- Method:GET
- Json path:

- 字段接收配置

3.1.3 确认支付状态
3.1.3.1代码注释
具体调用接口文档: https://opendocs.alipay.com/open/02ekfh?pathHash=925e7dfc&ref=api&scene=23


const axios = require('axios');
const crypto = require('crypto');
const { format } = require('date-fns');
const currentDate = new Date();
const formattedDate = format(currentDate, 'yyyy-MM-dd HH:mm:ss');
// 原始数据
const data = {
"timestamp":formattedDate,
"method": "alipay.trade.query",
"app_id": "2021003155650***",
"sign_type": "RSA2",
"version": "1.0",
"charset": "UTF-8"
};
data.biz_content =`{"out_trade_no": qf_field.{商户订单号$$17B54DD0A$$}}`;
// 第一步:剔除sign字段
const { sign, ...dataWithoutSign } = data;
// 第二步:剔除值为空的参数
const filteredData = Object.fromEntries(Object.entries(dataWithoutSign).filter(([key, value]) => value !== ''));
// 第三步:按键的ASCII码值递增排序
const sortedParams = Object.keys(filteredData).sort();
// 第四步:将排序后的参数与其对应的值按照"参数=参数值"的格式组合起来
const concatenatedParams = sortedParams.map(key => `${key}=${filteredData[key]}`).join('&');
// 第五步:生成待签名字符串
const signString = concatenatedParams;
// 使用私钥对待签名字符串进行加密
const privateKey = `-----BEGIN PRIVATE KEY-----
MII****BgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCSDlNKcCP4F68iQFV4ytD5yQ0BI4med+ol2rKOKG3Zy8QKJlmUqMSaOM6zBIGknf8BsWwFuj48MC7KPuRusENpk5A9FJ01qr+yQo1JuAvm+VMTqXPHfDAYhl0HW6vYuwJ/i35Utca+r3q9nn6QmLp9mtigFLj3kwWewz5mEkPacx5p4XhXtUcWCpKJ+Fluu8Y3x0/SoodoIu+7w/gjFpFi4d/eXBsAb/7uS2ko8Q3i02RilR7SSqBHJ9WkHTDlDia2/JHmwBeqgLW60ipLG9cUpLrE2DIVPUw5Sf94FQKfJOju7HWDlDM/WvhlLhB8cRhsaV9BOlafdaoGPYMKnCRDAgMBAAECggEAKRa4nddgdxoKngMlSH8ePTcvXmOmApvPlmipFM8Q4FWvx/8z8ltsO8rBc6FP64S7SbmlHxNfEMWpVCJPV0hlHp1x1Y0oEQIBPd/1KYkKaCc6FOz18mfgi/W41CoY9TbfJAyVNLWSvPBXAmNFTd55kH5wdNB/nL6StTBOLJ700c5h5vjhcY0rZrEhmD4QChlmghHXSeFTyAHaLy1hUKVhIACWQNnSSwlg3WOjS4ddonwdXRi3L203FxlmyJBM1Gb3fv7KFZPnNjLfU8szuvL8SzJSLnRqfnafiA5x7ulxByst/KqoGArYWV37zOAzHj9YMckYGG6S00C8LLPwGrx0yQKBgQD/4AD1e2r1uzvbda70lLO2y0CsBXye7WYTRbYVX3u5Z8D++I3b2beebSPflS9wWWsw2urYj8AKSzGiUuVh8/Gy3hcWZ2GyPdNlywe8UkmgN4BjVcj5THoW5VPi+o1FbfPitKLsL9ccXYKTBnwNTuVMyblEGzWZx3uSoBNUqHImTwKBgQCSIJbRKqZAeOq7OcgCKvnDlztSbK35H4DxuAdMI04sV3fvRs5bE4H9hUySy2mfgrCrewdQkxjmtTzrRJFHVHnU1doDH0/HMDE2ry0I0RX79esaEJAartZerqxW+8EyTgAQL3nG1BfyvH1c38kMRDbMaUhmVEK0EheefsgSU35ZzQKBgQCa8gTiopgEshrvLHaDuUCSosZI5RGwE8ZKSV6X1rhPb9rZC56r0U117FVa4TZW7G8SqJ6qAXKjSSGHUHeDN3vXetG0SWpJy1KmQ6otig73rGRcwufuvzb3gmun+V1u+8RCNmyqZdX3YVDew4B/dpU4SLed3HQ66SeVhMXv8Akf1QKBgEPuBm5iBzs9etFigQoQ9F7qdNdSUmXXMVgtFqdcWkDewJBpOBC6ttkmGHy9NvLCDGMLJFFesFq/sfwkueyQ5rn8WAbPjYSpcJddQ/AvUqr4nTxWqsbctCb7yH3/Nsat3/WmPFQj0KY03YpJNesP4vGPl+qKDSAssPIrOdLbIYeZAoGADyKnem0BQK2dTRETTcH2AlYw3E4gVZipqmge2FziMM+QKwzKUa2w0m7ReamForpwoVD/rjPnhP8kf/wtM2R8BnQD25tEN9uplZfJguHEvhDrt9xKkshntFQz0Qcwk7CiHvQH2+zOJLykcu0HU2K9oEoxTkZzsoHLAbzI7CLKF4k=
-----END PRIVATE KEY-----`;
const signer = crypto.createSign('RSA-SHA256');
signer.update(signString, 'utf8');
const signature = signer.sign(privateKey);
const sig=signature.toString('base64');
const encodedSig = encodeURIComponent(sig);
let config = {
method: 'get',
maxBodyLength: Infinity,
url: `https://openapi.alipay.com/gateway.do?timestamp=${formattedDate}&method=${data.method}&app_id=${data.app_id}&sign_type=${data.sign_type}&sign=${encodedSig}&version=${data.version}&charset=${data.charset}&biz_content=${data.biz_content}`
};
axios(config).then(function (res) {
qf_output={'data':res.data}
});
3.1.3.2代码测试

3.1.3.3解析配置

3.1.3.4字段接受配置



3.1.4 流程配置


3.1.4.1申请人节点配置

3.1.4.2确认支付信息并扫码支付




3.1.4.3告知用户

3.1.4.4webhook节点
具体接口文档:
https://help.qingflow.com/help-docs?type=qingCode&docId=fc8e64656428e08a06fdf030002e2a74&parentId=
- accessToken:轻商城——拓展插件——openAPI

- 节点ID获取方式
可以调用接口来进行获取:
https://help.qingflow.com/help-docs?type=qingCode&docId=0122a5876428e120070b62b8001478f4&parentId=

3.2支付宝申请订单退款

3.2.1商户订单号

3.2.2订单总金额

3.2.3 退款
3.2.3.1代码注释
具体调用接口文档:
https://opendocs.alipay.com/open/02ekfk?pathHash=b45b14f7&ref=api&scene=common
注意:交易超过约定时间(签约时设置的可退款时间)的订单无法进行退款。
app_id:需要替换成具体调用的应用ID


const axios = require('axios');
const crypto = require('crypto');
const { format } = require('date-fns');
const currentDate = new Date();
const formattedDate = format(currentDate, 'yyyy-MM-dd HH:mm:ss');
// 原始数据
const data = {
"timestamp":formattedDate,
"method": "alipay.trade.refund",
"app_id": "2021003155650***",
"sign_type": "RSA2",
"version": "1.0",
"charset": "UTF-8"
};
data.biz_content =`{"out_trade_no":qf_field.{商户订单号$$17B598970$$},"refund_amount":qf_field.{退款金额$$17B598089$$},"refund_reason":qf_field.{退款原因说明$$17B59808A$$}}`;
// 第一步:剔除sign字段
const { sign, ...dataWithoutSign } = data;
// 第二步:剔除值为空的参数
const filteredData = Object.fromEntries(Object.entries(dataWithoutSign).filter(([key, value]) => value !== ''));
// 第三步:按键的ASCII码值递增排序
const sortedParams = Object.keys(filteredData).sort();
// 第四步:将排序后的参数与其对应的值按照"参数=参数值"的格式组合起来
const concatenatedParams = sortedParams.map(key => `${key}=${filteredData[key]}`).join('&');
// 第五步:生成待签名字符串
const signString = concatenatedParams;
// 使用私钥对待签名字符串进行加密
const privateKey = `-----BEGIN PRIVATE KEY-----
MII*****NBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCSDlNKcCP4F68iQFV4ytD5yQ0BI4med+ol2rKOKG3Zy8QKJlmUqMSaOM6zBIGknf8BsWwFuj48MC7KPuRusENpk5A9FJ01qr+yQo1JuAvm+VMTqXPHfDAYhl0HW6vYuwJ/i35Utca+r3q9nn6QmLp9mtigFLj3kwWewz5mEkPacx5p4XhXtUcWCpKJ+Fluu8Y3x0/SoodoIu+7w/gjFpFi4d/eXBsAb/7uS2ko8Q3i02RilR7SSqBHJ9WkHTDlDia2/JHmwBeqgLW60ipLG9cUpLrE2DIVPUw5Sf94FQKfJOju7HWDlDM/WvhlLhB8cRhsaV9BOlafdaoGPYMKnCRDAgMBAAECggEAKRa4nddgdxoKngMlSH8ePTcvXmOmApvPlmipFM8Q4FWvx/8z8ltsO8rBc6FP64S7SbmlHxNfEMWpVCJPV0hlHp1x1Y0oEQIBPd/1KYkKaCc6FOz18mfgi/W41CoY9TbfJAyVNLWSvPBXAmNFTd55kH5wdNB/nL6StTBOLJ700c5h5vjhcY0rZrEhmD4QChlmghHXSeFTyAHaLy1hUKVhIACWQNnSSwlg3WOjS4ddonwdXRi3L203FxlmyJBM1Gb3fv7KFZPnNjLfU8szuvL8SzJSLnRqfnafiA5x7ulxByst/KqoGArYWV37zOAzHj9YMckYGG6S00C8LLPwGrx0yQKBgQD/4AD1e2r1uzvbda70lLO2y0CsBXye7WYTRbYVX3u5Z8D++I3b2beebSPflS9wWWsw2urYj8AKSzGiUuVh8/Gy3hcWZ2GyPdNlywe8UkmgN4BjVcj5THoW5VPi+o1FbfPitKLsL9ccXYKTBnwNTuVMyblEGzWZx3uSoBNUqHImTwKBgQCSIJbRKqZAeOq7OcgCKvnDlztSbK35H4DxuAdMI04sV3fvRs5bE4H9hUySy2mfgrCrewdQkxjmtTzrRJFHVHnU1doDH0/HMDE2ry0I0RX79esaEJAartZerqxW+8EyTgAQL3nG1BfyvH1c38kMRDbMaUhmVEK0EheefsgSU35ZzQKBgQCa8gTiopgEshrvLHaDuUCSosZI5RGwE8ZKSV6X1rhPb9rZC56r0U117FVa4TZW7G8SqJ6qAXKjSSGHUHeDN3vXetG0SWpJy1KmQ6otig73rGRcwufuvzb3gmun+V1u+8RCNmyqZdX3YVDew4B/dpU4SLed3HQ66SeVhMXv8Akf1QKBgEPuBm5iBzs9etFigQoQ9F7qdNdSUmXXMVgtFqdcWkDewJBpOBC6ttkmGHy9NvLCDGMLJFFesFq/sfwkueyQ5rn8WAbPjYSpcJddQ/AvUqr4nTxWqsbctCb7yH3/Nsat3/WmPFQj0KY03YpJNesP4vGPl+qKDSAssPIrOdLbIYeZAoGADyKnem0BQK2dTRETTcH2AlYw3E4gVZipqmge2FziMM+QKwzKUa2w0m7ReamForpwoVD/rjPnhP8kf/wtM2R8BnQD25tEN9uplZfJguHEvhDrt9xKkshntFQz0Qcwk7CiHvQH2+zOJLykcu0HU2K9oEoxTkZzsoHLAbzI7CLKF4k=
-----END PRIVATE KEY-----`;
const signer = crypto.createSign('RSA-SHA256');
signer.update(signString, 'utf8');
const signature = signer.sign(privateKey);
const sig=signature.toString('base64');
const encodedSig = encodeURIComponent(sig);
let config = {
method: 'get',
maxBodyLength: Infinity,
url: `https://openapi.alipay.com/gateway.do?timestamp=${formattedDate}&method=${data.method}&app_id=${data.app_id}&sign_type=${data.sign_type}&sign=${encodedSig}&version=${data.version}&charset=${data.charset}&biz_content=${data.biz_content}`
};
axios(config).then(function (res) {
qf_output={'data':res.data}
});
######2.3.2.解析配置

3.2.3.3字段接受配置
