uni.makephonecall仅在app(ios/android)和微信小程序(基础库≥2.10.0)有效;h5端完全不支持,静默失败;小程序推荐用open-type="tel";app需处理权限及号码清洗。

不能只写 uni.makePhoneCall 就完事——H5 端完全不响应,小程序必须用 open-type="tel",App 端还得处理权限拒绝跳转,三端行为完全不同。
uni.makePhoneCall 在哪些平台有效?
这个 API 只在 App(iOS/Android)和微信小程序中生效,H5 端调用后静默失败,既不报错也不弹窗,用户点完毫无反应。微信小程序还要求基础库 ≥ 2.10.0;App 端则依赖系统原生拨号能力,iOS 必须真机测试,模拟器无效。
- H5:彻底不支持,
success/fail回调都不会触发 - 微信小程序:支持,但必须用
<button open-type="tel"></button>或uni.makePhoneCall(推荐前者) - App:支持,但 Android 11+ 需 manifest 勾选「拨打电话」权限,且运行时要检查
scope.callPhone
为什么点了没反应?常见原因和修复
最常踩的坑不是代码写错,而是环境或配置漏掉:
-
<image></image>直接绑@click在部分安卓 WebView 下默认不触发,改用<view><image src=""></image></view> - 号码含空格、横线、括号(如
"400-123-4567"),必须清洗:phoneNumber.replace(/[^0-9]/g, '') - App 端用户拒绝权限后,后续调用直接走
fail,且不会再次弹框——必须提前用uni.getSetting检查authSetting['scope.callPhone'],拒绝时调uni.openSetting() - H5 页面用了
button @click调 JS,实际应改用@#@#@#@#@#@#@#@#@#@0
三端统一调用怎么写?用条件编译最稳
不要试图靠一个函数覆盖所有平台,用 #ifdef 分支处理更清晰可靠:
callPhone(phoneNumber) {
const cleanNumber = phoneNumber.replace(/[^0-9]/g, '');
if (!cleanNumber) return;
// H5
#ifdef H5
window.location.href = `tel:${cleanNumber}`;
#endif
// 微信小程序
#ifdef MP-WEIXIN
uni.makePhoneCall({ phoneNumber: cleanNumber });
#endif
// App
#ifdef APP-PLUS
uni.authorize({
scope: 'scope.callPhone',
success: () => {
uni.makePhoneCall({ phoneNumber: cleanNumber });
},
fail: () => {
uni.openSetting({}).then(() => {
// 用户从设置页返回后可重试
});
}
});
#endif
}
注意:微信小程序里 uni.makePhoneCall 和 <button open-type="tel"></button> 效果一致,但后者无需权限、兼容性更好,适合简单场景。
号码清洗和权限检查不能省略
用户输入或后台返回的号码大概率带格式字符,而 uni.makePhoneCall 对非法字符极其敏感——哪怕开头多一个 +(国际号除外)或结尾多个空格,都会导致静默失败。权限检查也一样,Android 用户第一次拒绝后,uni.authorize 不会再弹窗,必须靠 uni.getSetting 主动判断状态并引导跳转设置页。这两个动作不是“可选优化”,是上线前必须验证的底线逻辑。











