nodejs 支付宝app支付
【链接】单笔转账到支付宝账户产品介绍更新时间:
https://docs.open.alipay.com/309
const crypto = require('crypto')
const moment = require('moment')
1.返回给移动端签名字符串:
router.post('createAliPayment', async (ctx, next) => {
    const orderInfo = await model.order.findOne({
        'orderStatus.status': {
            $in: [1, 9]
        },
        orderCode: ctx.params.orderCode,
        createdBy: ctx.user.userid,
        isDelete: false
    }, {
        _id: 0,
        orderCode: 1,
        transCode: 1,
        orderProducts: 1,
        CNYCharge: 1
    })
    if (!orderInfo) {
        throw {
            status: 20001,
            message: 'paying orderInfo not exists'
        }
        return
    }
    let aliPaySignObj = {
        app_id: '支付宝商户Id',
        method: 'alipay.trade.app.pay',
        charset: 'utf-8',
        sign_type: 'RSA2',
        timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
        version: '1.0',
        notify_url: `${config.notify_ulr}`,
        biz_content: JSON.stringify({
            body: '冰糖葫芦',
            subject: '冰糖葫芦',
            out_trade_no: orderInfo.orderCode,
            timeout_express: '15m',
            total_amount: Number(orderInfo.CNYCharge).toString(),
            product_code: 'QUICK_MSECURITY_PAY'
        })
    };
    let signStr = '',
        encodeStr = '';
    for (let n of Object.keys(aliPaySignObj).sort()) {
        signStr += (n + '=' + aliPaySignObj[n] + '&');
        encodeStr += (n + '=' + encodeURIComponent(aliPaySignObj[n]) + '&');
    }
    signStr = signStr.substring(0, signStr.length - 1);
    var signer = crypto.createSign('RSA-SHA256').update(signStr);
    let privateKey = fse.readFileSync(path.join(__dirname, '../alipay_private_key.pem')).toString();
    let sign = signer.sign(privateKey, 'base64')
    ctx.body = {
        encodeStr: encodeStr + 'sign=' + encodeURIComponent(sign)
    }
})
2.支付宝回调
router.post('notifyFromAliPay', async (ctx, next) => {
    const resData = ctx.params;
    if (!(resData && resData.trade_status && resData.trade_status == 'TRADE_SUCCESS')) {
        ctx.body = 'fail';
        return;
    }
    //1.验证签名信息
    let signStr = '';
    for (let n of Object.keys(resData).sort()) {
        if (n !== 'sign' && n !== 'sign_type') {
            signStr += (n + '=' + decodeURIComponent(resData[n]) + '&');
        }
    }
    signStr = signStr.substring(0, signStr.length - 1);
    let signer = crypto.createVerify('RSA-SHA256').update(signStr);
    const aliPublicKey = fse.readFileSync(path.join(__dirname, "../alipay_public_key.pem")).toString();
    const sign = signer.verify(aliPublicKey, resData.sign, 'base64');
    if (!sign) {
        ctx.body = 'fail';
        return;
    }
    const orderCodePhoto = resData.out_trade_no;
    const orderDb = await model.order.findOne({
        orderCode: orderCodePhoto
    }, {
        _id: 0,
        siteId: 1,
        CNYCharge: 1,
        usePPCodes: 1,
        orderProducts: 1,
        virtualProducts: 1,
        createdBy: 1,
        charge: 1
    })
    if (!orderDb) {
        throw new Error('alipay notify orderCode not exists !')
    }
    let queryAlipayParams = {
        app_id: '支付宝商户Id',
        method: 'alipay.trade.query',
        charset: 'utf-8',
        sign_type: 'RSA2',
        timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
        version: '1.0',
        biz_content: JSON.stringify({
            out_trade_no: orderCodePhoto,
            trade_no: resData.trade_no
        })
    }
    let signString = '',
        encodeStr = '';
    for (let n of Object.keys(queryAlipayParams).sort()) {
        signString += (n + '=' + queryAlipayParams[n] + '&');
        encodeStr += (n + '=' + encodeURIComponent(queryAlipayParams[n]) + '&');
    }
    signString = signString.substring(0, signString.length - 1);
    var signQuery = crypto.createSign('RSA-SHA256').update(signString);
    let privateKey = fse.readFileSync(path.join(__dirname, '../alipay_private_key.pem')).toString();
    let signrs = encodeURIComponent(signQuery.sign(privateKey, 'base64'));
    const querParams = encodeStr + `sign=${signrs}`;
    const queryAlipayResult = await request.getAsync({
        url: 'https://openapi.alipay.com/gateway.do?' + querParams
    })
    const aplipayQueryResult = queryAlipayResult && JSON.parse(queryAlipayResult.body) || '';
    if (!aplipayQueryResult) {
        ctx.body = 'fail';
        return;
    }
    const aplipayqr = aplipayQueryResult.alipay_trade_query_response;
    if (!(aplipayqr.code == '10000' && aplipayqr.msg == 'Success' && aplipayqr.trade_status == 'TRADE_SUCCESS' && Number(aplipayqr.total_amount) == orderDb.CNYCharge)) {
        ctx.body = 'fail';
        return;
    }
    try {
        ctx.body = 'success';
//更新业务操作
    } catch (err) {
        throw new Error(err)
    }
}
总结:1.nodejs app支付,后端做的就是以上两步,剩下的就是app端的事了。
2.以上代码,复制,稍微改改就成了
nodejs 支付宝app支付的更多相关文章
- 支付宝APP支付开发- IOException : DER input, Integer tag error
		支付宝APP支付Java开发报错: 1 java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: I ... 
- 支付宝APP支付开发- IOException : DerInputStream.getLength(): lengthTag=127, too big.
		支付宝APP支付Java开发报错: IOException : DerInputStream.getLength(): lengthTag=127, too big. 后来排查是因为没有设置私钥. 
- 支付宝APP支付之Java后台生成签名具体步骤
		/** *支付宝支付 * @param orderId 订单编号 * @param actualPay 实际支付金额 * @return */ private String getOrderInfoB ... 
- Android版-支付宝APP支付
		此项目已开源 赶快来围观 Start支持下吧 [客户端开源地址-JPay][服务端端开源地址-在com.javen.alipay 包名下] 上一篇详细介绍了微信APP支付 点击这里 此篇文章来详细介绍 ... 
- H5使用codovar插件实现支付宝支付(支付宝APP支付模式,前端)
		H5打包的app实现支付及支付宝支付,本章主要详解支付宝支付,微信支付请查看另一篇“H5使用codovar插件实现微信支付(微信APP支付模式,前端)” ps:本文只试用H5开发的,支付宝 APP支付 ... 
- 支付宝app支付服务端流程
		支付宝APP支付服务端详解 前面接了微信支付,相比微信支付,支付宝APP支付提供了支付封装类,下面将实现支付宝APP支付.订单查询.支付结果异步通知.APP支付申请参数说明,以及服务端返回APP端发起 ... 
- 微信、支付宝App支付-JPay0.0.2发布
		JPay 对微信App支付.支付宝App支付的二次封装,对外提供一个相对简单的接口以及支付结果的回调 GitHub:https://github.com/Javen205/JPay OsChina:h ... 
- 支付宝app支付java后台流程、原理分析(含nei wang chuan tou)
		java版支付宝app支付流程及原理分析 本实例是基于springmvc框架编写 一.流程步骤 1.执行流程 当手机端app(就是你公司开发的app)在支付 ... 
- 支付宝APP支付IOS手机端java后台版
		版权声明:http://blog.csdn.net/u012131769/article/details/76639527#t8 转载:http://blog.csdn.net/u012131769/ ... 
随机推荐
- .gz解压
			1.今天很神奇我遇到这样的压缩包,啧啧啧,好少见的,记录下 gzip -d http_log.gz 这是讲http_log文件解压到当前的路径下 
- python面向对象三大特性-多态
			import abc #利用abc模块实现抽象类 class All_file(metaclass=abc.ABCMeta): all_type='file' @abc.abstractmethod ... 
- Flask-WTF中的csrf保护
			CSRF 保护 这部分文档介绍了 CSRF 保护. 为什么需要 CSRF? Flask-WTF 表单保护你免受 CSRF 威胁,你不需要有任何担心.尽管如此,如果你有不包含表单的视图,那么它们仍需要保 ... 
- SpringBoot整合Kafka
			一.准备工作 提前启动zk,kafka,并且创建一个Topic("Hello-Kafk") bin/kafka-topics.sh --create --zookeeper 192 ... 
- VS2017远程调试C#或 Visual Studio 中的 Visual Basic 项目
			来源:远程调试C#或 Visual Studio 中的 Visual Basic 项目 若要调试已部署在另一台计算机的 Visual Studio 应用程序,安装和在其中部署您的应用程序的计算机上运行 ... 
- 如何保证Redis的高并发
			单机的redis几乎不太可能说QPS超过10万+,一般在几万. 除非一些特殊情况,比如你的机器性能特别好,配置特别高,物理机,维护做的特别好,而且你的整体的操作不是太复杂. Redis通过主从架构,实 ... 
- 各厂商服务器存储默认管理口登录信息(默认IP、用户名、密码)收集
			666:https://blog.csdn.net/xiezuoyong/article/details/84997917 
- vue-all
			http://v1-cn.vuejs.org/guide/ [1]. vue-cli [项目不完整,跳过]https://github.com/vuejs/vue-cli vue-cli-master ... 
- 详解 Java 中的三种代理模式
			代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能. 这里使用 ... 
- [转]Ubuntu /home下中文目录如何修改成英文?
			http://www.linuxidc.com/Linux/2016-05/130873.htm 打开终端,在终端中输入命令: export LANG=en_US xdg-user-dirs-gtk- ... 
