邀请好友
功能概述
使用好友邀请功能,可以快捷地给好友发送游戏邀请,被邀请的好友可以通过邀请消息一键加入游戏。
支持两种邀请消息:
- 邀请好友启动游戏(邀上线):被邀请方接受邀请后,
- 如果游戏运行中,游戏内会收到
TapEventID::RelationGameInviteReceived通知。 - 如果游戏未运行,TapTap 启动器会带命令行参数
--tap_invite_scheme启动游戏。
- 如果游戏运行中,游戏内会收到
- 邀请好友加入队伍(邀组队):邀请好友加入指定队伍/房间,需要传入开发者自定义的
team_id。被邀请方接受邀请后,- 如果游戏运行中,游戏内会收到
TapEventID::RelationTeamInviteReceived通知,其中包括team_id。 - 如果游戏未运行,TapTap 启动器会带命令行参数
--tap_invite_scheme启动游戏。
- 如果游戏运行中,游戏内会收到
命令行参数示例:
yourgame.exe --tap_invite_scheme="tds<client_id>://<action>?open_id=xxx&union_id=yyy[&team_id=team_123]"
- 游戏读取到
--tap_invite_scheme参数后,可调用TapRelation_HandleInviteScheme()接口处理该邀请信息,触发对应事件回调。
发起邀请
调用TapRelation_InviteGame()或TapRelation_InviteTeam(),会激活 TapTap 启动器的“邀请上线”或“邀请组队”窗口,点击“邀请”按钮即可给对方发送邀请消息。
// 邀请好友启动游戏
TapRelation_InviteGame(TapRelation());
// 邀请好友加入指定队伍/房间
TapRelationInviteTeamRequest inviteReq{};
inviteReq.team_id = "team_abc123"; // 必须为 ASCII,且不能包含空格、双引号、换行符等特殊符号
TapRelation_InviteTeam(TapRelation(), &inviteReq);

收到邀请
被邀请方收到邀请时,如果 TapTap 启动器好友聊天窗口处于激活状态,会直接在聊天窗口中显示邀请消息:

如果好友聊天窗口未激活,则会在右下角显示邀请通知:

接受邀请
被邀请方点击邀请消息上的“加入游戏”,或者邀请通知上的“接受”按钮,即可快速加入游戏,甚至进入指定的队伍/房间。
游戏处于运行状态
- 接受邀请时,如果游戏已经处于运行状态,被邀请方的游戏进程会被自动拉回前台,且游戏内会收到对应的事件通知。
注册回调的时机
开发者必须在 TapSDK 初始化成功后,立刻注册TapEventID::RelationGameInviteReceived和TapEventID::RelationTeamInviteReceived的回调函数,以便被邀请方接受邀请时,游戏内能收到对应的通知。
// 接受邀请的通知回调,根据 eventID 区分
void onInviteReceived(TapEventID eventID, void* data)
{
// 两类邀请共用 TapRelationInviteReceivedNotification 结构体
// 注意:data 及其引用的内存在回调返回后会被 SDK 释放,如需长期使用请自行拷贝
auto n = static_cast<TapRelationInviteReceivedNotification*>(data);
switch (eventID) {
case TapEventID::RelationGameInviteReceived:
// 被邀请方接受上线邀请时,游戏内收到的通知
// n->team_id 为 NULL(仅组队邀请才有意义)
cout << "game invitation accepted: inviter_open_id=" << n->open_id
<< ", inviter_union_id=" << n->union_id << endl;
break;
case TapEventID::RelationTeamInviteReceived:
// 被邀请方接受组队邀请时,游戏内收到的通知
cout << "team invitation accepted: inviter_open_id=" << n->open_id
<< ", inviter_union_id=" << n->union_id
<< ", team_id=" << n->team_id << endl;
// 根据 n->team_id 进入对应队伍/房间
break;
default:
break;
}
}
// 接受“邀上线”邀请时,被邀请方游戏内会收到TapEventID::RelationGameInviteReceived事件通知
TapSDK_RegisterCallback(TapEventID::RelationGameInviteReceived, onInviteReceived);
// 接受“邀组队”邀请时,被邀请方游戏内会收到TapEventID::RelationTeamInviteReceived事件通知
TapSDK_RegisterCallback(TapEventID::RelationTeamInviteReceived, onInviteReceived);
游戏尚未启动
- 接受邀请时,如果游戏尚未启动,TapTap 启动器会带命令行参数
--tap_invite_scheme启动游戏。命令行参数示例如下:yourgame.exe --tap_invite_scheme="tds<client_id>://<action>?open_id=xxx&union_id=yyy[&team_id=team_123]" - 命令行参数中的
<action>取值如下:invite_game:邀上线,对应事件TapEventID::RelationGameInviteReceivedinvite_team:邀组队,对应事件TapEventID::RelationTeamInviteReceived
- 游戏需要自行调用
CommandLineToArgvW(GetCommandLineW(), &argc)获取--tap_invite_scheme的值,并将其原封不动地传入TapRelation_HandleInviteScheme(),触发对应的事件通知。- 调用
TapRelation_HandleInviteScheme()前,必须保证已经注册TapEventID::RelationGameInviteReceived和TapEventID::RelationTeamInviteReceived的回调函数,否则无法触发通知。
- 调用
#include <windows.h>
#include <shellapi.h> // CommandLineToArgvW
#include <cwchar>
#include <string>
// 用 CommandLineToArgvW 切分命令行,遍历 argv 找到 --tap_invite_scheme= 的值
std::string ParseInviteSchemeFromCommandLine()
{
int argc = 0;
LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
if (argv == nullptr) {
return {};
}
const std::wstring kPrefix = L"--tap_invite_scheme=";
std::wstring schemeW;
for (int i = 1; i < argc; ++i) {
std::wstring arg = argv[i];
if (arg.rfind(kPrefix, 0) == 0) { // 以 kPrefix 开头
schemeW = arg.substr(kPrefix.size());
break;
}
}
LocalFree(argv);
if (schemeW.empty()) {
return {};
}
// TapRelation_HandleInviteScheme 接受 UTF-8,统一从 UTF-16 转一次
int len = WideCharToMultiByte(CP_UTF8, 0, schemeW.c_str(), -1, nullptr, 0, nullptr, nullptr);
std::string scheme(len > 0 ? len - 1 : 0, '\0');
if (len > 0) {
WideCharToMultiByte(CP_UTF8, 0, schemeW.c_str(), -1, scheme.data(), len, nullptr, nullptr);
}
return scheme;
}
int main()
{
// 这里省略 SDK 初始化和启动校验相关代码,假设已经正确完成
// 1. 必须先注册回调函数,否则下面 HandleInviteScheme 触发的事件会丢失
TapSDK_RegisterCallback(TapEventID::RelationGameInviteReceived, onInviteReceived);
TapSDK_RegisterCallback(TapEventID::RelationTeamInviteReceived, onInviteReceived);
// 2. 解析命令行参数中的 --tap_invite_scheme=...
std::string inviteScheme = ParseInviteSchemeFromCommandLine();
if (!inviteScheme.empty()) {
// 3. 把 scheme 原样交给 SDK,由 SDK 根据 <action> 触发对应事件
auto ret = TapRelation_HandleInviteScheme(TapRelation(), inviteScheme.c_str());
if (ret != TapSDK_Result_OK) {
cout << "TapRelation_HandleInviteScheme failed, ret=" << ret << endl;
}
}
// 4. 进入游戏主循环,处理 SDK 回调
// ...
return 0;
}
无法直接启动游戏的情况
- 如果被邀请方尚未购买/安装游戏,或者游戏有更新,无法直接启动游戏,此时会打开详情页,提醒被邀请方执行相应操作后,再重新点击“加入游戏”。
- 如果是有更新,进入详情页的同时,会自动开始更新。

其他异常
- 如果游戏已启动,但尚未完成 TapSDK 初始化,接受邀请时会提示稍后重试。

- 如果 TapSDK 已初始化,但尚未注册接受邀请的事件通知回调函数,接受邀请的事件会丢失,被邀请方不会看到任何提示。
- 如果游戏进程恰好在接受邀请的同一时刻退出,可能出现邀请信息无法通知给游戏,也不会启动游戏的情况,同时被邀请方也不会看到任何提示。
调试方法
- 接入好友邀请功能,进行调试时,无论本地测试,还是传包测试,都无法串联 TapTap 启动器和游戏程序的完整交互流程。但只要通过以下测试,就不会有问题,正式上线后再回归下即可。
- 下面我们基于游戏已经成功初始化 TapSDK,并已注册
TapEventID::RelationGameInviteReceived和TapEventID::RelationTeamInviteReceived的回调函数这个前提,来说明这些测试案例。
接受邀请时,游戏处于运行状态
- 游戏会收到事件通知
- 如果是本地测试,游戏不会被自动拉回前台。游戏进程必须通过 TapTap 启动器启动,才能被拉回前台。
- 如果是传包测试时,且通过 TapTap 启动游戏,游戏会被拉回前台。
接受邀请时,游戏尚未启动
- 接受邀请时,TapTap 启动器启动的是正式发布的游戏程序,无法启动测试版的游戏程序(无论本地测试或传包测试)。
- 因此,只能通过在命令行中带
--tap_invite_scheme参数启动游戏,模拟接受邀请、启动游戏的场景。比如:yourgame.exe --tap_invite_scheme="tds<client_id>://invite_team?open_id=xxx&union_id=yyy&team_id=team_123" - 如果游戏程序已经正确接入冷启流程,则在游戏启动后,会收到对应的事件通知。