NodeJS实现支付宝沙箱支付②③

文章目录

  • 前言
  • 版权声明
  • Alipay SDK 沙箱环境简介
  • Node环境要求
  • 沙箱环境配置
  • 下载所需模块
  • 准备前端静态页面以及Node服务器
  • 文件夹规范
  • AlipaySdk 配置准备
  • AlipaySdk 代码演示
  •    Alipay实例化 ~ alipay.sdk 文件
  •    AlipayForm ~ alipayForm文件
  •    AlipayFormStatus ~ alipayForm文件
  •    AlipayForm文件 ~ 完整代码
  • 使用沙箱
  • 效果演示
  • AlipaySdk API ~
  • 最后


                    ⡖⠒⠒⠒⠤⢄⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸   ⠀⠀⠀⡼⠀⠀⠀⠀ ⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢶⣲⡴⣗⣲⡦⢤⡏⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⠋⠉⠉⠓⠛⠿⢷⣶⣦⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠇⠀⠀⠀⠀⠀⠀⠘⡇⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⠀⠀⠀⢰⠇⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⡴⠊⠉⠳⡄⠀⢀⣀⣀⡀⠀⣸⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⢸⠃⠀⠰⠆⣿⡞⠉⠀⠀⠉⠲⡏⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠈⢧⡀⣀⡴⠛⡇⠀⠈⠃⠀⠀⡗⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣱⠃⡴⠙⠢⠤⣀⠤⡾⠁⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢀⡇⣇⡼⠁⠀⠀⠀⠀⢰⠃⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⣸⢠⣉⣀⡴⠙⠀⠀⠀⣼⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⡏⠀⠈⠁⠀⠀⠀⠀⢀⡇⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⢸⠃⠀⠀⠀⠀⠀⠀⠀⡼⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⣰⠃⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⣀⠤⠚⣶⡀⢠⠄⡰⠃⣠⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⢀⣠⠔⣋⣷⣠⡞⠀⠉⠙⠛⠋⢩⡀⠈⠳⣄⠀⠀⠀⠀⠀⠀⠀
⠀⡏⢴⠋⠁⠀⣸⠁⠀⠀⠀⠀⠀ ⠀⣹⢦⣶⡛⠳⣄⠀⠀⠀⠀⠀
⠀⠙⣌⠳⣄⠀⡇   不能   ⡏⠀⠀  ⠈⠳⡌⣦⠀⠀⠀⠀
⠀⠀⠈⢳⣈⣻⡇   白嫖 ⢰⣇⣀⡠⠴⢊⡡⠋⠀⠀⠀⠀
⠀⠀⠀⠀⠳⢿⡇⠀⠀⠀⠀⠀⠀⢸⣻⣶⡶⠊⠁⠀⠀
⠀⠀⠀⠀⠀⢠⠟⠙⠓⠒⠒⠒⠒⢾⡛⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⣠⠏⠀⣸⠏⠉⠉⠳⣄⠀⠙⢆⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⡰⠃⠀⡴⠃⠀⠀⠀⠀⠈⢦⡀⠈⠳⡄⠀⠀⠀⠀⠀⠀⠀
⠀⠀⣸⠳⣤⠎⠀⠀⠀⠀⠀⠀⠀⠀⠙⢄⡤⢯⡀⠀⠀⠀⠀⠀⠀
⠀⠐⡇⠸⡅⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⡆⢳⠀⠀⠀⠀⠀⠀
⠀⠀⠹⡄⠹⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣇⠸⡆⠀⠀⠀⠀⠀
⠀⠀⠀⠹⡄⢳⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⡀⣧⠀⠀⠀⠀⠀
⠀⠀⠀⠀⢹⡤⠳⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣷⠚⣆⠀⠀⠀⠀
⠀⠀⠀⡠⠊⠉⠉⢹⡀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡎⠉⠀⠙⢦⡀⠀
⠀⠀⠾⠤⠤⠶⠒⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠙⠒⠲⠤⠽   

前言

  1. Node.js是一个javascript运行环境。它让javascript可以开发后端程序,实现几乎其他后端语言实现的所有功能,可以与```PHP、Java、Python、.NET、Ruby等后端语言平起平坐。
  2. Nodejs是基于V8引擎,V8是Google发布的开源JavaScript引擎,本身就是用于Chrome浏览器的JS解释,但是Node之父 Ryan Dahl在这里插入图片描述把这V8搬到了服务器上,用于做服务器的软件。

版权声明

在这里插入图片描述

Copyright © [SYFStrive],未经许可,禁止转载 ~~~

Alipay SDK 沙箱环境简介

沙箱环境 : 是协助开发者进行功能测试,模拟了开放平台产品的主要功能,逻辑。可用于在产品上线前进行功能测试。

Node环境要求

Node.js 8 以上版本

沙箱环境配置

官方 : https://openhome.alipay.com/

配置步骤 :使用支付宝登录 进入我的控制台 下方的开发工具推荐 点击沙箱 沙箱应用 启动公钥模式 获取公钥和私钥 网关地址

下载所需模块

npm install koa

npm install koa-router

npm install alipay-sdk

npm install koa koa-router alipay-sdk

准备前端静态页面以及Node服务器

  • 静态页面
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js"></script>
    <title>支付宝沙箱支付</title>
</head>

<body>
    <button>支付宝</button>
</body>
<script>

    const but = document.querySelector('button')
    but.addEventListener('click', () => {
        axios({
            method: 'get',
            url: 'http://127.0.0.1:8000/payment'
        }).then(reason => {
            console.log(reason.data);
        })
    })
</script>

</html>
  • Node服务器
const koa = require("koa");
const app = new koa();//实例
const koaRouter = require('koa-router')
const router = new koaRouter()

router.get("/payment", (ctx, next) => {
    ctx.set('Access-Control-Allow-Origin', '*')
    ctx.set('Access-Control-Allow-Methods', "OPTIONS, GET, PUT, POST, DELETE")
    ctx.body = ({
        code: 200
    })
    next()
})

app.use(router.routes(), router.allowedMethods())
app.listen(8000, function () {
    console.log("HTTP服务已启动");
})

文件夹规范

NodeJS实现支付宝沙箱支付②③_第1张图片
NodeJS实现支付宝沙箱支付②③_第2张图片

AlipaySdk 配置准备

初始化 SDK 准备参数

  • 公钥证书模式(推荐): appId、应用私钥、应用公钥证书文件、支付宝公钥证书文件、支付宝证书文件
  • 公钥模式:appId、应用私钥、应用公钥、支付宝公钥

AlipaySdk 代码演示

   Alipay实例化 ~ alipay.sdk 文件

  • 封装配置方法
const AlipaySdk = require('alipay-sdk').default
const fs = require('fs')
// 普通公钥模式
const alipaySdk = new AlipaySdk({
    appId: '2021000122664484', //开放平台上创建应用时生成的 appId
    signType: 'RSA2',//签名算法,默认 RSA2
    gateway: 'https://openapi.alipaydev.com/gateway.do',//支付宝网关地址
    privateKey: fs.readFileSync('private-key.pem', 'ascii'),//应用私钥
    alipayPublicKey: fs.readFileSync('alipay-public-key.pem', 'ascii'),//支付宝公钥
});

// 证书模式
// const alipaySdk = new AlipaySdk({
//   appId: '2021000122664484',
//   privateKey: fs.readFileSync('private-key.pem', 'ascii'),
//   // 传入支付宝根证书、支付宝公钥证书和应用公钥证书。
//   alipayRootCertPath: path.join(__dirname, 'alipayRootCert.crt'),
//   alipayPublicCertPath: path.join(__dirname, 'alipayCertPublicKey_RSA2.crt'),
//   appCertPath: path.join(__dirname, 'appCertPublicKey.crt'),
// });
module.exports = alipaySdk

   AlipayForm ~ alipayForm文件

//参数 商品订单 商品名称 商品详细 商品价格
const AlipayForm = (orderNumber, goodsName, goodsDetail, price) => {
    return new Promise((resolve, reject) => {
        // 创建支付宝需要的表单表 对接支付宝
        const formData = new AlipayFormData();
        formData['setMethod']('get');
        // 支付成功回调地址,必须为可以直接访问的地址,不能带参数
        formData['addField']('returnUrl', 'http://localhost:9999/#/paysuccess');
        // 然后就是需要的订单参数
        formData['addField']('bizContent', {
            outTradeNo: orderNumber, // 商户订单号,64个字符以内、可包含字母、数字、下划线,且不能重复
            productCode: 'FAST_INSTANT_TRADE_PAY', // 销售产品码,与支付宝签约的产品码名称,仅支持FAST_INSTANT_TRADE_PAY
            totalAmount: `${price}`, // 订单总金额,单位为元,精确到小数点后两位
            subject: goodsName, // 订单标题
            body: goodsDetail, // 订单描述
        });

        // 业务处理
        // result 为可以跳转到支付链接的 url
        //'alipay.trade.page.pay' 统一收单下单并支付页面接口
        //{} api 请求的参数(包含“公共请求参数”和“业务参数”)
        alipaySdk.exec(
            'alipay.trade.page.pay',
            {},
            {formData: formData},
        ).then(reason => {
            resolve({
                message: '支付成功❗',
                code: 200,
                data: reason,
                ok: true
            })
        }, err => {
            resolve({
                message: '支付失败❗',
                code: 404,
                data: {},
                ok: false
            })
        })
    })
}

   AlipayFormStatus ~ alipayForm文件

//参数 订单号 交易号
const AlipayFormStatus = (out_trade_no, trade_no) => {
    return new Promise((resolve, reject) => {
        // 创建支付宝需要的表单表 对接支付宝
        const formData = new AlipayFormData();
        formData.setMethod('get');
        // 然后就是需要的订单参数
        formData.addField('bizContent', {
            out_trade_no,
            trade_no,
        });

        alipaySdk.exec(
            'alipay.trade.query',
            {},
            {formData: formData},
        ).then(result => {
            axios({
                url: result,
                method: 'get'
            }).then(reason => {
                let saveData = reason.data['alipay_trade_query_response']
                if (saveData.code === '10000') {
                    switch (saveData['trade_status']) {
                        case 'WAIT_BUYER_PAY':
                            resolve({
                                message: '通知不会返回,不能申请修改',
                                code: 199,
                                data: '支付宝有交易记录,没付款',
                                ok: true
                            })
                            break;
                        case 'TRADE_FINISHED':
                            resolve({
                                message: '交易结束,不可退款',
                                code: 200,
                                data: '交易完成',
                                ok: true
                            })
                            break;
                        case 'TRADE_SUCCESS':
                            resolve({
                                message: '高级即时到帐状态下',
                                code: 201,
                                data: '交易完成',
                                ok: true
                            })
                            break;
                        case 'TRADE_CLOSED':
                            resolve({
                                message: '默认通知不返回,可申请修改(条件需开通高级即时到帐功能,且非常需要退款的同步)。出现该情况在开通高级即时到帐时的人工操作退款时、买家没付款系统自动或卖家手动关闭了该笔交易',
                                code: 202,
                                data: '交易关闭',
                                ok: true
                            })
                            break;
                        default:
                            resolve({
                                message: '交易不存在❗',
                                code: 404,
                                data: {},
                                ok: false
                            })
                            break;
                    }
                } else {
                    resolve({
                        message: '交易不存在❗',
                        code: 404,
                        data: {},
                        ok: false
                    })
                }
            }, err => {
                resolve({
                    message: '交易不存在❗',
                    code: 404,
                    data: {},
                    ok: false
                })
            })
        }, err => {
            resolve({
                message: '交易不存在❗',
                code: 404,
                data: {},
                ok: false
            })
        })
    })
}

   AlipayForm文件 ~ 完整代码

const alipaySdk = require('./alipay.sdk')
const AlipayFormData = require('alipay-sdk/lib/form').default
const axios = require('axios')

//参数 商品订单 商品名称 商品详细 商品价格
const AlipayForm = (outTradeNo, goodsName, goodsDetail, price) => {
    return new Promise((resolve, reject) => {
        // 创建支付宝需要的表单表 对接支付宝
        const formData = new AlipayFormData();
        formData['setMethod']('get');
        // 支付成功回调地址,必须为可以直接访问的地址,不能带参数
        formData['addField']('returnUrl', 'http://127.0.0.1:3005/#/paysuccess');
        // 然后就是需要的订单参数
        formData['addField']('bizContent', {
            outTradeNo: outTradeNo, // 商户订单号,64个字符以内、可包含字母、数字、下划线,且不能重复
            productCode: 'FAST_INSTANT_TRADE_PAY', // 销售产品码,与支付宝签约的产品码名称,仅支持FAST_INSTANT_TRADE_PAY
            totalAmount: `${price}`, // 订单总金额,单位为元,精确到小数点后两位
            subject: goodsName, // 订单标题
            body: goodsDetail, // 订单描述
        });

        // 业务处理
        // result 为可以跳转到支付链接的 url
        //'alipay.trade.page.pay' 统一收单下单并支付页面接口
        //{} api 请求的参数(包含“公共请求参数”和“业务参数”)
        alipaySdk.exec(
            'alipay.trade.page.pay',
            {},
            { formData: formData },
        ).then(reason => {
            resolve({
                message: '支付成功❗',
                code: 200,
                data: reason,
                ok: true
            })
        }, err => {
            resolve({
                message: '支付失败❗',
                code: 404,
                data: {},
                ok: false
            })
        })
    })
}

//参数 订单号 交易号
const AlipayFormStatus = (out_trade_no, trade_no) => {
    return new Promise((resolve, reject) => {
        // 创建支付宝需要的表单表 对接支付宝
        const formData = new AlipayFormData();
        formData.setMethod('get');
        // 然后就是需要的订单参数
        formData.addField('bizContent', {
            out_trade_no,
            trade_no,
        });

        alipaySdk.exec(
            'alipay.trade.query',
            {},
            { formData: formData },
        ).then(result => {
            axios({
                url: result,
                method: 'get'
            }).then(reason => {
                let saveData = reason.data['alipay_trade_query_response']
                if (saveData.code === '10000') {
                    switch (saveData['trade_status']) {
                        case 'WAIT_BUYER_PAY':
                            resolve({
                                message: '通知不会返回,不能申请修改',
                                code: 199,
                                data: '支付宝有交易记录,没付款',
                                ok: true
                            })
                            break;
                        case 'TRADE_FINISHED':
                            resolve({
                                message: '交易结束,不可退款',
                                code: 200,
                                data: '交易完成',
                                ok: true
                            })
                            break;
                        case 'TRADE_SUCCESS':
                            resolve({
                                message: '高级即时到帐状态下',
                                code: 201,
                                data: '交易完成',
                                ok: true
                            })
                            break;
                        case 'TRADE_CLOSED':
                            resolve({
                                message: '默认通知不返回,可申请修改(条件需开通高级即时到帐功能,且非常需要退款的同步)。出现该情况在开通高级即时到帐时的人工操作退款时、买家没付款系统自动或卖家手动关闭了该笔交易',
                                code: 202,
                                data: '交易关闭',
                                ok: true
                            })
                            break;
                        default:
                            resolve({
                                message: '交易不存在❗',
                                code: 404,
                                data: {},
                                ok: false
                            })
                            break;
                    }
                } else {
                    resolve({
                        message: '交易不存在❗',
                        code: 404,
                        data: {},
                        ok: false
                    })
                }
            }, err => {
                resolve({
                    message: '交易不存在❗',
                    code: 404,
                    data: {},
                    ok: false
                })
            })
        }, err => {
            resolve({
                message: '交易不存在❗',
                code: 404,
                data: {},
                ok: false
            })
        })
    })
}

module.exports = {
    AlipayForm,
    AlipayFormStatus
}

使用沙箱

NodeJS实现支付宝沙箱支付②③_第3张图片

NodeJS实现支付宝沙箱支付②③_第4张图片

效果演示

AlipaySdk API ~

  • new AlipaySdk(config)
参数 类型 描述
Param Type Description
Config AlipaySdkConfig 初始化 SDK 配置
  • AlipaySdkConfig
参数 说明 类型 必须
appId 应用ID string
privateKey 应用私钥字符串 string
signType 签名种类 “RSA2”|“RSA”
alipayPublicKey 支付宝公钥(需要对返回值做验签时候必填) string
gateway 网关 string
timeout 网关超时时间(单位毫秒,默认 5s) number
camelcase 是否把网关返回的下划线 key 转换为驼峰写法 boolean
keyType 指定private key类型, 默认: PKCS1, PKCS8: PRIVATE KEY, PKCS1: RSA PRIVATE KEY “PKCS1”|“PKCS8”
appCertPath 应用公钥证书文件路径 string
appCertContent 应用公钥证书文件内容 string|Buffer
appCertSn 应用公钥证书sn string
alipayRootCertPath 支付宝根证书文件路径 string
alipayRootCertContent 支付宝根证书文件内容 string|Buffer
alipayRootCertSn 支付宝根证书 sn string 否
alipayPublicCertPath 支付宝公钥证书文件路径 string
alipayPublicCertContent 支付宝公钥证书文件内容 string|Buffer
alipayCertSn 支付宝公钥证书 sn string
encryptKey AES密钥,调用AES加解密相关接口时需要 string
wsServiceUrl 服务器地址 string
  • AlipaySdk.sdkExec(method, params) ⇒ string

作用 : 生成请求字符串,用于客户端进行调用 ~ Returns: string - 请求字符串

Param Type Description
method string 方法名
params IRequestParams 请求参数
params.bizContent object 业务请求参数
  • AlipaySdk.pageExec(method, params) ⇒ string

作用 :生成网站接口请求链接或表单 ~ Returns: string - 请求链接或表单 HTML

Param Type Description
method string 方法名
params IRequestParams 请求参数
params.bizContent object 业务请求参数
params.method string 后续进行请求的方法。如为 GET,即返回 http 链接;如为 POST,则生成表单 html
  • AlipaySdk.exec(method, params, option) ⇒ Promise.<(AlipaySdkCommonResult|string)>

作用 :执行请求,调用支付宝服务端

Returns: Promise.<(AlipaySdkCommonResult|string)> - 请求执行结果

Param Type Description
method string 调用接口方法名,比如 alipay.ebpp.bill.add
params IRequestParams 请求参数
params.bizContent object 业务请求参数
option IRequestOption 选项
option.validateSign Boolean 是否验签
args.log object 可选日志记录对象
  • AlipaySdkCommonResult

作用 : 响应结果

参数 说明 类型 必须
code 响应码。10000 表示成功,其余详见 https://opendocs.alipay.com/common/02km9f string
msg 响应讯息。Success 表示成功。 string
sub_code 错误代号 string
sub_msg 错误辅助信息 string
  • IRequestParams

作用 :请求参数

参数 说明 类型 必须
bizContent 业务请求参数 object
needEncrypt 自动AES加解密 boolean
  • AlipaySdk.checkNotifySign(postData, raw)

作用 :通知验签 ~ Returns: Boolean - 是否验签成功

Param Type Description
postData JSON 服务端的消息内容
raw Boolean 是否使用 raw 内容而非 decode 内容验签

最后

以上是个人学习Node的相关知识点,一点一滴的记录了下来,有问题请评论区指正,共同进步,这才是我写文章的原因之,如果这篇文章对您有帮助请三连支持一波

你可能感兴趣的:(NODEJS,前端,typescript,vscode)