小程序消息
本章节介绍如何使用小程序消息通道,在主播端小程序下发消息给观众端小程序。通常的场景是:
- 主播端设置一些参数,例如提示语、礼物设置等等;
- 观众端根据这些参数做一些操作,例如显示提示语、渲染礼物按钮供用户送礼等等。
为了满足上面的业务场景,虎牙小程序平台提供了两条小程序消息通信通道,分别为:
主播端到观众端的单向通道,通过JS SDK通信
- 主播端通过hyExt.observer.emit SDK 向观众端下发消息;
- 观众端通过hyExt.observer.on SDK 监听小程序响应消息。
业务服务端到主播端/观众端的单向通道,通过小程序API通信
- 业务服务器通过小程序API给主播端/观众端下发消息;
- 主播端/观众端通过hyExt.observer.on监听小程序响应消息;
- 如果需要观众端反馈消息到主播端,则需要:
- 观众端调用hyExt.request通知业务服务器
- 业务服务器通过小程序API转推到主播端
- 并不支持直接从观众端下发消息给主播端
以下是两种通信方式的简单示例:
方式一:通过SDK通信
此模块主要介绍 主播端调用hyExt.observer.emit SDK 给观众端下发消息,观众端调用hyExt.observer.on SDK 监听小程序响应消息,这是一条单向通道,实现主播端向观众端下发消息。
准备工作
参考创建小程序项目,初始化一个小程序项目,其中小程序类型选择:
- 虎牙直播主站-面板
- 虎牙直播APP-面板
- PC主播端-面板
参考创建小程序,创建一个小程序和创建一个开发版本。
新增示例组件
在streamer主播端和viewer观众端各新增两个文件,共新增四个文件
- 新增
streamer/common.js:
import React, { useState, useEffect } 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 emitMessage = function () {
hyExt.observer
.emit("message-push", `${JSON.stringify(sendMessage)}`)
.then((res) => {
setSendResult("向客户端小程序广播信息成功!");
})
.catch((err) => {
setSendResult("内容包含敏感信息,广播消息失败!");
});
};
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={() => emitMessage()}>
发送数据至观众端
</Button>
</View>
<Text className="text">发送结果:{sendResult}</Text>
</View>
);
};
- 新增
streamer/common.hycss:
.container{
flex: 1;
align-items: center;
margin-top: 200px;
}
.section {
margin: 20px auto;
}
.button {
height: 100px;
width: 400px;
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;
}
- 新增
viewer/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>
);
};
- 新增
viewer/common.hycss:
.container {
display: flex;
flex: 1;
justify-content: center;
align-items: center;
}
其中:
- 使用
React.useState()记录主播端需要广播的文本信息、广播的结果,观众端监听接收到的响应信息; - 主播端点击按钮触发自定义的
emitMessage()方法,调用hyExt.observer.emit SDK 后,首先会自动向虎牙平台发起文本的秩序审核,审核通过的信息会被成功广播; - 观众端使用
React.useEffect()调用hyExt.observer.on SDK 监听主播端发送的小程序消息。
在小程序中使用组件
修改streamer/app.js和viewer/app.js两个文件
- 修改
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>
)
}
}
- 修改
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>
)
}
}
在直播间中预览
参考在直播间预览的方式,运行npm start,启动开发服务,在直播间添加并打开 开发版小程序:
- PC主播端
- 虎牙主站
通过文本的秩序审核,广播消息成功
- PC主播端
- 虎牙主站
- 虎牙直播APP
未通过文本的秩序审核,发送失败,观众端无法正常接收消息
方式二:通过小程序API通信
此模块主要介绍通过小程序API实现观众端向主播端反馈消息,这是一条单向通道,总体实现流程如下:
- 观众端调用hyExt.request通知业务服务器;
- 业务服务器通过小程序API转推到主播端;
- 主播端通过hyExt.observer.on监听小程序响应消息。
下面将会演示利用Express搭建一个简单的业务服务器,并对方式一中的小程序进行简单改造,实现观众端向主播端反馈消息。
搭建业务服务器
- 创建项目文件夹,运行
npm init创建package.json文件; - 安装
Express、request、jsonwebtoken和cors,并保存在依赖列表中;npm install express --save npm install jsonwebtoken --save npm install request --save npm install cors --save npm install body-parser --save
- 安装
jsonwebtoken依赖用于JWT统一鉴权- 调用
jwt.verify()方法,对观众端调用hyExt.requestSDK 请求的数据进行解码,获得profileId、roomId等信息 - 调用
jwt.sign()方法,会根据Header.Payload.Signature的格式生成鉴权签名
- 调用
- 安装
request依赖用于向小程序API https://apiext.huya.com 发送请求,具体接口可查看小程序API列表 - 安装
cors依赖用于处理跨域问题 - 安装
body-parser依赖用于解析body数据,不解析无法读取req.body
新增
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); /** * 发送请求 */ await request( { url: `https://apiext.huya.com/message/deliverByProfileId?appId=${appId}&extUuid=${extUuid}`, method: "POST", headers: { Authorization }, 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("启动成功!"); });
改造方式一的示例小程序
- 修改
streamer/common.js文件
- 添加
requestServer()方法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> );
在小程序中使用组件
在streamer/app.js中使用viewer/common.js组件,在viewer/app.js中使用streamer/common.js组件。
- 修改
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 { Example } from '../viewer/common'
import './app.hycss'
const { View, Text } = UI
class App extends Component {
render () {
return (
<View className="container">
<Example />
</View>
)
}
}
- 修改
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 { Example } from '../streamer/common'
import './app.hycss'
const { View, Text } = UI
class App extends Component {
render () {
return (
<View className="container">
<Example />
</View>
)
}
}
在直播间中预览
参考在直播间预览的方式,运行npm start,启动小程序开发服务,在直播间添加并打开 开发版小程序。同时运行node app.js命令启动业务服务器。
- 虎牙主站
- PC主播端
注意事项
- 上述通过小程序API通信中,在观众端调用hyExt.request SDK 向业务服务器传递数据时,需要调用hyExt.order.reportText SDK 对传输的data数据进行文本的秩序审核;
- 本章节仅提供
Node.js版本的小程序API接入示例,JAVA和Python的接入示例代码可参考接入示例代码; - 小程序API列表中的后台API的使用权限需要在开发者中心中提交请求IP白名单(增强套餐)申请,具体请参考权限管理说明
相关链接
- 创建小程序项目
- 创建小程序
- 网络库
- 小程序API
- 开放API
- 接口
- github仓库
- 通过SDk通信的示例小程序:https://github.com/huya-ext/hyext-examples/tree/master/examples/observer-event-sdk-version
- Express版本的业务服务器:https://github.com/huya-ext/hyext-examples/tree/master/examples/observer-event-api-version/express-server
- 通过API通信的示例小程序:https://github.com/huya-ext/hyext-examples/tree/master/examples/observer-event-api-version/observer-event-miniapp