im2-link-jssdk - v1.4.3
    Preparing search index...

    im2-link-jssdk - v1.4.3

    im2-link-jssdk

    im2-link-jssdk 是 H5 小程序与宿主 App/WebView 之间的通信 SDK。Web 侧通过统一 API 请求宿主完成支付 、导航、系统分享、下载、网络请求等原生能力;SDK 负责平台识别、消息封装和回调分发。

    本 README 以当前源码为准:公开方法、参数类型、消息类型和回调协议均与 src/index.ts、src/types/common.ts 保持一致。

    以上地址指向 npm 当前已发布版本的类型文档。仓库中的最新改动会在下次发布后同步到这两个地址。

    npm install im2-link-jssdk
    

    SDK 同时提供 ESM、CommonJS 和 TypeScript 类型声明。

    import IMSDK from 'im2-link-jssdk';

    const sdk = new IMSDK({
    id: 'your-app-id',
    token: 'your-app-token',
    debug: false
    });

    sdk.share({
    type: 'system',
    param: {
    title: '分享标题',
    text: '分享描述',
    shareUrl: 'https://example.com?share_source=tg',
    imageUrl: 'https://example.com/share.png'
    }
    });

    初始化参数:

    参数 类型 必填 说明
    id string 是 小程序 App ID
    token string 是 小程序 App Token
    debug boolean 否 是否打印 SDK 调试日志,默认 false
    • 使用 Webpack、Rspack 或其他可输出浏览器资源的构建工具。
    • 使用 Hash 路由,路由状态由 window.location.hash 承载。
    • 构建入口文件命名为 index.html。
    • 发布时将构建产物打包为 ZIP。
    • SDK 依赖浏览器的 window 和 navigator,不要在 SSR 服务端执行初始化。
    API 宿主消息类型 用途
    platform - 获取当前运行平台
    callPayment payment 拉起原生支付
    callBack back 通知宿主返回
    callConversation conversation 打开指定用户会话
    callNavigate navigate 调用宿主导航
    permissions permissions 请求宿主权限能力
    callOpenMiniProgram openminiapp 打开其他小程序
    callSetBarColor barcolor 设置状态栏颜色
    callPopup popup 拉起原生弹框
    requestApi requireAPI 由宿主发起网络请求
    requestApp requireAPP 与宿主交换业务数据
    adjustInputBoxHeight inputBoxHeight 调整输入框高度
    switchLandscape landscape 切换横屏状态
    share share 业务分享或系统分享
    download download 请求宿主下载视频
    behaviorCaptcha behaviorCaptcha 发送行为验证码结果
    getCaptchaAccount captchaAccount 索取登录页账号与区号
    vibrate vibrate 触发宿主系统振动
    const platform = sdk.platform;
    

    返回值为:

    type Platform = 'win' | 'mac' | 'unix' | 'linux' | 'android' | 'ios' | 'unknown';
    
    import { IMChainCurrencyEnum } from 'im2-link-jssdk';

    sdk.callPayment(
    {
    amount: '99.00',
    consumeType: 'goods',
    chainCurrencyType: IMChainCurrencyEnum.CNY,
    productOrderNo: 'ORDER-20260828-001',
    productName: '商品名称',
    quantity: '1'
    },
    (isSuccess) => {
    console.log('支付是否成功:', isSuccess);
    }
    );

    chainCurrencyType 可选值:CNY = 1、KKC = 2、VNC = 3。

    支付参数可以省略;省略时表示只校验支付密码:

    sdk.callPayment(undefined, (isSuccess) => {
    console.log('支付密码校验结果:', isSuccess);
    });

    当初始化的 id 不等于字符串 '0' 时,SDK 会先校验 App ID 和 App Token,再向宿主发送支付消息。校验 失败只会输出 callPayment error,不会继续拉起支付。

    callPayment 是当前唯一返回 Promise<void> 的公开方法。等待该 Promise 只表示前置校验和消息发送结束 ,支付最终结果仍以回调为准。

    sdk.callBack(() => {
    console.log('宿主已处理返回');
    });
    sdk.callConversation('target-user-open-id', () => {
    console.log('宿主已处理会话请求');
    });
    sdk.callNavigate(
    {
    actionType: 'external',
    params: {
    route: 'https://example.com'
    }
    },
    () => {
    console.log('宿主已处理导航请求');
    }
    );

    当前约定的 actionType 包括:

    值 用途
    home 首页
    channel 超级群,params 中传 channelId
    trad 交易页面
    inner 内部链接,params 中传 route
    external 外部链接,params 中传 route
    invite 邀请页面
    share 系统分享入口
    shortVideoSearch 短视频搜索
    customerService 客服页面

    actionType 在当前类型定义中是 string,表格列出的是宿主已约定的业务值。

    sdk.permissions(
    {
    actionType: 'camera'
    },
    (result) => {
    console.log('权限结果:', result);
    }
    );

    params 当前使用 IMNavigateParams 结构,实际 actionType 及返回数据由宿主约定。

    sdk.callOpenMiniProgram(
    'miniapp://target-app',
    {
    source: 'current-app',
    scene: 'detail'
    },
    () => {
    console.log('宿主已处理打开请求');
    }
    );

    第二个参数为可选的透传对象。若不需要透传参数,可传 undefined:

    sdk.callOpenMiniProgram('miniapp://target-app', undefined, () => {
    console.log('宿主已处理打开请求');
    });
    sdk.callSetBarColor(
    {
    titleColor: '#FFFFFF',
    backgroundColor: '#1677FF'
    },
    () => {
    console.log('颜色设置完成');
    }
    );

    titleColor 和 backgroundColor 均为可选字符串,颜色格式由宿主解析。

    sdk.callPopup(
    {
    url: 'https://example.com/popup',
    ratio: 0.75,
    popupType: 2
    },
    () => {
    console.log('弹框已处理');
    }
    );

    popupType:

    值 展示方式
    1 带标题栏
    2 居中弹出
    3 从底部向上覆盖
    interface UserProfile {
    id: string;
    nickname: string;
    }

    sdk.requestApi<UserProfile>(
    {
    type: 'core',
    url: '/v1/user/profile',
    method: 'GET',
    param: {
    userId: '10001'
    }
    },
    (data) => {
    console.log(data.nickname);
    }
    );

    参数说明:

    参数 类型 必填 说明
    type 'core' | 'wallet' 否 请求服务类型,默认 'core'
    url string 是 请求地址
    method string 是 请求方法,例如 GET、POST
    param Record<string, any> 否 请求参数
    sdk.requestApp<{ url: string }>(
    {
    method: 'h5-register',
    param: {
    locale: 'zh-CN'
    }
    },
    (data) => {
    console.log('注册页面:', data.url);
    }
    );

    method 和 param 由 Web 与宿主共同约定;当前已记录的方法为 h5-register。

    sdk.adjustInputBoxHeight(320, (result) => {
    console.log('调整结果:', result);
    });

    高度单位和结果数据由宿主约定。

    sdk.switchLandscape(true, (result) => {
    console.log('切换结果:', result);
    });

    第一个参数默认值为 true;传 false 表示取消横屏。

    share 通过 type 区分短视频、棋牌游戏和系统分享。

    sdk.share(
    {
    type: 'shortVideo',
    param: {
    cover_url: 'https://example.com/cover.jpg',
    description: '视频描述',
    title: '视频标题',
    user_id: '10001',
    video_id: 'video-001'
    }
    },
    (result) => {
    console.log('分享结果:', result);
    }
    );
    sdk.share(
    {
    type: 'cardGame',
    param: {
    show_type: 3,
    game_path: '/room/10001',
    game_preview_width: 375,
    game_preview_height: 667,
    game_preview_url: 'https://example.com/game-preview',
    currencySource: 'CNY',
    subGameName: {
    ch: '游戏名称',
    en: 'Game name'
    }
    }
    },
    (result) => {
    console.log('分享结果:', result);
    }
    );

    show_type 的含义:0 为默认旧样式,1 为不带链接的棋牌游戏样式,2 为带链接的棋牌游戏样式,3 为游戏预览。

    sdk.share({
    type: 'system',
    param: {
    title: '分享标题',
    text: '分享描述',
    shareUrl: 'https://example.com?share_source=tg',
    imageUrl: 'https://example.com/share.png'
    }
    });

    所有字段均为必填字符串:

    字段 说明
    title 分享标题
    text 分享描述
    shareUrl 分享链接;游戏分享来源参数 share_source=tg 拼在此链接中
    imageUrl 分享图片 URL;宿主下载图片后用于图文分享

    宿主收到的消息如下:

    {
    "type": "share",
    "params": {
    "type": "system",
    "param": {
    "title": "分享标题",
    "text": "分享描述",
    "shareUrl": "https://example.com?share_source=tg",
    "imageUrl": "https://example.com/share.png"
    }
    },
    "appid": "your-app-id",
    "apptoken": "your-app-token"
    }

    系统分享与其他 share 类型一样,可以传入可选回调。

    sdk.download(
    {
    fileType: 'video',
    url: 'https://example.com/video.mp4'
    },
    (result) => {
    console.log('下载结果:', result);
    }
    );

    当前 fileType 仅支持 'video'。

    sdk.behaviorCaptcha(
    {
    token: 'captcha-result-token'
    },
    () => {
    console.log('验证码结果已发送给宿主');
    }
    );

    此 API 用于 H5 完成滑动验证后,将验证码 token 透传给宿主。

    验证码 token 获取失败时,也可沿用同一通道透传上游业务响应;SDK 不解析业务码或文案:

    sdk.behaviorCaptcha({
    code: 1038,
    msg: '由业务服务返回的提示',
    data: {}
    });

    成功结果仍保持 { token },以兼容既有 App。宿主可通过是否存在 params.token 区分成功与业务失败。

    H5 通过 vibrate 通知宿主调用设备系统振动 / 触觉反馈。未传参数时按短振动处理。

    // 默认短振动
    sdk.vibrate();

    // 短振动,指定强度
    sdk.vibrate({ type: 'short', style: 'heavy' });

    // 长振动
    sdk.vibrate({ type: 'long' }, (isSuccess) => {
    console.log('振动是否已触发:', isSuccess);
    });

    // 指定时长(毫秒),宿主按系统能力执行
    sdk.vibrate({ duration: 200 });

    参数说明:

    参数 类型 必填 说明
    type 'short' | 'long' 否 振动类型,默认 'short'
    style 'light' | 'medium' | 'heavy' 否 短振动强度,仅 type 为 'short' 时生效
    duration number 否 振动时长(毫秒)。与 type 同时存在时,宿主优先按 duration 执行

    宿主收到的消息如下:

    {
    "type": "vibrate",
    "params": {
    "type": "short",
    "style": "heavy"
    },
    "appid": "your-app-id",
    "apptoken": "your-app-token"
    }

    iOS 建议将 short + style 映射为 UIImpactFeedbackGenerator,long 映射为系统振动;Android 建议使用 VibrationEffect。桌面端和无振动能力的设备可直接回 isSuccess: 0。

    本节供 iOS、Android、桌面端和 H5 容器开发者实现消息桥接。

    API Web 侧收到的回调值
    requestApi、requestApp 宿主返回的业务数据
    permissions 宿主返回的权限数据
    其他带回调的 API isSuccess === 1 时为 true,否则为 false

    部分历史 API 的 TypeScript 回调签名为 () => void,调用方可以只把它当作完成通知;SDK 运行时仍会传入 上述布尔结果。

    interface SDKMessage {
    type: MessageTypeEnum;
    params?: unknown;
    callback?: string;
    appid: string;
    apptoken: string;
    }
    • type:原生能力标识,见“API 概览”。
    • params:对应 API 的业务参数。
    • callback:调用方传入回调时由 SDK 生成;无回调时不发送该字段。
    • appid、apptoken:初始化 SDK 时传入的身份信息。
    环境 SDK 调用的宿主通道 消息形式
    iOS window.webkit.messageHandlers.JSParent.postMessage(message) 对象
    Android window.JSParent.postMessage(JSON.stringify(message)) JSON 字符串
    Windows / Unix / Linux window.miniJSParent.postMessage(message) 对象
    macOS 优先使用 webkit.messageHandlers.JSParent,否则使用 miniJSParent 对象
    H5 iframe window.parent.postMessage(message, '*') 对象

    消息带有 callback 时,原生宿主处理完成后应调用对应的全局回调:

    // 普通原生能力:payment、navigate、share 等
    window.IMCallBack[callback](
    JSON.stringify({
    isSuccess: 1,
    callback
    })
    );

    // requestApi、requestApp
    window.receiveData[callback](JSON.stringify(responseData));

    // permissions
    window.permissions[callback](JSON.stringify(permissionData));

    IMCallBack 中 isSuccess 为 1 时,Web 回调接收 true;其他值接收 false。receiveData 和 permissions 的数据会先经过安全 JSON 解析,以避免大整数精度丢失。

    父页面通过 postMessage 返回:

    iframeWindow.postMessage(
    {
    type: 'IMCallBack',
    callback: message.callback,
    data: {
    isSuccess: 1
    }
    },
    '*'
    );

    type 与调用类型的对应关系:

    SDK 调用 回调 type
    requestApi、requestApp receiveData
    permissions permissions
    其他带回调的 API IMCallBack

    H5 宿主需要在父级 window 上注入:

    window['h5-app-version'] = '宿主版本号';
    

    跨域 iframe 无法读取父页面字段时,SDK 会按 H5 容器处理。SDK 只接收 event.source === window.parent 的标准浏览器消息;source === null 的回包会被拒绝,网页宿主应通过 IMSDK.web.createHost 绑定真实 iframe WindowProxy。

    • 回调被调用后会立即从全局回调表中删除。
    • requestApi 回调在 30 秒后仍未收到响应时会被清理。
    • 其他 API 回调在 10 分钟后仍未收到响应时会被清理。
    • 当前清理行为不会主动调用 Web 侧回调,也不会生成超时错误。

    SDK 面向 App WebView 和宿主 iframe。在普通浏览器顶层页面中,如果不存在原生桥且未注入 h5-app-version,调用不会发送给宿主;传入回调时,SDK 会以 undefined 调用该回调。

    除默认导出的 IMSDK 外,包还导出:

    • 类型与枚举 :MessageTypeEnum、IMSDKConfig、IMPaymentParams、IMNavigateParams、IMRequestParams、IMRequestAppParams、IMPopupParams、IMShareParams、IMSystemShareParams、IMDownLoadParams、IMBehaviorCaptchaParams、IMVibrateParams、IMChainCurrencyEnum 等。
    • 工具:safeJSONParse、uuidv4、getOS、Md5。

    大整数 JSON 解析示例:

    import { safeJSONParse } from 'im2-link-jssdk';

    const data = safeJSONParse('[123456789123456789123456789, 2.3]');
    // 超出 JavaScript 安全整数范围的数字以字符串形式保留
    npm install
    npm run build
    npm run doc
    • npm run build:生成 ESM、CommonJS 和类型声明到 dist/。
    • npm run doc:根据源码类型和注释生成 TypeDoc 到 docs/。
    • 项目要求 Node.js >= 22.0.0。

    发布流程见 PUBLISH.md。

    网页容器可以直接使用 IMSDK.web.createHost(也可 import { web }),不需要创建游戏端 SDK 实例或传入 app token。该入口没有自动监听副作用,也不会改动 iOS/Android/PC 的原生桥。

    import IMSDK from 'im2-link-jssdk';

    const host = IMSDK.web.createHost({
    getTarget: () => iframe.contentWindow ? {
    source: iframe.contentWindow,
    origin: new URL(iframe.src).origin,
    key: `${currentAccountId}:${currentAppId}:${iframe.src}`
    } : null,
    onMessage: async (request) => {
    if (request.message.type !== 'share') return;
    // params 为 { type: 'cardGame', param: { show_type, game_path, ... } }。
    // 宿主必须校验 message.appid 与当前 iframe 的可信应用资料,然后让用户选会话。
    const accepted = await selectAndShare(request.message.params, request.signal);
    request.reply('IMCallBack', { isSuccess: accepted ? 1 : 0 });
    }
    });
    host.listen();
    // iframe 关闭/重新加载、切账号和卸载时:
    host.stop();
    • getTarget 必须来自宿主 iframe,不得用收到的 event.origin 或消息里的 appid 生成信任规则。origin 必须精确匹配,禁止 *。显式绑定 origin: 'null' 才接受 opaque iframe,此时回包使用浏览器要求的 *,仍严格绑定 WindowProxy。
    • key 标识当前应用/账号/页面。异步工作前使用 request.isCurrent();重新加载同一地址时也应 stop() 后 listen(),中止旧业务。监听只校验窗口来源,不代替宿主的 app token/权限验证。
    • reply('IMCallBack' | 'receiveData' | 'permissions', data) 自动带上原 callback,只能回复一次。停止或目标变化后的回复返回 false。业务回调 share(params, cb) 继续收到 boolean,不改变旧 API。
    • onMessage 的 Promise 拒绝时回 {isSuccess:0,error:'HOST_ERROR'};可用 onError 接入宿主诊断,不应输出完整请求凭据。不支持的业务应由宿主明确回失败。
    • 默认只分发 SDK 已声明消息类型,额外旧游戏事件通过 additionalMessageTypes 注册;normalizeMessage 只用于拆开宿主已有扩展包装,执行前已经校验 source/origin。
    • 已有事件循环可调用 handleMessage(event);不要同时再把同一事件交给自己的业务处理器。web.parseMessage(value) 只做对象/JSON 结构解析,不做来源或权限验证。
    • 同源与跨域 iframe 都支持网页通信,不要求父网页注入 h5-app-version。原生环境仍优先现有原生桥。没有原生桥、没有标记的顶层独立页仍不冒充宿主。

    H5 游戏分享宿主将 isSuccess:1 定义为用户确认后,所有选中目标均被 IM 发送 API 接受;这不代表送达/已读。取消、忙碌、不可用及部分失败回 0,原始响应附带 status/sent/failed。iOS 现有分享没有实现结果回包,不应把“已弹出选择器”写为它的成功合同。