找到已经在用应用的好友
把标准化后的电话号码与后端中的账号进行比对,显示“您有 3 位联系人在这里”,而不是一个空空的好友列表。
Replit + 通讯录
“查找好友”页面、群组邀请和 AA 分账应用常常需要访问通讯录。在 WebViewGold 应用中,您的 Replit 应用通过 requestcontactpermission:// 请求权限,并在调用 readcontacts:// 后从 contacts 变量中以 JSON 形式获得姓名和电话号码。代码几分钟就能写好;能否通过审核,取决于您如何使用这些数据。
每个平台一次性 $109 起,或由我们的团队全程代劳,$698 起。
把标准化后的电话号码与后端中的账号进行比对,显示“您有 3 位联系人在这里”,而不是一个空空的好友列表。
用户选择一位联系人,应用准备一条个人邀请并打开分享面板。不群发邀请,也不会让收件人感到意外。
CRM、预约和团队类应用可以用选中的联系人预填新记录,省去用户重新输入姓名和号码的麻烦。
通过原生分享面板(shareapp://)发送普通邀请链接完全不需要权限,也更容易通过审核。只有当匹配或挑选联系人能带来真正的价值时,才请求通讯录权限。
把这段粘贴到 Replit 中以实现 Web 应用端。检查结果,发布,然后在 WebViewGold 应用中测试。
为 WebViewGold 原生应用封装添加“从通讯录邀请或查找好友”功能。1) 前端:在说明页面之后,仅当 navigator.userAgent 包含 WebViewGold 时跳转到 requestcontactpermission://;“显示联系人”按钮设置 window.contacts = undefined,跳转到 readcontacts://,并每 100 ms 轮询一次 window.contacts,最多 5 秒;null 表示没有权限。2) 显示一个可搜索的姓名列表及其号码,不预选任何人,不提供“全选”。3) 后端:添加 POST /api/contacts/match:要求用户已登录,用 libphonenumber-js 把最多 2000 个号码标准化为 E.164 格式,与 users.phone 比对,返回匹配到的用户 id 和姓名,绝不记录或存储输入;按用户限流。4) 每位联系人都有一个“邀请”按钮,打开 shareapp://message?=TEXT&url=APP_URL/join?ref=CODE。5) 如果缺少权限,提供 settingsapp:// 和普通邀请链接。

在过去5年我们尝试过的所有应用平台中,WebViewGold为我们带来了有史以来最短、最高效的上市时间。我不知道为什么没有更早发现你们,但我真的非常满意。目前我们的应用在iOS App Store和Google Play商店的下载量已超过6000次,没有任何问题!
代码一小时,隐私文案再多花一点时间。
Android:按照 WebViewGold 文档的要求,在 AndroidManifest.xml 中添加 android.permission.READ_CONTACTS。iOS:Info.plist 中的通讯录用途说明必须写明原因,例如“用于显示您的哪些联系人已经在使用本应用”。
先显示您自己的说明页面,介绍好处并提供一个“继续”按钮,然后再导航到 requestcontactpermission://。绝不要在首次启动时或用户进入该功能之前请求权限。
获得权限后,导航到 readcontacts://。WebViewGold 会用一个包含姓名和电话号码数组的对象填充全局变量 contacts;没有权限时它为 null。
显示一个可搜索的列表,不预先选中任何人,也不提供“全选”按钮,并在发送任何内容之前展示确切的邀请文字。
用于好友匹配时,把号码标准化后发送到后端做一次性比对;不要保留未匹配的号码。用于邀请时,什么都不用发送:直接打开分享面板。
两次独立的点击:一次用于授权,一次用于加载列表。contacts 变量是异步到达的。如果需要好友匹配,请只为已登录用户在服务端执行;在您的 Replit 项目中,这意味着:Express/Flask/FastAPI 后端,搭配 Replit Postgres 或外部数据库。
var IN_APP = navigator.userAgent.indexOf("WebViewGold") !== -1; // 您的自定义 User-Agent 标识
function waitFor(name, timeoutMs, done) {
var start = Date.now();
(function check() {
if (typeof window[name] !== "undefined") { done(window[name]); }
else if (Date.now() - start < timeoutMs) { setTimeout(check, 100); }
else { done(undefined); }
})();
}
// 第 1 次点击:在您自己的说明页面之后
function askForContacts() {
if (!IN_APP) { showInviteLink(); return; }
window.location.href = "requestcontactpermission://";
}
// 第 2 次点击:“显示我的联系人”
function loadContacts() {
window.contacts = undefined;
window.location.href = "readcontacts://";
waitFor("contacts", 5000, function (list) {
if (!list) { showPermissionHint(); return; } // null = 没有权限
// 结构:{ "John Appleseed": ["888-555-5512", "888-555-1212"], ... }
var people = Object.keys(list).map(function (n) { return { name: n, phones: list[n] }; });
renderPicker(people); // 不预选任何人,不提供“全选”
});
}
// 之前拒绝过?让用户在设置中更改
function openAppSettings() { window.location.href = "settingsapp://"; }一个以联系人姓名为键的 JSON 对象,每个键对应一个电话号码数组,存放在全局变量 contacts 中。没有权限时该变量为 null。电子邮件地址、通讯地址和照片不在文档规定的格式之内。
不会因为读取本身被拒,但常常会因为读取的方式被拒。请在具体情境中、配合清晰的用途说明请求权限,让用户逐个选择联系人,绝不一次邀请所有人;除非功能确实需要且隐私政策中有说明,否则不要把通讯录保存在服务器上。
通常不需要。带个人邀请链接的分享面板无需任何权限就能触达 WhatsApp、“信息”和电子邮件,在审核中也容易解释得多。只有在匹配好友或从现有联系人创建群组时,才使用通讯录访问。
那么 readcontacts:// 会让 contacts 变量保持为 null。请改为提供邀请链接;如果用户之后改变主意,用 settingsapp:// 打开应用设置,让他们授予权限。
结果相同,只是您需要投入的工作量不同。三种方式都附带审核通过保证和 7×24 小时人工支持。
$109 每个平台,一次性付费
WebViewGold 许可证:一个现成的 Xcode 或 Android Studio 项目。粘贴您的 URL,设置名称和图标,开启所需功能,构建并提交。永久免费更新。
在主页查看方案$349 每个许可证,一次性附加购买
无需 Mac、Xcode 或 Android Studio:在浏览器中完成配置,我们在云端构建两个应用,并将其交付到 App Store Connect 和 Play Console。
Cloud Builder 如何运作 试用免费演示$698 每个平台 $798
把您的 URL 和图标发给我们。我们的团队在 72 小时内完成配置、构建并交付您的应用,白标,附源码项目。两个平台共 $1,158。
Full Service 详情 服务提供方:冬季特惠价格有效期至 2026年12月31日。
App Store & Google Play 审核通过保证 – 否则 14 天内退款
想直接交给我们?Full Service:我们在 72 小时内完成配置、构建并交付,每个平台 $698 起。有疑问?通过 7×24 小时在线聊天联系我们。
退款依据我们 FAQ 中列出的条件:应用因非内容原因被 Apple 和/或 Google 拒审,并在购买后 14 天内提出申请。