node接入支付宝支付API

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";
    // fffehrwiyrewy43434228758473
    const goPay = () => {
      let data = {
        orderId,
      };
      let instance = axios.create({
        headers: { "content-type": "application/x-www-form-urlencoded" },
      });

      // 代理到  http://localhost:3000/api/pcpay
      instance.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/pcpay
      let 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/pcpay
      let 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/pcpay
      let 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,会返回可以跳转到支付页面的 url
  const 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_PAY
    totalAmount: "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,会返回可以跳转到支付页面的 url
  const 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,会返回可以跳转到支付页面的 url
  const 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,会返回可以跳转到支付页面的 url
  const 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", // 开放平台上创建应用时生成的 appId
  signType: "RSA2", // 签名算法,默认 RSA2
  gateway: "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;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值