node接入支付宝支付API
- CLIENT端
- 支付 查询订单 退款 退款查询四个功能
- SERVER端
- 公钥私钥可以到支付宝开发平台申请
CLIENT端
支付 查询订单 退款 退款查询四个功能
<template><div class="home"><button @click="goPay">点击跳转支付</button><button @click="queryOrder">点击查询订单状态</button><button @click="refund">点击退款</button><button @click="refundQuery">查询退款状态</button></div>
</template><script lang="ts">
import { defineComponent } from "vue";
import axios from "axios";
export default defineComponent({name: "",setup() {const orderId = "fffehrwiyrewy43434228758123";const outRequestNo = "fff21332";// fffehrwiyrewy43434228758473const goPay = () => {let data = {orderId,};let instance = axios.create({headers: { "content-type": "application/x-www-form-urlencoded" },});// 代理到 http://localhost:3000/api/pcpayinstance.post(`http://localhost:8080/api/pcpay`, data).then((res) => {window.open(res.data.result);});};const queryOrder = async () => {let data = {};let instance = axios.create({headers: { "content-type": "application/x-www-form-urlencoded" },});// 代理到 http://localhost:3000/api/pcpaylet res = await instance.get(`http://localhost:8080/api/order/query`, {params: {orderId,},});if (res.data.code == 200) {console.log(res);let orderRes = await instance.get(res.data.result);console.log(orderRes);}};const refund = async () => {let data = {};let instance = axios.create({headers: { "content-type": "application/x-www-form-urlencoded" },});// 代理到 http://localhost:3000/api/pcpaylet res = await instance.post(`http://localhost:8080/api/order/refund`, {orderId,refundAmount: 0.01,outRequestNo,});if (res.data.code == 200) {console.log(res);let orderRes = await instance.get(res.data.result);console.log(orderRes);}};const refundQuery = async () => {let data = {};let instance = axios.create({headers: { "content-type": "application/x-www-form-urlencoded" },});// 代理到 http://localhost:3000/api/pcpaylet res = await instance.get(`http://localhost:8080/api/order/refund/query`,{params: {orderId,outRequestNo,},});if (res.data.code == 200) {console.log(res);let orderRes = await instance.get(res.data.result);console.log(orderRes);}};return {goPay,queryOrder,refund,refundQuery,};},
});
</script>
<style scoped lang="scss"></style>
SERVER端
公钥私钥可以到支付宝开发平台申请
支付宝开发平台
文档api接口
npm包下载地址
app.js
const express = require("express");
const router = express();
const alipaySdk = require("./util/alipayUtil");
const AlipayFormData = require("alipay-sdk/lib/form").default; // alipay.trade.page.pay 返回的内容为 Form 表单
const cors = require("cors");
router.use(express.json());
// 使用cors解决跨域问题
router.use(cors());
router.use(express.urlencoded({ extended: true }));router.post("/api/pcpay", (req, res) => {let orderId = req.body.orderId;// * 添加购物车支付支付宝 */// 调用 setMethod 并传入 get,会返回可以跳转到支付页面的 urlconst formData = new AlipayFormData();formData.setMethod("get");// 通过 addField 增加参数// 在用户支付完成之后,支付宝服务器会根据传入的 notify_url,以 POST 请求的形式将支付结果作为参数通知到商户系统。// formData.addField("notifyUrl", "http://localhost:5173/"); // 支付成功回调地址,必须为可以直接访问的地址,不能带参数formData.addField("bizContent", {outTradeNo: orderId, // 商户订单号,64个字符以内、可包含字母、数字、下划线,且不能重复productCode: "FAST_INSTANT_TRADE_PAY", // 销售产品码,与支付宝签约的产品码名称,仅支持FAST_INSTANT_TRADE_PAYtotalAmount: "0.01", // 订单总金额,单位为元,精确到小数点后两位subject: "商品", // 订单标题body: "商品详情", // 订单描述});formData.addField("returnUrl", "http://localhost:5173/"); //加在这里才有效果,不是加在bizContent 里面// 如果需要支付后跳转到商户界面,可以增加属性"returnUrl"const result = alipaySdk.exec(// result 为可以跳转到支付链接的 url"alipay.trade.page.pay", // 统一收单下单并支付页面接口{}, // api 请求的参数(包含“公共请求参数”和“业务参数”){ formData: formData });result.then((resp) => {res.send({success: true,message: "success",code: 200,timestamp: new Date().getTime(),result: resp,});});
});router.get("/api/order/query", (req, res) => {let orderId = req.query.orderId;console.log(orderId);// * 添加购物车支付支付宝 */// 调用 setMethod 并传入 get,会返回可以跳转到支付页面的 urlconst formData = new AlipayFormData();formData.setMethod("get");// 通过 addField 增加参数// 在用户支付完成之后,支付宝服务器会根据传入的 notify_url,以 POST 请求的形式将支付结果作为参数通知到商户系统。// formData.addField("notifyUrl", "http://localhost:5173/"); // 支付成功回调地址,必须为可以直接访问的地址,不能带参数formData.addField("bizContent", {outTradeNo: orderId, // 商户订单号,64个字符以内、可包含字母、数字、下划线,且不能重复});// 如果需要支付后跳转到商户界面,可以增加属性"returnUrl"const result = alipaySdk.exec(// result 为可以跳转到支付链接的 url"alipay.trade.query", // 统一收单下单并支付页面接口{}, // api 请求的参数(包含“公共请求参数”和“业务参数”){ formData: formData });result.then((resp) => {res.send({success: true,message: "success",code: 200,timestamp: new Date().getTime(),result: resp,});});
});
router.post("/api/order/refund", (req, res) => {let orderId = req.body.orderId;let refundAmount = req.body.refundAmount;let outRequestNo = req.body.outRequestNo;// * 添加购物车支付支付宝 */// 调用 setMethod 并传入 get,会返回可以跳转到支付页面的 urlconst formData = new AlipayFormData();formData.setMethod("get");// 通过 addField 增加参数// 在用户支付完成之后,支付宝服务器会根据传入的 notify_url,以 POST 请求的形式将支付结果作为参数通知到商户系统。// formData.addField("notifyUrl", "http://localhost:5173/"); // 支付成功回调地址,必须为可以直接访问的地址,不能带参数formData.addField("bizContent", {outTradeNo: orderId, // 商户订单号,64个字符以内、可包含字母、数字、下划线,且不能重复refundAmount: refundAmount, // 商户订单号,64个字符以内、可包含字母、数字、下划线,且不能重复outRequestNo: outRequestNo, // 商户订单号,64个字符以内、可包含字母、数字、下划线,且不能重复});// 如果需要支付后跳转到商户界面,可以增加属性"returnUrl"const result = alipaySdk.exec(// result 为可以跳转到支付链接的 url"alipay.trade.refund", // 统一收单下单并支付页面接口{}, // api 请求的参数(包含“公共请求参数”和“业务参数”){ formData: formData });result.then((resp) => {res.send({success: true,message: "success",code: 200,timestamp: new Date().getTime(),result: resp,});});
});
router.get("/api/order/refund/query", (req, res) => {let orderId = req.query.orderId;let outRequestNo = req.query.outRequestNo;console.log(outRequestNo);// * 添加购物车支付支付宝 */// 调用 setMethod 并传入 get,会返回可以跳转到支付页面的 urlconst formData = new AlipayFormData();formData.setMethod("get");// 通过 addField 增加参数// 在用户支付完成之后,支付宝服务器会根据传入的 notify_url,以 POST 请求的形式将支付结果作为参数通知到商户系统。// formData.addField("notifyUrl", "http://localhost:5173/"); // 支付成功回调地址,必须为可以直接访问的地址,不能带参数formData.addField("bizContent", {outTradeNo: orderId, // 商户订单号,64个字符以内、可包含字母、数字、下划线,且不能重复outRequestNo: outRequestNo,});// 如果需要支付后跳转到商户界面,可以增加属性"returnUrl"const result = alipaySdk.exec(// result 为可以跳转到支付链接的 url"alipay.trade.fastpay.refund.query", // 统一收单下单并支付页面接口{}, // api 请求的参数(包含“公共请求参数”和“业务参数”){ formData: formData });result.then((resp) => {res.send({success: true,message: "success",code: 200,timestamp: new Date().getTime(),result: resp,});});
});
router.listen(8080, () => {console.log("服务器启动成功");
});
alipayUtil.js
const AlipaySdk = require("alipay-sdk").default; // 引入 SDK
const alipaySdk = new AlipaySdk({appId: "9021000122683808", // 开放平台上创建应用时生成的 appIdsignType: "RSA2", // 签名算法,默认 RSA2gateway: "https://openapi-sandbox.dl.alipaydev.com/gateway.do", // 支付宝网关地址 ,沙箱环境下使用时需要修改alipayPublicKey:"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAprDYjifvWQDRQjUTQ8acCKBv2qBoiwfoTNI9Huhq2ry1EA8MqWUvLGEkOj4ik6pH079rzLfAFZoXFeLboPqBXK+zxFganJbog+R2CrLtD5Y6uuqGpRc5UBsFbYl26gPZGKA3an0jkGfqKteiNU8u90HflO+OJTBHoRMuu5iy0kfzdx73XecA7zkp5LSx0b1wVgj5s6Q4CIiSpiWx46kneufR0CW5nKg6WTzPsqsYNjrij6nwyWHuhBQ+FhBjPN5kE1Y0gdP5qtSrsG+n3uT6vhUgz0CPqXsTx5aHq8gikuKFyYEyeT2SZL/s0EMMCdkIZwJLwvqKcSKUTfzhAO5PFwIDAQAB", // 支付宝公钥,需要对结果验签时候必填privateKey:"MIIEpAIBAAKCAQEA10GY9s3M34xvg3CoxOz41NwxtiaFqYwI8iIRfsepud+oXuZG9Fa/+TK1yvy4CNtz+s/E5eS+YDCqsHWj4RGpUizlmZYXG5a3eoBTYjbfyl8ZLQPzXeOfXLpRBh/oF0aU1EOif12m4ZAfLWlFKgH16B/NMfXydKzQvcFniS7MzKBaQNe96qSEGo7PShcoyGCfeghlUPjJ0Vox5E64FJu0Qagjz9eTT6BNQj5jzbGsplG/btrL7obauQsGn3+Hhm1DJsEwskkj3j1mgUhBomlaxHlXpW6rDhvKYDm7hp7mwlE+n4Y4S8GQbuCc6HihnezTsMc4TSxbslpGpDXYpDMWkwIDAQABAoIBAQCSr40BgrT+EcFcHMWljKb0xyjJK+8h3t+pwTWS45TxqUwff2US1Jr1wmzH6veucX3TiQpwbzSccA2hOkl28oYkDZxY0ULl9gsKW7B22VYfnjaVyn9pl9fdZMoaFlweoGaDT6PIj5VNWN0mIPqU6ckdaa53QVb701hcNxPLFC1TsyIJz5MPcK/o8i9go/jFeP1bMPHqk9/z2Wzai5z+XLkk1XO3iSjFiP8ZvfRKv0lgFFRrRMnqmZrC7MsO2m/doIYh2+svmu9pIjoVzb9dJtaxQmz5+w8EHZMQFescZ2R44mYRdTCu1+iqo9IMtjPUIyct5qVpMp/3CQS0KGZMJPdBAoGBAPWamHTn4ITwVAvblYa41lSpgbSiz1k/0k1D0oi4HZGPDguuMClmL+c3zgm7xfyVsmO6YeicxpfaVoy4cKu2Y+LygfJrS+ZCJ8f3phtKJyWzR6pyJBSzsHvqB4QZcjfaXQPzD9FyWo4pZ9l2wWCjcshjUl/t/GS+PbTkkyIto9MpAoGBAOBeJltKa2dSNJIeWd3OC6PqMXUdMh1/wMxeT1bDuzKfzvEll7qJeM9QaVjODcg8SsVi1rqOMa6h2sGC36H2gkfc7CSxBdJZMRerl4btWhmZEE1mygrza20EKmcDaZ95MQT5qwLVaMzVKehJqGSSzG5lEAf+7pxl8orXG71ibq9bAoGBAMk6oS8nzQ0e273ba+e2CeXT/DHEM58sa2Ji71yVfaSFUTzAuzUwRI9taaMP9me9Pyv2ycGMsio4+jDR7X7DMZQAnffBca53BaERh0dUuj5pZY6Bdo5/q1nbpczWDH82qn9R5uP0jb1sr2m9ozNKuAD3X8a5dtIUDPrpTKP0QQYBAoGASkpiYO/vSDLL/WXXU74Z1JiC78hPA719VS4VDyGYJlcL6oUMDFPgkKSLfUAdCCQOjfUALJ1QjgZBrLls2vAIi0r3Vd7XkqK9wpyqe56zqq4n27khRSb8dwheEeXrX0Z9mKwil7maDdi3G5boDwUcc6E7AarDzz1iZd577OVeyOkCgYA4n/VwvOCBNXr6ZdrST9gQ1XTW8iTWlhQXI+w/zeH1AuGoOthG9d58743Sl90QD/x7kBlZIYXWZyToX5GtS4Td/kXEGP7AMmSNGemjxel9UbI/bmPmYYvlYMnBJ9pHsJAnaeQIXJ+EuzC09TvI02Z/INfows9JPlOIkdSj+ntITA==", // 应用私钥字符串
});
module.exports = alipaySdk;