微信支付链路+封装对接微信API工具类(下)

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 微信支付链路+封装对接微信API工具类(下)

封装获取微信平台证书列表+解密得到微信公钥

wx回调本地地址时使用wx证书的公 钥进行解密。

WxPayment
    //验证签名 timestamp,nonce,serial,signature均在HTTP头中获取,body为请求参数
    async verifySign({ timestamp, nonce, serial, body, signature }) {
        // 拼接参数
        let data = `${timestamp}\n${nonce}\n${typeof body == 'string' ? body : JSON.stringify(body)}\n`;
        // 用crypto模块解密
        let verify = crypto.createVerify('RSA-SHA256');
        // 添加摘要内容
        verify.update(Buffer.from(data));
        // 从初始化的平台证书中获取公钥
        for (let cert of this.certificates) {
            if (cert.serial_no == serial) {
                return verify.verify(cert.public_key, signature, 'base64');
            } else {
                throw new Error('平台证书序列号不相符')
            }
        }
    }
       //解密证书列表 解出CERTIFICATE以及public key
    async decodeCertificates() {
        let result = await this.getCertificates();
        if (result.status != 200) {
            throw new Error('获取证书列表失败')
        }
        let certificates = typeof result.data == 'string' ? JSON.parse(result.data).data : result.data.data
        for (let cert of certificates) {
            let output = this.dec ode(cert.encrypt_certificate)
            cert.decrypt_certificate = output.toString()
            let beginIndex = cert.decrypt_certificate.indexOf('-\n')
            let endIndex = cert.decrypt_certificate.indexOf('\n-')
            let str = cert.decrypt_certificate.substring(beginIndex + 2, endIndex)
            // 生成X.509证书
            let x509Certificate = new x509.X509Certificate(Buffer.from(str, 'base64'));
            let public_key = Buffer.from(x509Certificate.publicKey.rawData).toString('base64')
            // 平台证书公钥
            cert.public_key = `-----BEGIN PUBLIC KEY-----\n` + public_key + `\n-----END PUBLIC KEY-----`
        }
        return this.certificates = certificates
    }
    //解密
    decode(params) {
        const AUTH_KEY_LENGTH = 16;
        // ciphertext = 密文,associated_data = 填充内容, nonce = 位移
        const { ciphertext, associated_data, nonce } = params;
        // 密钥
        const key_bytes = Buffer.from(this.apiv3_private_key, 'utf8');
        // 位移
        const nonce_bytes = Buffer.from(nonce, 'utf8');
        // 填充内容
        const associated_data_bytes = Buffer.from(associated_data, 'utf8');
        // 密文Buffer
        const ciphertext_bytes = Buffer.from(ciphertext, 'base64');
        // 计算减去16位长度
        const cipherdata_length = ciphertext_bytes.length - AUTH_KEY_LENGTH;
        // upodata
        const cipherdata_bytes = ciphertext_bytes.slice(0, cipherdata_length);
        // tag
        const auth_tag_bytes = ciphertext_bytes.slice(cipherdata_length, ciphertext_bytes.length);
        const decipher = crypto.createDecipheriv(
            'aes-256-gcm', key_bytes, nonce_bytes
        );
        decipher.setAuthTag(auth_tag_bytes);
        decipher.setAAD(Buffer.from(associated_data_bytes));
        const output = Buffer.concat([
            decipher.update(cipherdata_bytes),
            decipher.final(),
        ]);
        return output;
    } 

封装验证微信发起的签名+解密数据得到用户订单信息

开发微信服务器回调接口

  callback: async (req) => {
    let timestamp = req.header('Wechatpay-Timestamp')
    let nonce = req.header('Wechatpay-Nonce')
    let serial = req.header('Wechatpay-Serial')
    let signature = req.header('Wechatpay-Signature')
    let body = req.body
    // 1.校验收到的请求是否来自微信服务器和平台证书是否一致
    let result = await payment.verifySign({
      timestamp,
      nonce,
      serial,
      signature,
      body
    })
    if (!result) {
      return
    }
    // 2.解密body中的数据,拿到用户订单信息
    let bufferoOne = payment.decode(body.resource)
    let json = JSON.parse(bufferoOne.toString('utf8'))
    let { out_trade_no, trade_state } = json
    console.log(json)
    if (trade_state === 'SUCCESS') {
      // 3.根据微信服务器返回的订单信息更新数据库中改订单的支付状态
      await DB.ProductOrder.update({ order_state: 'PAY' }, { where: { out_trade_no } })
      // 4.更新redis课程热门排行榜数据
      let productItem = await DB.ProductOrder.findOne({ where: { out_trade_no }, raw: true })
      let memberInfo = {
        id: productItem.product_id,
        title: productItem.product_title,
        img: productItem.product_img,
      }
      let time = dayjs(Date.now()).format('YYYY-MM-DD')
      await redisConfig.zincrby({ key: `${time}:rank:hot_product`, increment: 1, member: JSON.stringify(memberInfo) })
    }
    return BackCode.buildSuccess()
  },

这里redis的逻辑是

  1. DB.ProductOrder.findOne({ where: { out_trade_no }, raw: true }): 这是一个数据库查询操作,通过out_trade_no作为查询条件,在ProductOrder表中查找匹配的记录,并返回一个包含产品项信息的对象。raw: true选项表示返回原始数据,而不进行模型实例化。
  2. 接下来,将产品项的信息存储到memberString对象中,包括产品的 ID、标题和图片。
  3. dayjs(Date.now()).format('YYYY-MM-DD'): 这行代码使用了第三方库 dayjs,用于获取当前日期并以 'YYYY-MM-DD' 的格式进行格式化。生成的日期字符串被存储在time变量中。
  4. redisConfig.zincrby({ key: {time}:rank:hot_product, increment: 1, member: JSON.stringify(memberString) }): 这是一个使用 Redis 的命令,通过zincrby方法向 Redis 的有序集合中更新数据。key参数表示要更新的有序集合的键名,这里使用了{time}:rank:hot_product作为键名;increment参数表示每次增加的分值,这里设置为 1;member参数表示要添加或更新的成员,将前面存储的产品项信息以 JSON 字符串的形式作为成员。

每天凌晨清除昨天的数据

定时插件

yarn add node-schedule@2.1.0

配置

// 定时任务工具
const schedule = require('node-schedule')
let rule = new schedule.RecurrenceRule()
class ScheduleTool {
  // 每天凌晨0点执行
  static dayJob(handle) {
    rule.hour = 0
    schedule.scheduleJob(rule, handle)
  }
}
module.exports = ScheduleTool

定时任务执行

ScheduleTool.dayJob(() => {
  let yesterday = dayjs().subtract(1, 'day').format('YYYY-MM-DD')
  redisConfig.del(`${yesterday}:rank:hot_product`)
})

我们要拿到的就是body.resource

image.png

pay.weixin.qq.com/wiki/doc/ap…

订单状态确认-查询订单⽀付状态逻辑封装+快速验证

node服务器主动进行接口调用查询订单

查询订单逻辑封装

//通过out_trade_no查询订单
async getTransactionsByOutTradeNo(params) {
  return await this.wxSignRequest({ pathParams: params, type: 'getTransactionsByOutTradeNo' })
}

验证订单状态查询

const { payment } = require('./config/wechatPay');
(async () => {
    let wechatOrder = await payment.getTransactionsByOutTradeNo({ out_trade_no: '123456789wqjeqjwdiqhdhqd' })
    console.log(wechatOrder.data)
})()
目录
相关文章
|
2月前
|
监控 安全 API
什么是API?进行API对接的5大常见误区!
API是软件间通信的桥梁,API对接则实现系统间数据互通。广泛应用于内外部系统集成,提升效率、降低成本、增强竞争力。本文详解其概念、场景、方法及常见误区。
什么是API?进行API对接的5大常见误区!
|
2月前
|
JSON 监控 API
Shopee:对接海外仓API实现本地发货,优化物流时效
Shopee卖家可通过对接海外仓API实现本地发货,将物流时效从10-15天缩短至3-5天,显著提升买家体验与店铺转化率。本文详解API对接原理、步骤及代码示例,助力优化跨境物流效率。
155 1
|
2月前
|
JSON 监控 API
小红书:对接苹果支付API满足iOS用户习惯,提升转化率
小红书集成Apple Pay可显著提升iOS用户支付体验,简化流程、增强安全、提高转化率。本文详解从开发配置、代码实现到后端验证与优化策略的全流程,助力高效落地,推动业务增长。(238字)
339 0
|
2月前
|
数据采集 缓存 API
小红书笔记详情 API 实战指南:从开发对接、场景落地到收益挖掘(附避坑技巧)
本文详解小红书笔记详情API的开发对接、实战场景与收益模式,涵盖注册避坑、签名生成、数据解析全流程,并分享品牌营销、内容创作、SAAS工具等落地应用,助力开发者高效掘金“种草经济”。
小红书笔记详情 API 实战指南:从开发对接、场景落地到收益挖掘(附避坑技巧)
|
2月前
|
JSON 安全 测试技术
医药电商:对接处方审核API实现线上购药合规化
医药电商需合规销售处方药。本文详解对接处方审核API,实现自动化真实性验证、用药合理性审查与全程留痕,满足监管要求。提升审核效率至3秒内,错误率低于0.5%,降低人力成本40%。构建审核闭环,保障安全与体验双赢。(238字)
347 0
|
2月前
|
消息中间件 人工智能 Java
抖音微信爆款小游戏大全:免费休闲/竞技/益智/PHP+Java全筏开源开发
本文基于2025年最新行业数据,深入解析抖音/微信爆款小游戏的开发逻辑,重点讲解PHP+Java双引擎架构实战,涵盖技术选型、架构设计、性能优化与开源生态,提供完整开源工具链,助力开发者从理论到落地打造高留存、高并发的小游戏产品。
|
3月前
|
小程序 JavaScript API
uni-halo + 微信小程序开发实录:我的第一个作品诞生记
这篇文章介绍了使用uni-halo框架进行微信小程序开发的过程,包括选择该框架的原因、开发目标以及项目配置和部署的步骤。
167 0
uni-halo + 微信小程序开发实录:我的第一个作品诞生记
|
9月前
|
自然语言处理 搜索推荐 小程序
微信公众号接口:解锁公众号开发的无限可能
微信公众号接口是微信官方提供的API,支持开发者通过编程与公众号交互,实现自动回复、消息管理、用户管理和数据分析等功能。本文深入探讨接口的定义、类型、优势及应用场景,如智能客服、内容分发、电商闭环等,并介绍开发流程和工具,帮助运营者提升用户体验和效率。未来,随着微信生态的发展,公众号接口将带来更多机遇,如小程序融合、AI应用等。
|
6月前
|
小程序 前端开发 Android开发
小程序微信分享功能如何开发?开放平台已绑定仍不能使用的问题?-优雅草卓伊凡
小程序微信分享功能如何开发?开放平台已绑定仍不能使用的问题?-优雅草卓伊凡
1402 29
小程序微信分享功能如何开发?开放平台已绑定仍不能使用的问题?-优雅草卓伊凡
|
5月前
|
监控 数据可视化 数据处理
微信养号脚本,全自动插件,AUTOJS开发版
这是一套自动化微信养号工具,包含主脚本`wechat_auto.js`与配置文件`config.json`。主脚本实现自动浏览朋友圈、随机阅读订阅号文章及搜索指定公众号三大功能,支持自定义滚动次数、阅读时长等参数。代码通过随机化操作间隔模拟真实用户行为,具备完善的错误处理和日志记录功能。配套UI模块提供可视化操作界面,可实时监控任务状态与运行日志,便于调整参数设置。控制器部分扩展了批量数据处理能力,如学生信息的增删改查操作,适用于多场景应用。下载地址:https://www.pan38.com/share.php?code=n6cPZ 提取码:8888(仅供学习参考)。
下一篇
oss云网关配置