koa实现对接支付宝沙箱支付

Posted 小小白学计算机

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了koa实现对接支付宝沙箱支付相关的知识,希望对你有一定的参考价值。

一、沙箱环境

支付宝有一个供开发者测试使用的沙箱环境,会提供一个沙箱版的支付宝app、一个商家账户、一个买家账户。有了这个,可以让我们跳过商家入驻、企业资质审核等过程,开箱即用,降低了学习成本。

1、密钥工具下载

密钥工具


支付宝开放平台沙箱应用

相关链接:
电脑网站支付
api文档

二、代码实现




注意:
如果出现下图的报错:

解决方案:
将应用私钥通过 支付宝开放平台密钥工具 - 格式转换菜单 进行转换

把生成的应用私钥放入privateKey中

  1. 安装sdk
npm install alipay-sdk
  1. alipaySdk.js文件:
const AlipaySdk = require("alipay-sdk").default; // 引入 SDK
const alipaySdk = new AlipaySdk(
  appId: "11114541", // 开放平台上创建应用时生成的 appId
  signType: "RSA2", // 签名算法,默认 RSA2
  gateway: "https://openapi.alipaydev.com/gateway.do", // 支付宝网关地址 ,沙箱环境下使用时需要修改 正式线上的时候换成 https://openapi.alipay.com/gateway.do
  alipayPublicKey:
    "MIDAQAB", // 支付宝公钥,需要对结果验签时候必填
  privateKey:
    "MIIEoUBGzxQ", // 应用私钥字符串
);
module.exports = alipaySdk;

//正式环境只要把上述换成正式的就可以了


  1. app.js文件:
//1.引入koa
const Koa = require("koa");
const axios = require("axios");
const cors = require("koa2-cors");
const static = require("koa-static");
const bodyparser = require("koa-bodyparser"); // 引入koa-bodyparser
const alipaySdk = require("./alipaySdk");

let port = 9000;
let host = "localhost";
// let host = "192.168.43.213";
const app = new Koa();

app.use(
  cors(
    // 任何地址都可以访问
    origin: "*",
    // 指定地址才可以访问
    // origin: 'http://localhost:8080',
    maxAge: 2592000,
    // 必要配置
    credentials: true,
  )
);
app.use(static("static"));


const Router = require("koa-router");
const router = new Router(); //配置无路由前缀的路由
const payMentRouter = new Router(
  //配置路由前缀为users的路由
  prefix: "/payment",
);

// 获取post提交的数据,解析请求体
app.use(bodyparser());

payMentRouter.get("/payNotify", async (ctx) => 
  console.log("payNotify====");
  ctx.body = 
    code: 0,
    msg: "成功通知",
  ;
);

// 生成支付链接给用户进行支付
payMentRouter.post("/pay", async (ctx) => 
  // console.log(ctx.request.body, "ctx.request.body");
  const  orderId  = ctx.request.body;
  const AlipayFormData = require("alipay-sdk/lib/form").default;
  const formData = new AlipayFormData();
  formData.setMethod("get");
  formData.addField("bizContent", 
    outTradeNo: orderId, // 商户订单号,64个字符以内、可包含字母、数字、下划线,且不能重复
    productCode: "FAST_INSTANT_TRADE_PAY", // 销售产品码,与支付宝签约的产品码名称,仅支持FAST_INSTANT_TRADE_PAY
    totalAmount: "0.01", // 订单总金额,单位为元,精确到小数点后两位
    subject: "商品订单标题", // 订单标题
    body: "商品详情", // 订单描述
  );
  // 表示异步通知回调,必须是一个外网可以访问的网址,因为它是由支付宝服务器发起的,只能是线上访问
  // formData.addField("notifyUrl", "http://localhost:9000/payment/payNotify");
  formData.addField("notifyUrl", "https://www.baidu.com");
  // 付款成功的跳转页面
  // 可以是本地地址,因为它是本地客户端请求URL,会被本地host拦截至本地服务器中
  formData.addField("returnUrl", "http://localhost:9000/payment/payNotify");
  // const result = await alipaySdk.pageExec(
  const result = await alipaySdk.exec(
    // result 为可以跳转到支付链接的 url
    "alipay.trade.page.pay", // 统一收单下单并支付页面接口
    , // api 请求的参数(包含“公共请求参数”和“业务参数”)
    
      formData: formData,
    
  );

  ctx.body = 
    code: 0,
    msg: "成功",
    result: result,
  ;
);

// 查询订单的支付状态
payMentRouter.post("/checkPayStatus", async (ctx) => 
  const  orderId  = ctx.request.body;
  let outTradeNo = orderId; // 商家订单号
  const AlipayFormData = require("alipay-sdk/lib/form").default;
  const formData = new AlipayFormData();
  formData.setMethod("get");
  formData.addField("bizContent", 
    outTradeNo,
  );
  // 通过该接口主动查询订单状态
  // 查询订单状态:https://opendocs.alipay.com/apis/api_1/alipay.trade.query?scene=23
  // 这里的result还是一个网址,我们需要axios请求这个网址,才能查看订单状态:
  let result = await alipaySdk.exec(
    "alipay.trade.query",
    ,
    
      formData: formData,
    
  );
  // console.log("result", result);

  try 
    const data = await axios(
      method: "GET",
      url: result,
    );
    let r = data.data.alipay_trade_query_response;
    if (r.code === "10000") 
      // 接口调用成功
      switch (r.trade_status) 
        case "WAIT_BUYER_PAY":
          ctx.body = 
            success: true,
            message: "success",
            code: 200,
            timestamp: new Date().getTime(),
            result: 
              status: 0,
              massage: "交易创建,等待买家付款",
            ,
          ;
          break;
        case "TRADE_CLOSED":
          ctx.body = 
            success: true,
            message: "success",
            code: 200,
            timestamp: new Date().getTime(),
            result: 
              status: 1,
              massage: "未付款交易超时关闭,或支付完成后全额退款",
            ,
          ;
          break;
        case "TRADE_SUCCESS":
          ctx.body = 
            success: true,
            message: "success",
            code: 200,
            timestamp: new Date().getTime(),
            result: 
              status: 2,
              massage: "交易支付成功",
            ,
          ;
          break;
        case "TRADE_FINISHED":
          ctx.body = 
            success: true,
            message: "success",
            code: 200,
            timestamp: new Date().getTime(),
            result: 
              status: 3,
              massage: "交易结束,不可退款",
            ,
          ;
          break;
      
     else if (r.code === "40004") 
      ctx.body = 
        code: -1,
        message: "交易不存在",
      ;
    
   catch (err) 
    ctx.body = 
      msg: "查询失败",
      err,
    ;
  

  // ctx.body = 
  //   code: 0,
  //   result: result,
  // ;
);

app.use(router.routes());
app.use(payMentRouter.routes());
app.use(payMentRouter.allowedMethods());


app.listen(port, () => 
  console.log(`http://$host:$port`);
);

三、启动服务并测试

  1. 命令行执行:node ./app.js 启动服务

  2. 使用postman测试接口是否正常:





以上是关于koa实现对接支付宝沙箱支付的主要内容,如果未能解决你的问题,请参考以下文章

对接支付宝支付,沙箱环境提示:支付存在钓鱼风险!防钓鱼网站的方法

对接支付宝遇到的坑

golang集成支付宝支付(沙箱环境)

前端对接后台支付(支付宝)

吐槽支付宝小程序支付-php

开源web框架django知识总结(二十二)