虎牙开放平台文档

网络库

本章节介绍如何使用网络库向业务服务器发送请求,以及在业务服务器处理并转发接收到的请求。

演示初始化一个示例小程序和搭建一个简单Express业务服务器(代理服务器),将会在该示例小程序中调用虎牙小程序提供的hyExt.request SDK 向业务服务器发送HTTP请求。

业务服务器接收和解析小程序的请求数据后,需要根据JWT统一鉴权的规范生成鉴权签名 ,并将该鉴权签名添加到请求头部(http header)的authorization <token>中,向小程序后台服务 https://apiext.huya.com 发送请求。

小程序后台服务会根据这个请求头校验当前请求是否从虎牙小程序平台发出,并且可解密获取更多信息。

新建小程序

准备工作

参考创建小程序项目,初始化一个小程序项目,其中小程序类型选择:

  • 虎牙直播主站-面板
  • 虎牙直播APP-面板
  • PC主播端-面板

参考创建小程序,创建一个小程序和创建一个开发版本。

新增示例组件

  1. viewer观众端新增viewer/common.jsviewer/common.hycss两个文件
  • 新增viewer/common.js
import React, { useState } from "react"; import { UI } from "@hyext/hy-ui"; import "./common.hycss"; const { View, Text, Input, Button } = UI; export const Example = () => { const [sendMessage, setSendMessage] = useState(""); const [sendResult, setSendResult] = useState("暂无发送"); const requestServer = function () { hyExt .request({ url: "http://localhost:3001", // 本地业务服务器 method: "POST", data: {"event": "message-push", "message": sendMessage}, dataType: "text", isDirect: true, }) .then((res) => { setSendResult("向业务服务器发送数据成功!", res); }) .catch((err) => { setSendResult("向业务服务器发送数据失败!", err); }); }; return ( <View className="container"> <View className="section"> <Text>请在输入框输入数据</Text> <Input className="input" blurOnSubmit={false} placeholder="输入发送输入" value={sendMessage} onChange={(v) => setSendMessage(v)} /> </View> <View className="section"> <Button className="button" onPress={() => requestServer()}> 发送数据 </Button> </View> <Text className="text">发送结果:{sendResult}</Text> </View> ); };
  • 新增viewer/common.hycss
.container{ flex: 1; align-items: center; margin-top: 200px; } .section { margin: 20px auto; } .button { height: 100px; background-color: rgb(253, 69, 69); border-radius: 50px; } .input { width: 600px; height: 80px; border: gray solid 3px; border-radius: 20px; } .text{ margin-top: 10px; }
  1. streamer观众端新增streamer/common.jsstreamer/common.hycss两个文件
  • 新增streamer/common.js
import React, { useState, useEffect } from "react"; import { UI } from "@hyext/hy-ui"; import "./common.hycss"; const { View, Text } = UI; export const Example = () => { const [receiveMessage, setReceiveMessage] = useState("暂无消息"); useEffect(() => { hyExt.observer.on("message-push", (content) => setReceiveMessage(JSON.parse(content))); }, []); return ( <View className="container"> <Text>监听到的消息:{receiveMessage}</Text> </View> ); };
  • 新增streamer/common.hycss
.container { display: flex; flex: 1; justify-content: center; align-items: center; }

在小程序中使用组件

  • 修改viewer/app.js
--- a/viewer/app.js +++ b/viewer/app.js @@ -1,5 +1,6 @@ import { UI } from '@hyext/hy-ui' import React, { Component } from 'react' +import { Example } from './common' import './app.hycss' const { View, Text } = UI @@ -7,7 +8,9 @@ const { View, Text } = UI class App extends Component { render () { return ( - <View className="container"><Text>hello world</Text></View> + <View className="container"> + <Example /> + </View> ) } }
  • 修改streamer/app.js
--- a/streamer/app.js +++ b/streamer/app.js @@ -1,5 +1,6 @@ import { UI } from '@hyext/hy-ui' import React, { Component } from 'react' +import { Example } from './common' import './app.hycss' const { View, Text } = UI @@ -7,7 +8,9 @@ const { View, Text } = UI class App extends Component { render () { return ( - <View className="container"><Text>hello world</Text></View> + <View className="container"> + <Example /> + </View> ) } }

搭建业务服务器

  1. 创建项目文件夹,运行npm init创建package.json文件;
  2. 安装Expressrequestjsonwebtokencors,并保存在依赖列表中; npm install express --save npm install jsonwebtoken --save npm install request --save npm install cors --save npm install body-parser --save
  • 安装jsonwebtoken依赖用于JWT统一鉴权
    • 开发者中心获取appSecret(开发者密钥)后,调用jwt.verify()方法,对观众端调用hyExt.request SDK 请求的authorization数据进行解码,获得profileIdroomId等信息
    • 调用jwt.sign()方法,根据Header.Payload.SignatureJWT统一鉴权规范生成鉴权签名
  • 安装request依赖用于向小程序API https://apiext.huya.com 发送请求,具体接口可查看小程序API列表
  • 安装cors依赖用于统一处理跨域问题
  • 安装body-parser依赖用于解析body数据,不解析无法读取req.body
  1. 新增app.js文件

    const express = require("express"); const cors = require("cors"); const app = express(); const request = require("request"); const jwt = require("jsonwebtoken"); const bodyParser = require("body-parser"); // 跨域处理 app.use(cors()); // 解析body内的数据 app.use(bodyParser.json()); app.use("/", async (req, res, next) => { /** * 从小程序观众端获得请求信息 * 需要对authorization进行解密 */ const authorization = req.headers.authorization; // appSecret【填入自己专属的appSecret】 const appSecret = "xxxxxx"; // 解密观众端的请求信息 let decodeData = jwt.verify(authorization, appSecret); // 需要请求的数据 const { iat, exp, appId, extUuid, profileId, roomId } = decodeData; const { event, message } = req.body; /** * 生成签名Authorization * 格式:Header.Payload.Signature */ // 1. header:调用jwt.sign()方法之后会编码成"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"字符串(可在jwt.io验证) const header = { // alg属性表示签名的算法,字符串类型,默认是HS256(HMACSHA256) alg: "HS256", // typ属性表示token的类型,字符串类型,统一为JWT typ: "JWT", }; // 2.Payload:实际需要传递的数据 const payload = { iat, // token生成时间戳(秒) exp, // 过期时间戳(秒) appId, // 小程序开发者appid extUuid, // 小程序uuid }; // 3. Signature(同上appSecret)【填入自己专属的appSecret】 const signature = appSecret; // 4. 生成签名 const Authorization = jwt.sign(header + "." + payload, signature); console.log("==============打印数据==============="); console.log("req.body:", req.body); console.log("请求头解码后数据为:", decodeData); console.log("打印生成的数字签名:", Authorization); /** * 向虎牙后台服务发送请求 * 此处调用 /message/deliverByProfileId 接口只做简单实例,完整示例可查看 小程序消息 场景文档。 */ await request( { url: `https://apiext.huya.com/message/deliverByProfileId?appId=${appId}&extUuid=${extUuid}`, method: "POST", headers: { Authorization }, // headers中携带生成的数字签名 json: true, body: { profileId, roomId, event, message, }, }, (error, response, body) => { if (!error && response.statusCode == 200) { res.send("广播成功!"); } } ); }); // 监听端口、启动程序 app.listen(3001, (err) => { if (err) throw err; console.log("http://localhost:3001"); console.log("启动成功!"); });

    在直播间中预览

    参考在直播间预览的方式,运行npm start,启动开发服务,在直播间添加并打开 开发版小程序。同时运行node app.js命令启动业务服务器。

2022 04 15 11 20 19

输入合法内容并点击“发送数据”按钮后向业务服务器发送请求。

  • 虎牙主站

2022 04 15 12 00 12

  • 业务服务器

打印小程序通过调用hyExt.request SDK 发送的data数据,解码后的authorization数据以及生成的鉴权签名字符串。

2022 04 15 12 01 11

注意事项

  • 调用hyExt.request SDK 向业务服务器发送请求时
    • 回包大小限制:64KB;
    • 发包大小限制:5KB;
    • POST方法请求时,data会以application/json方式传递;服务器可通过获取body中的信息,做JSON反序列化,获取对应参数;
  • 示例小程序在请求时添加isDirect字段(本地开发,且保持最新版本的APP和SDK)和配置本地服务后,才能请求本地的后台服务,实际应用中还需要把对应的HTTP服务发到公网中使用

相关链接