- 小程序登录、用户信息相关接口调整说明
公告更新时间:2021年04月15日考虑到近期开发者对小程序登录、用户信息相关接口调整的相关反馈,为优化开发者调整接口的体验,回收wx.getUserInfo接口可获取用户授权的个人信息能力的截止时间由2021年4月13日调整至2021年4月28日24时。为优化用户的使用体验,平台将进行以下调整: 2021年2月23日起,若小程序已在微信开放平台进行绑定,则通过wx.login接口获取的登录凭证可直接换取unionID2021年4月28日24时后发布的小程序新版本,无法通过wx.getUserInfo与<button open-type="getUserInfo"/>获取用户个人信息(头像、昵称、性别与地区),将直接获取匿名数据(包括userInfo与encryptedData中的用户个人信息),获取加密后的openID与unionID数据的能力不做调整。此前发布的小程序版本不受影响,但如果要进行版本更新则需要进行适配。新增getUserProfile接口(基础库2.10.4版本开始支持),可获取用户头像、昵称、性别及地区信息,开发者每次通过该接口获取用户个人信息均需用户确认。具体接口文档:《getUserProfile接口文档》由于getUserProfile接口从2.10.4版本基础库开始支持(覆盖微信7.0.9以上版本),考虑到开发者在低版本中有获取用户头像昵称的诉求,对于未支持getUserProfile的情况下,开发者可继续使用getUserInfo能力。开发者可参考getUserProfile接口文档中的示例代码进行适配。请使用了wx.getUserInfo接口或<button open-type="getUserInfo"/>的开发者尽快适配。开发者工具1.05.2103022版本开始支持getUserProfile接口调试,开发者可下载该版本进行改造。 小游戏不受本次调整影响。 一、调整背景很多开发者在打开小程序时就通过组件方式唤起getUserInfo弹窗,如果用户点击拒绝,无法使用小程序,这种做法打断了用户正常使用小程序的流程,同时也不利于小程序获取新用户。 二、调整说明通过wx.login接口获取的登录凭证可直接换取unionID 若小程序已在微信开放平台进行绑定,原wx.login接口获取的登录凭证若需换取unionID需满足以下条件: 如果开发者帐号下存在同主体的公众号,并且该用户已经关注了该公众号如果开发者帐号下存在同主体的公众号或移动应用,并且该用户已经授权登录过该公众号或移动应用2月23日后,开发者调用wx.login获取的登录凭证可以直接换取unionID,无需满足以上条件。 回收wx.getUserInfo接口可获取用户个人信息能力 4月28日24时后发布的新版本小程序,开发者调用wx.getUserInfo或<button open-type="getUserInfo"/>将不再弹出弹窗,直接返回匿名的用户个人信息,获取加密后的openID、unionID数据的能力不做调整。 具体变化如下表: [图片] 即wx.getUserInfo接口的返回参数不变,但开发者获取的userInfo为匿名信息。 [图片] 此外,针对scope.userInfo将做如下调整: 若开发者调用wx.authorize接口请求scope.userInfo授权,用户侧不会触发授权弹框,直接返回授权成功若开发者调用wx.getSetting接口请求用户的授权状态,会直接读取到scope.userInfo为true新增getUserProfile接口 若开发者需要获取用户的个人信息(头像、昵称、性别与地区),可以通过wx.getUserProfile接口进行获取,该接口从基础库2.10.4版本开始支持,该接口只返回用户个人信息,不包含用户身份标识符。该接口中desc属性(声明获取用户个人信息后的用途)后续会展示在弹窗中,请开发者谨慎填写。开发者每次通过该接口获取用户个人信息均需用户确认,请开发者妥善保管用户快速填写的头像昵称,避免重复弹窗。 插件用户信息功能页 插件申请获取用户头像昵称与用户身份标识符仍保留功能页的形式,不作调整。用户在用户信息功能页中授权之后,插件就可以直接调用 wx.login 和 wx.getUserInfo 。 三、最佳实践调整后,开发者如需获取用户身份标识符只需要调用wx.login接口即可。 开发者若需要在界面中展示用户的头像昵称信息,可以通过<open-data>组件进行渲染,该组件无需用户确认,可以在界面中直接展示。 在部分场景(如社交类小程序)中,开发者需要在获取用户的头像昵称信息,可调用wx.getUserProfile接口,开发者每次通过该接口均需用户确认,请开发者妥善处理调用接口的时机,避免过度弹出弹窗骚扰用户。 微信团队 2021年4月15日
2021-04-15 - 手机号解密失败?扫盲帖+解决方案
一、之前的解密流程,会偶现“解密失败”,步骤如下: 1、点击 ‘getPhoneNumber’ 的按钮,弹出授权界面 2、调用 wx.checkSession 进行检查,success 的话就发送授权手机号解密接口;fail 的话就进行 wx.login 获取 code 后请求后端获取 openid/sessionKey,并将两个值缓存到本地,然后再进行手机号解密。 二、粗暴方式解密流程,会偶现“解密失败”,步骤如下: 1、点击 ‘getPhoneNumber’ 的按钮,弹出授权界面 2、调用 wx.login 获取 code 后请求后端获取 openid/sessionKey,然后进行手机号解密 探讨微信解密机制(个人理解,如有不对,请指出哟),如下: 1、点击 ‘getPhoneNumber’ 的按钮,弹出授权界面时,在微信后台会将数据进行加密,此时用于加密的 sessionKey-0 是微信后台已存的 sessionKey,这个 sessionKey 有可能是之前其他业务生成的,比如 wx.login(会刷新微信后台的 sessionKey)。 [图片] 2、按照如上错误的步骤,进行 wx.login 获取 code 再获取 sessionKey-1,由于 wx.login 会刷新微信后台的登录状态,此时新生成的 sessionKey-1 和上一步中用于加密的 sessionKey-0 不是同一个,于是解密失败了。 3、重点:必须保持操作前后的 sessionKey 都是同一个,如果 wx.login 刷新了后台的 sessionKey,而之前的操作还是原来的 sessionKey,则会失败。 必现方式一(解密失败),如下: 1、正常授权解密后,关闭小程序一段时间,测试的时候大概 30-40 分钟左右,后台 sessionKey 过期了 2、重新打开小程序走之前的步骤,出现“解密失败”,然后第二次进行授权解密时,又成功了 必现方式二(解密失败),如下: 1、清理缓存后,点击授权登录(此时后台的sessionKey为空,所以无论怎么做登录和检查,都会解密失败),弹出界面后调用 wx.login 进行登录获取 sessionKey 2、授权解密,失败 3、再次点击授权登录(此时会获取第一步中登录生成的 sessionKey,与未过期的sessionKey一致),则进行解密,成功。 解决方案,如下: 基于对上面机制的理解,wx.login 方式获取的 sessionKey 必须在唤起授权弹窗前进行,必须保证授权弹窗时获取的 sessionKey 和 本地未过期的sessionKey是同一个。 1、在 app.js 的 onLaunch 中,先进行 wx.checkSession。success,则进行后续代码执行;如果 fail,则进行 wx.login 重新获取 sessionKey,后端同学将 sessionKey 存储至数据库,openid 是唯一的,可以作为主键。此时,会先于任何操作之前生成一个 sessionKey。 2、唤起授权界面,点击“允许”后,将 openid+iv+encryptedData 传给后端进行解密。 代码如下(IDE复制后没发改样式,const 等变量可能看不清,可以复制到自己的编辑器中查看哈): 然后在 onLaunch 中调用 onLogin.checkSession 进行前置 session 检查和获取 export const onLogin = { // 检查 session 是否有效 checkSession(cb = () => {}) { const _this = this; // 检查登录态是否可用 wx.checkSession({ success () { console.log('session success'); // session_key 未过期,并且在本生命周期一直有效 const { openid, session_key } = wx.getStorageSync('session'); cb(openid, session_key); }, // 登录态失效了 fail () { console.log('session fail'); _this._wxLogin((openid, session_key) => { cb(openid, session_key); }); } }); }, // 微信获取 code 进行解密 _wxLogin(cb = () => {}) { // 将 js_code 发送给后端获取 openId 和 sessionKey,并进行缓存 wx.showLoading({ mask: true }); wx.login({ success: ({ code }) => { // 将 js_code 发送给后端获取 openId 和 sessionKey,并进行缓存 request({ url: `/wx/open/getSessionKey.json?code=${code}&clientIdentity=${CONFIG.clientIdentity}`, onSuccess: ({ openid, session_key }) => { wx.setStorageSync('session', { openid, session_key }); cb(openid, session_key); }, complete: () => { wx.hideLoading(); } }) } }); }, }
2020-11-05 - 地理位置接口新增与相关流程调整
一、地理位置接口新增说明 由于精确地理位置接口只允许部分类目的小程序申请使用,为了满足开发者在更多场景使用地理位置接口,自 2022 年 7 月 14 日起,新增获取模糊地理位置接口(wx.getFuzzyLocation)。同时为保障用户合法权益,该接口调用前需进行准入开通申请,该接口准入规则与 wx.chooseLocation 一致。 wx.getFuzzyLocation 接口说明: 1、该接口返回的是经过模糊处理的经纬度坐标; 2、该接口支持返回 wgs84 或 gcj02 两种类型的坐标; 3、该接口需要用户授权 scope.userFuzzyLocation。 二、app.json 的配置指引 为了开发者能够正常使用获取模糊地理位置等接口,以及后续对于代码提审环节的优化(见「三、地理位置接口使用流程」),自 2022 年 7 月 14 日起,开发者在使用地理位置相关接口时(共计 8 个,见表1),需要提前在 app.json 中进行配置。 1、需配置的接口列表 [图片] 表1 2、配置规则 1)在代码中使用的地理位置相关接口(共计 8 个,见表1),开发者均需要在 app.json 中 requiredPrivateInfos 配置项中声明,代码格式如下: [图片] 2)表1中模糊位置信息(序号1)和精确位置信息(序号2-5)是互斥的,即声明了模糊位置信息就无法声明精确位置信息。若同时声明模糊位置信息和精确位置信息,则在编译代码时出现错误; 3)注意:自 2022 年 7 月 14 日后发布的小程序,如果未在 app.json 中声明表1中的相关接口,则小程序调用这些接口(表1)时会出现错误,在 2022 年 7 月 14 日之前发布的小程序不受影响; 4)对于第三方开发者,需要在上传代码时通过参数在 ext.json 中声明其需调用的地理位置相关接口,配置规则和普通小程序的配置规则相同。 三、地理位置接口使用流程 自 2022 年 7 月 14 日起,开发者如需在最新版本发布后使用地理位置相关接口,除需完成接口权限开通外,还需在 app.json(或ext.json)配置环节,具体如下: 1、接口权限开通 以下 8 个接口需完成准入开通流程:wx.getFuzzylocation、wx.getLocation、wx.onLocationChange、wx.chooseAddress、wx.choosePoi、wx.chooseLocation、wx.startLocationUpdate、wx.startLocationUpdateBackground 1)普通开发者:需要在 “小程序管理后台 -「开发」-「开发管理」-「接口设置」” 中完成权限申请; 2)第三方开发者:可通过 apply_privacy_interface 接口完成权限申请。 2、app.json(或 ext.json)配置 1)普通开发者:需在 app.json 中声明其需调用的地理位置相关接口,具体配置流程见「二、app.json 的配置指引」; 2)第三方开发者:需要在上传代码时通过参数在 ext.json 中声明其需调用的地理位置相关接口(配置方式:可通过 commit 接口配置)。 同时,为了提升开发者体验,平台在代码提审环节会协助开发者对地理位置接口进行检测,如检测出代码中包含未完成准入开通的地理位置接口,平台将再次提醒开发者确认是否需使用相关接口。 1)普通开发者:若无需使用,开发者可在提审时确认不使用该接口,即可正常进行代码提审。小程序审核通过且新版本发布完成后,平台将对小程序确认不使用的接口关闭使用权限; 2)第三方开发者:若无需使用,可在提审时通过参数声明不使用该接口(声明方式:可通过 submit_audit 接口配置),即可正常进行代码提审,审核通过后发布上线,将对其声明不使用的接口关闭使用权限。 以上调整将仅对所有小程序生效。 微信团队 2022年6月1日
2023-09-26 - 微信小程序自定义tarbra的坑,动态适配iphoneX iphone11 带安全区域的手机
微信小程序虽然开放了自定义的tabbar 因为他用的是fixed定位布局 导致每个tabbar页都要去动态计算padding-bottom 或者bottom值,之前尝试过 wx.getSystemInfo({ success: function(res) { console.log(res) if (res.model.search('iPhone X') != -1) { that.globalData.isIphoneX = true } }, }) 在app.js中判断是不是iphone X ok这个时候是完美适配的 但是有一天测试同学拿着iphone 11 pro max找我 说页面的padding-bottom值会盖住,在我的排查中发现res.model.search('iPhone X') != -1 这句代码拿到的结果为-1 我之前是这么处理的 我判断机型为iphonex的时候 tabbar 页面的padding-bottom为100rpx+64rpx 但是iphone 11pro 系列手机在这个判断中无效 经过排查并反复改 终于拿到了完美适配的方案!!!!我们只需要在外层的view padding-bottom: calc(100rpx + env(safe-area-inset-bottom))就好了 有需要的同学点个关注吧!!! 对了 再次说明下 custom-tab-bar.wxss 中.tar-bar里的height我自己改成了100rpx 微信官方的是50px
2020-03-19 - video全屏状态下切换为非全屏后出现了滚动条,还可以滚动?
RT,非全屏下是正常的。只要是切换全屏后就出现了滚动条
2020-08-06 - 第三方小程序涉直播代码上传经验总结
一直以来作为第三方服务商为商户运营小程序时,使用的是 复用公众号主体快速注册小程序 ,这种方式创建小程序很快速,商户也不需要去记录小程序帐号信息,我们维护小程序代码时也很容易,一套代码,有升级时自动去全网更新。 一切执行起来都挺和谐的,直到直播功能出现后,这份安宁被打破了 1、原来的商户无小程序帐号,变成一种羁绊了。好在还可以引导商户扫描《小程序助手》小程序码,设置登录邮箱;或在微信公众平台,通过找回帐号的方式获得; 2、小程序模板不能一蹴而就了,还得区分商户是否有开通小程序直播插件; 3、新的小程序要开通直播功能,必须经历①设置登录邮箱(或找回帐号)→②上传不带直播的代码→③发起小程序支付→④开通小程序插件→⑤上传带直播的代码 这样一串长流程。 能一次就解决的问题都不算问题,最大的问题是代码管理,如果非得分成2套代码来管理,对于程序员来讲确实有点痛苦,如果再来一个类似直播的插件,那不得分4套代码,接着8套代码,16套代码,那不得逼疯程序员。 好在小程序有为第三方提供ext_json,用来区分不同商户,有了它,我们就可以1套代码搞定不同的商户了。具体操作如下: 1、app.json中去掉插件相关引入代码 2、上传小程序代码前获取商家已经开通的插件列表 https://api.weixin.qq.com/wxa/plugin?access_token= post参数{"action":"list"} 再判断是否已经开通相关插件,如直播插件的appid为wx2b03c6e691cd7370,那么可以判断返回的插件list字符串是否包含该appid。 如果有开通,则extJson中插入该插件的引用(plugins开始的这串) {\"ext\":{\"你自己定义的扩展参数\":\"扩展参数值\",\"haveLive\":1},\"plugins\": {\"live-player-plugin\": {\"version\": \"1.0.16\", \"provider\": \"wx2b03c6e691cd7370\"}},\"recompile\": true} 如果没有开通则extJosn为 {\"ext\":{\"你自己定义的扩展参数\":\"扩展参数值\",\"haveLive\":0}} 3、上传代码时传入ext_json https://api.weixin.qq.com/wxa/commit?access_token= post参数 {"template_id":模板ID,"ext_json":"2中返回的json字符串","user_version":"版本号","user_desc":"版本描述"} 4、在小程序中通过 wx.getExtConfig 获取参数 haveLive, 当为0时,表示没有开通直播插件,这时候需要隐藏所有可能出现直播相关的界面。不然小程序审核时会被驳回,要求类目要增加选择“社交 → 直播”类目(因为有直播相关功能,却没有开通小程序直播插件。在小程序中要使用直播功能,要么使用官方提供的小程序直播插件;要么设置类目为“社交 → 直播”后,使用其他途径进行直播)
2020-07-07 - 关于微信安卓端网页字体适配的通知
为了提供给用户更好的阅读体验,微信安卓版 7.0.10 版本起,网页的字体会跟随微信设置里的字体大小更改而变化。 若调整字体变大或变小后,部分未适配网页的排版会出现显示错乱,建议未进行适配的开发者尽快完成对“ 字体大小” 的适配。 查看网页在字体不同大小下展示效果的方法: 方法1:"设置">"通用">“字体大小">进行字体大小修改后查看对应网页显示效果。 方法2:在微信内访问对应网页右上角”…">底部菜单栏选择调整字体">进行字体大小修改后查看对应网页显示效果。 另外,对于现有的显示问题,我们提供以下方案让开发者临时将字体还原标准大小。同时,开发者可以在页面中提示用户在右上角”…”更多菜单中修改字体到合适的大小。 下列方案可以将字体还原标准大小,但我们仍然建议后续做字体适配来提高用户的阅读体验。 『字体还原标准大小』方案: 我们提供了一个 JSAPI 用于设置字体大小,只需将字体大小等级设置为 2 (标准)即可,代码示例如下: document.addEventListener("WeixinJSBridgeReady", function () { WeixinJSBridge.invoke("setFontSizeCallback", { fontSize: '2' }); }, false); 此外,若页面是用 rem 单位进行排版的(目前该做法更容易导致页面不可用),可以反向重置 font-size 的数值达到还原字体标准大小的目的,此方法在效果上也比较理想。代码示例如下: // 以下代码思路来源网络。同时代码放在 body 标签开头位置效果最佳 var $dom = document.createElement('div'); $dom.style = 'font-size: 10px'; document.body.appendChild($dom); // 计算出放大后的字体 var scaledFontSize = parseInt(window.getComputedStyle($dom, null).getPropertyValue('font-size')); document.body.appendChild($dom); // 计算原字体和放大后字体的比例 var scaleFactor = 10 / scaledFontSize; // 取 html 元素的字体大小 var originRootFontSize = parseInt(window.getComputedStyle(document.documentElement, null).getPropertyValue('font-size')); // 由于设置 font-size 后实际会变大,故 font-size 需设置为更小一级 document.documentElement.style.fontSize = originRootFontSize * scaleFactor * scaleFactor + 'px';
2020-01-14 - 社区每周 | 网页字体适配方案、小程序搜索优化指南、社区上周问题反馈(12.23-12.27)
各位微信开发者: 以下是小程序搜索优化指南、网页字体适配方案及上周我们在社区收到的问题反馈、需求的处理进度,希望同大家一同打造小程序生态。 小程序搜索优化指南(SEO) 2019年上半年微信发布了基于小程序页面的搜索,为了让我们更好地发现及理解小程序的页面,结合过去一段时间来我们遇到的各种情况,建议各位开发者阅读《小程序搜索优化指南》并结合实际情况进行优化。 网页字体适配方案 微信安卓版 7.0.10 版本起,网页的字体大小会跟随微信全局设置里的字体大小。若用户设置了较大字体后,可能导致网页的排版出现错乱,建议开发者做好较大字体的适配。详情请查看《关于微信安卓端网页字体适配的通知》。 上周问题反馈和处理进度(12.23-12.27) 已修复的问题 微信公众平台测试号管理页面跳转连接问题 查看详情 开放社区-我的主页,编辑个性签名后无法保存的问题 查看详情 社区编辑文章,保存草稿提示提交太频繁的问题 查看详情 社区等级被清零的问题 查看详情 前一天发布的文章在列表里不见的问题 查看详情 文档搜索不了内容的问题 查看详情 关于微信小游戏后台订阅消息申请模版问题 查看详情 微信git仓库报500了的问题 查看详情 后台发布不了新版本的问题 查看详情 微信公众平台发生错误的问题 查看详情 修复中的问题 社区文章编辑器的样式与消息的样式冲突 查看详情 movable-view 组件在 scale 开启的时候,设置偏移值的问题 查看详情 vivo手机出现大量黑屏的问题 查看详情 消息模块少了个}的问题 查看详情 微信7.0.8,部分 iphone 机型出现文字显示黑块的问题 查看详情 视频广告播放过程中,如果断网,无法再次拉起的问题 查看详情 文档内嵌文档入口404,第三方平台》小程序管理》提交代码的问题 查看详情 开发工具使用「预览-自动预览」时,自定义编译模式中获取参数错误的问题 查看详情 wx.startAccelerometer() 安卓手机设置 interval 无效的问题 查看详情 微信更新到7.0.9后 小游戏闪屏的问题 查看详情 innerAudioContext.duration Android无法获取时长的问题 查看详情 wx.addPhoneContact 点“取消”无法返回的问题 查看详情 真机调试,只有我的开发者账户可以获取授权提示,其他人都提示未使用您任何信息的问题 查看详情 iOS 真机 锁屏或切换后台程序后再打开,input focus为true 唤不起键盘的问题 查看详情 canvas.toTempFilePathSync 截图为全黑色(部分手机出现该问题)的问题 查看详情 安卓部分机型 wx.chooseImage 时无法回调 complete 的问题 查看详情 基础库2.10.0中的 textarea 引入了新的 feature 的问题 查看详情 wx.requestSubscribeMessage 调用后弹起的弹窗按钮没有文案的问题 查看详情 为什么升级到微信7.0.9版本后,支付插件无法唤起支付弹框的问题 查看详情 小程序支付插件内唤起的微信支付功能页面内,点击立即支付无反应的问题 查看详情 调用接口查询小程序提审额度提示 system error 的问题 查看详情 小程序是否可以支持从微信聊天窗口选择聊天记录的需求 查看详情 稳定在线好几个月没更新的游戏,今天突然开始大量报出 readFileSync 的错误的问题 查看详情 微信版本(7.0.9)中小程序使用支付插件,支付功能页中点击'立即支付'按钮,无法弹出支付弹窗 查看详情 官方文档页面左侧菜单显示异常的问题 查看详情 微信小游戏闪退的问题 查看详情 切后台时间稍长,再重连 websocket 就会失败,提示 jsapi has no permission 的问题 查看详情 iOS最新版7.0.9微信,获取cameraFrame数据时,内容发生了变形 查看详情 小程序插件不能支付,点击“立即支付”,直接返回上一个页面的问题 查看详情 来源识别的部分多了个空格的问题 查看详情 生命周期 onload 里面调用 wx.hideLoading 失效的问题 查看详情 格式化代码无效的问题 查看详情 需求反馈 需求评估中 出个自助解绑原先绑定小程序的功能的需求 查看详情 live-play 局部放大的功能的需求 查看详情 小程序调试的 vConsole 中增加查看Storage的功能 查看详情 改善微信使用体验感的需求 查看详情 云函数续费方式网页续费方式的需求 查看详情 wx.onLocationChange 加个周期参数的需求 查看详情 在类目政务民生-司法下添加长期订阅模版的需求 查看详情 微信团队 2020.01.03
2020-01-03 - 小程序代码包总包上限提升至12M、新增内置扩展库支持
小程序代码包总包上限提升至12M为了让开发者开发出功能更丰富的小程序,小程序或小游戏代码包总包上限由8M提升到12M。建议开发者优化小程序性能并将每个分包做得尽可能小,以便提升用户的打开速度,优化用户体验。 开发者可登录开发者工具,在详情-项目配置中点击刷新按钮,获取最新的配置信息。 [图片] 内置扩展库支持扩展库是将官方提供的一系列扩展能力打包而成的一些类库。为方便开发者使用,我们在最新的nightly版开发者工具支持了内置扩展库,开发者只需在app.json配置文件声明引用指定扩展库即可,无需自行引入相关 npm 包且不计入小程序代码包大小,目前支持了kbone和WeUI两种扩展库,更多详情请参考文档。 欢迎各位开发者接入,如有问题,可在本帖下方留言或在社区发帖反馈。 微信团队 2019.11.22
2019-11-22 - 小程序模板消息能力调整通知
小程序模板消息能力在帮助小程序实现服务闭环的同时,也存在一些问题,如: 1. 部分开发者在用户无预期或未进行服务的情况下发送与用户无关的消息,对用户产生了骚扰; 2. 模板消息需在用户访问小程序后的 7 天内下发,不能满足部分业务的时间要求。 为提升小程序模板消息能力的使用体验,我们对模板消息的下发条件进行了调整,由用户自主订阅所需消息。 一次性订阅消息 一次性订阅消息用于解决用户使用小程序后,后续服务环节的通知问题。用户自主订阅后,开发者可不限时间地下发一条对应的服务消息;每条消息可单独订阅或退订。 [图片] (一次性订阅示例) 长期性订阅消息 一次性订阅消息可满足小程序的大部分服务场景需求,但线下公共服务领域存在一次性订阅无法满足的场景,如航班延误,需根据航班实时动态来多次发送消息提醒。为便于服务,我们提供了长期性订阅消息,用户订阅一次后,开发者可长期下发多条消息。 目前长期性订阅消息仅向政务民生、医疗、交通、金融、教育等线下公共服务开放,后期将逐步支持到其他线下公共服务业务。 调整计划 小程序订阅消息接口上线后,原先的模板消息接口将停止使用,详情如下: 1. 开发者可登录小程序管理后台开启订阅消息功能,接口开发可参考文档:《小程序订阅消息》 2. 开发者使用订阅消息能力时,需遵循运营规范,不可用奖励或其它形式强制用户订阅,不可下发与用户预期不符或违反国家法律法规的内容。具体可参考文档:《小程序订阅消息接口运营规范》 3. 原有的小程序模板消息接口将于 2020 年 1 月 10 日下线,届时将无法使用此接口发送模板消息,请各位开发者注意及时调整接口。 微信团队 2019.10.12
2019-10-13 - 微信开放平台发布新版本SDK,请开发者尽快更新
为适配 iOS 及安卓系统版本升级,微信开放平台发布新版本SDK,请开发者及时更新。 一、iOS系统 由于苹果iOS 13系统版本安全升级,微信SDK在1.8.6.1版本进行了适配,支持通过Universal Links方式跳转完成应用安全校验,提升使用流程安全性。查看接入文档 接入指引如下: 1. 更新iOS 1.8.6.1版本SDK,前往下载SDK工具包 2. 按苹果官网的要求,创建应用的Universal Links服务,参考Universal Links苹果官方文档 3. 登录微信开放平台,填写应用的Universal Links信息 [图片] 二、安卓系统 为适配Android 10系统,微信发布5.5.8版本SDK,前往更新 平台预计从2020年起,逐步回收旧版本SDK的能力,为避免应用无法正常使用微信相关功能,请开发者尽快升级。
2019-12-24 - 微信连Wi-Fi功能调整通知
各位开发者: 基于操作系统如iOS 13及Android Q针对Wi-Fi能力的安全策略调整,微信所提供的“portal鉴权连Wi-Fi”能力将受到影响。现发出公告。具体变更如下: 2019年08月19日起,“公众号连Wi-Fi”暂停微信portal鉴权连网方式,不再提供wifi关联公众号的功能配置后台及接口,回收第三方平台微信连Wi-Fi权限集。此外,其他功能不变,“扫二维码连网”模式依然可以正常使用。 请各位开发者及时调整,以免影响业务功能。(以下红框内容为调整功能) [图片] [图片] Android Q文档可见: Android Q 隐私权:相机和网络连接变更 Android Q 隐私权:数据和标识符变更 微信团队 2019.07.19
2019-07-22 - 微信卡券“网页链接跳转”能力即将下线通知
各位开发者: 为了确保微信生态良性发展,微信卡券将于2019年8月13日下线网页链接跳转能力。下线后,卡券创建流程中,“自定义入口”与“卡券详情>立即使用跳转”不再支持跳转至网页配置,你可尝试使用跳转小程序作为替代。本次调整仅针对券,会员卡原有能力暂时不变。 给你带来不便,敬请谅解。感谢你的理解和支持。 微信团队 2019年7月26日
2019-07-26 - 「小程序·云开发」功能更新和问题反馈
各位开发者: 大家好 由于近期小程序·云开发将上线付费功能(付费功能针对非基础资源配额,基础资源配额仍可免费使用)。为了给开发者更充足的时间进行调整,对于截止 2019-06-21 日前通过邮件申请调整的配额(非基础资源配额)的截止日期统一延长至 2019-08-31。 为了方便开发者进行功能开发并提高开发效率,「小程序·云开发」近期进行了一系列的功能优化。开发者可通过下载最新 Nightly Build 版的开发者工具进行功能体验。 同时,为了给开发者提供更优质的服务,我们诚邀大家参加小程序·云开发问卷调查。我们将根据问卷调查中的反馈信息调整后续版本的功能,感谢大家的支持! 欢迎开发者填写小程序·云开发调查问卷。 基础能力 数据库高级操作:数据库高级操作是小程序·云开发提供的一种十分灵活的数据库操作能力。通过数据库高级操作,开发者可以更加便捷和高效地对数据库中的大量数据进行进行增删查改/CRUD操作。 [图片] 云函数支持单文件更新:为了优化云函数代码的上传体验,云函数新增单文件更新功能。开发者可在需上传文件右键选择云函数增量上传体验单文件更新能力。 [图片] 云函数获取当前环境:小程序·云开发提供 getWXContext 方法用于在云函数中获取微信调用上下文(AppID、环境ID、openid 以及 unionid),使开发者可以更灵活的使用多套资源环境。 云调用:云调用是云开发提供的基于云函数使用小程序开放接口的能力,目前覆盖服务端调用、开放数据等场景。进一步降低了小程序的开发门槛 HTTP API:HTTP API 是云开发提供的一种小程序外访问云开发资源的能力。使用 HTTP API 开发者可在已有服务器上访问云资源,实现与云开发资源的互通。 开发调试 Network 面板展示云开发请求信息:从微信开发者工具 1.02.1905302 及基础库 2.7.1 起,在小程序 Network 面板中会显示云开发请求信息,包括调用所实际请求的环境 ID、请求体、JSON 回包、耗时、及调用堆栈。 [图片] 本地调试:云函数开发可以不再需要频繁上传测试,只需用 IDE 在本地调试完成再上传到现网验证。开发者可在云函数根目录右键选择本地调试来开启本地调试界面。 微信团队 2019.06.21
2019-06-21 - 微信证件OCR识别能力开放
微信证件OCR识别能力是微信团队推出的一套提升移动端快捷信息录入的工具,目前支持身份证、银行卡、行驶证、驾驶证、营业执照 OCR 识别。经过持续迭代优化,现在对外开放接入测试。 使用场景 微信证件OCR广泛适用于政务、医疗、交通、教育、金融等各行各业,涉及到需要用户输入身份信息、银行卡信息、车辆信息场景时,即可通过OCR识快速识别、输入信息,极大提高输入效率,提高用户体验。 以下为开通插件的部分小程序案例:国家发展改革委政务服务、安徽省统一公共支付平台、南航e行、湖南电信网上营业厅、中国国际航空、厦门航空、上海客运总站、沃尔玛、青岛银行信用卡等。以下是部分使用场景的截图: [图片] [图片] [图片] 业界领先的识别水准 微信证件OCR历经v1.0版本(基于传统的版面分析, 单字切分, 字符分类算法),v2.0 (基于深度学习的卡片定位, 文字定位, 单字切分, 字符分类),到现在的v3.0版本(基于深度学习的卡片定位, 文本行定位, 串识别),不断优化OCR的识别精度, 取得了业界领先的识别水准。可以轻松应对在移动端拍照/扫描的情况,诸如拍摄角度、光照、阴影、遮挡等的干扰。 可以扫码体验我们的demo小程序 [图片] 灵活易用的调用方式 目前有两种调用方式:小程序插件方式和云端API的方式。 对于对交互没特殊需求的开发者,可以直接使用我们的小程序插件;有订制化需求的,也可以直接使用我们的云端API方式;后续我们也会把这个升级成小程序的基础能力,做成类扫码的体验,进一步简化接入和调用流程。合作与开放 内测期间,对于已认证的订阅号、服务号、企业号、小程序,我们提供了 500 次/天 的免费额度供开发者使用。如免费额度无法满足使用需求,开发者可以【申请调整 OCR 接口调用次数上限】为主题,发送邮件至:wx_city@tencent.com 申请调整,并在正文中注明小程序帐号 AppID、业务主体、业务背景、服务流程载体、日调用量预估。调整的额度仅在内测期间有效。有任何意见或者反馈,都可以在微信开放社区上联系我们,以便于我们更加了解客户对OCR的需求精确度以及需求场景,从而不断迭代优化OCR版本,拓展OCR服务的范围,如支持更多的场景需求: 发票识别、名片识别、街景识别等等。 微信团队 2019/07/03
2019-09-19 - 小程序开发另类小技巧 --用户授权篇
小程序开发另类小技巧 --用户授权篇 getUserInfo较为特殊,不包含在本文范围内,主要针对需要授权的功能性api,例如:wx.startRecord,wx.saveImageToPhotosAlbum, wx.getLocation 原文地址:https://www.yuque.com/jinxuanzheng/gvhmm5/arexcn 仓库地址:https://github.com/jinxuanzheng01/weapp-auth-demo 背景 小程序内如果要调用部分接口需要用户进行授权,例如获取地理位置信息,收获地址,录音等等,但是小程序对于这些需要授权的接口并不是特别友好,最明显的有两点: 如果用户已拒绝授权,则不会出现弹窗,而是直接进入接口 fail 回调, 没有统一的错误信息提示,例如错误码 一般情况而言,每次授权时都应该激活弹窗进行提示,是否进行授权,例如: [图片] 而小程序内只有第一次进行授权时才会主动激活弹窗(微信提供的),其他情况下都会直接走fail回调,微信文档也在句末添加了一句请开发者兼容用户拒绝授权的场景, 这种未做兼容的情况下如果用户想要使用录音功能,第一次点击拒绝授权,那么之后无论如何也无法再次开启录音权限**,很明显不符合我们的预期。 所以我们需要一个可以进行二次授权的解决方案 常见处理方法 官方demo 下面这段代码是微信官方提供的授权代码, 可以看到也并没有兼容拒绝过授权的场景查询是否授权(即无法再次调起授权) [代码]// 可以通过 wx.getSetting 先查询一下用户是否授权了 "scope.record" 这个 scope wx.getSetting({ success(res) { if (!res.authSetting['scope.record']) { wx.authorize({ scope: 'scope.record', success () { // 用户已经同意小程序使用录音功能,后续调用 wx.startRecord 接口不会弹窗询问 wx.startRecord() } }) } } }) [代码] 一般处理方式 那么正常情况下我们该怎么做呢?以地理位置信息授权为例: [代码]wx.getLocation({ success(res) { console.log('success', res); }, fail(err) { // 检查是否是因为未授权引起的错误 wx.getSetting({ success (res) { // 当未授权时直接调用modal窗进行提示 !res.authSetting['scope.userLocation'] && wx.showModal({ content: '您暂未开启权限,是否开启', confirmColor: '#72bd4a', success: res => { // 用户确认授权后,进入设置列表 if (res.confirm) { wx.openSetting({ success(res){ // 查看设置结果 console.log(!!res.authSetting['scope.userLocation'] ? '设置成功' : '设置失败'); }, }); } } }); } }); } }); [代码] 上面代码,有些同学可能会对在fail回调里直接使用wx.getSetting有些疑问,这里主要是因为 微信返回的错误信息没有一个统一code errMsg又在不同平台有不同的表现 从埋点数据得出结论,调用这些api接口出错率基本集中在未授权的状态下 这里为了方便就直接调用权限检查了 ,也可以稍微封装一下,方便扩展和复用,变成: [代码] bindGetLocation(e) { let that = this; wx.getLocation({ success(res) { console.log('success', res); }, fail(err) { that.__authorization('scope.userLocation'); } }); }, bindGetAddress(e) { let that = this; wx.chooseAddress({ success(res) { console.log('success', res); }, fail(err) { that.__authorization('scope.address'); } }); }, __authorization(scope) { /** 为了节省行数,不细写了,可以参考上面的fail回调,大致替换了下变量res.authSetting[scope] **/ } [代码] 看上去好像没有什么问题,fail里只引入了一行代码, 这里如果只针对较少页面的话我认为已经够用了,毕竟**‘如非必要,勿增实体’,但是对于小打卡这个小程序来说可能涉及到的页面,需要调用的场景偏多**,我并不希望每次都人工去调用这些方法,毕竟人总会犯错 梳理目标 上文已经提到了背景和常见的处理方法,那么梳理一下我们的目标,我们到底是为了解决什么问题?列了下大致为下面三点: 兼容用户拒绝授权的场景,即提供二次授权 解决多场景,多页面调用没有统一规范的问题 在底层解决,业务层不需要关心二次授权的问题 扩展wx[funcName]方法 为了节省认知成本和减少出错概率,我希望他是这个api默认携带的功能,也就是说因未授权出现错误时自动调起是否开启授权的弹窗 为了实现这个功能,我们可能需要对wx的原生api进行一层包装了(关于页面的包装可以看:如何基于微信原生构建应用级小程序底层架构) 为wx.getLocation添加自己的方法 这里需要注意的一点是直接使用常见的装饰模式是会出现报错,因为wx这个对象在设置属性时没有设置set方法,这里需要单独处理一下 [代码]// 直接装饰,会报错 Cannot set property getLocation of #<Object> which has only a getter let $getLocation = wx.getLocation; wx.getLocation = function (obj) { $getLocation(obj); }; // 需要做一些小处理 wx = {...wx}; // 对wx对象重新赋值 let $getLocation = wx.getLocation; wx.getLocation = function (obj) { console.log('调用了wx.getLocation'); $getLocation(obj); }; // 再次调用时会在控制台打印出 '调用了wx.getLocation' 字样 wx.getLocation() [代码] 劫持fail方法 第一步我们已经控制了wx.getLocation这个api,接下来就是对于fail方法的劫持,因为我们需要在fail里加入我们自己的授权逻辑 [代码]// 方法劫持 wx.getLocation = function (obj) { let originFail = obj.fail; obj.fail = async function (errMsg) { // 0 => 已授权 1 => 拒绝授权 2 => 授权成功 let authState = await authorization('scope.userLocation'); // 已授权报错说明并不是权限问题引起,所以继续抛出错误 // 拒绝授权,走已有逻辑,继续排除错误 authState !== 2 && originFail(errMsg); }; $getLocation(obj); }; // 定义检查授权方法 function authorization(scope) { return new Promise((resolve, reject) => { wx.getSetting({ success (res) { !res.authSetting[scope] ? wx.showModal({ content: '您暂未开启权限,是否开启', confirmColor: '#72bd4a', success: res => { if (res.confirm) { wx.openSetting({ success(res){ !!res.authSetting[scope] ? resolve(2) : resolve(1) }, }); }else { resolve(1); } } }) : resolve(0); } }) }); } // 业务代码中的调用 bindGetLocation(e) { let that = this; wx.getLocation({ type: 'wgs84', success(res) { console.log('success', res); }, fail(err) { console.warn('fail', err); } }); } [代码] 可以看到现在已实现的功能已经达到了我们最开始的预期,即因授权报错作为了wx.getLocation默认携带的功能,我们在业务代码里再也不需要处理任何再次授权的逻辑 也意味着wx.getLocation这个api不论在任何页面,组件,出现频次如何,**我们都不需要关心它的授权逻辑(**效果本来想贴gif图的,后面发现有图点大,具体效果去git仓库跑一下demo吧) 让我们再优化一波 上面所述大致是整个原理的一个思路,但是应用到实际项目中还需要考虑到整体的扩展性和维护成本,那么就让我们再来优化一波 代码包结构: 本质上只要在app.js这个启动文件内,引用./x-wxx/index文件对原有的wx对象进行覆盖即可 [图片] **简单的代码逻辑: ** [代码]// 大致流程: //app.js wx = require('./x-wxx/index'); // 入口处引入文件 // x-wxx/index const apiExtend = require('./lib/api-extend'); module.exports = (function (wxx) { // 对原有方法进行扩展 wxx = {...wxx}; for (let key in wxx) { !!apiExtend[key] && (()=> { // 缓存原有函数 let originFunc = wxx[key]; // 装饰扩展的函数 wxx[key] = (...args) => apiExtend[key](...args, originFunc); })(); } return wxx; })(wx); // lib/api-extend const Func = require('./Func'); (function (exports) { // 需要扩展的api(类似于config) // 获取权限 exports.authorize = function (opts, done) { // 当调用为"确认授权方法时"直接执行,避免死循环 if (opts.$callee === 'isCheckAuthApiSetting') { console.log('optsopts', opts); done(opts); return; } Func.isCheckAuthApiSetting(opts.scope, () => done(opts)); }; // 选择地址 exports.chooseAddress = function (opts, done) { Func.isCheckAuthApiSetting('scope.address', () => done(opts)); }; // 获取位置信息 exports.getLocation = function (opts, done) { Func.isCheckAuthApiSetting('scope.userLocation', () => done(opts)); }; // 保存到相册 exports.saveImageToPhotosAlbum = function (opts, done) { Func.isCheckAuthApiSetting('scope.writePhotosAlbum', () => done(opts)); } // ...more })(module.exports); [代码] 更多的玩法 可以看到我们无论后续扩展任何的微信api,都只需要在lib/api-extend.js 配置即可,这里不仅仅局限于授权,也可以做一些日志,传参的调整,例如: [代码] // 读取本地缓存(同步) exports.getStorageSync = (key, done) => { let storage = null; try { storage = done(key); } catch (e) { wx.$logger.error('getStorageSync', {msg: e.type}); } return storage; }; [代码] 这样是不是很方便呢,至于Func.isCheckAuthApiSetting这个方法具体实现,为了节省文章行数请自行去git仓库里查看吧 关于音频授权 录音授权略为特殊,以wx.getRecorderManager为例,它并不能直接调起录音授权,所以并不能直接用上述的这种方法,不过我们可以曲线救国,达到类似的效果,还记得我们对于wx.authorize的包装么,本质上我们是可以直接使用它来进行授权的,比如将它用在我们已经封装好的录音管理器的start方法进行校验 [代码]wx.authorize({ scope: 'scope.record' }); [代码] 实际上,为方便统一管理,Func.isCheckAuthApiSetting方法其实都是使用wx.authorize来实现授权的 [代码]exports.isCheckAuthApiSetting = async function(type, cb) { // 简单的类型校验 if(!type && typeof type !== 'string') return; // 声明 let err, result; // 获取本地配置项 [err, result] = await to(getSetting()); // 这里可以做一层缓存,检查缓存的状态,如果已授权可以不必再次走下面的流程,直接return出去即可 if (err) { return cb('fail'); } // 当授权成功时,直接执行 if (result.authSetting[type]) { return cb('success'); } // 调用获取权限 [err, result] = await to(authorize({scope: type, $callee: 'isCheckAuthApiSetting'})); if (!err) { return cb('success'); } } [代码] 关于用户授权 用户授权极为特殊,因为微信将wx.getUserInfo升级了一版,没有办法直接唤起了,详见《公告》,所以需要单独处理,关于这里会拆出单独的一篇文章来写一些有趣的玩法 总结 最后稍微总结下,通过上述的方案,我们解决了最开始目标的同时,也为wx这个对象上的方法提供了统一的装饰接口(lib/api-extend文件),便于后续其他行为的操作比如埋点,日志,参数校验 还是那么一句话吧,小程序不管和web开发有多少不同,本质上都是在js环境上进行开发的,希望小程序的社区环境更加活跃,带来更多有趣的东西
2019-06-14 - 如何实现快速生成朋友圈海报分享图
由于我们无法将小程序直接分享到朋友圈,但分享到朋友圈的需求又很多,业界目前的做法是利用小程序的 Canvas 功能生成一张带有小程序码的图片,然后引导用户下载图片到本地后再分享到朋友圈。相信大家在绘制分享图中应该踩到 Canvas 的各种(坑)彩dan了吧~ 这里首先推荐一个开源的组件:painter(通过该组件目前我们已经成功在支付宝小程序上也应用上了分享图功能) 咱们不多说,直接上手就是干。 [图片] 首先我们新增一个自定义组件,在该组件的json中引入painter [代码]{ "component": true, "usingComponents": { "painter": "/painter/painter" } } [代码] 然后组件的WXML (代码片段在最后) [代码]// 将该组件定位在屏幕之外,用户查看不到。 <painter style="position: absolute; top: -9999rpx;" palette="{{imgDraw}}" bind:imgOK="onImgOK" /> [代码] 重点来了 JS (代码片段在最后) [代码]Component({ properties: { // 是否开始绘图 isCanDraw: { type: Boolean, value: false, observer(newVal) { newVal && this.handleStartDrawImg() } }, // 用户头像昵称信息 userInfo: { type: Object, value: { avatarUrl: '', nickName: '' } } }, data: { imgDraw: {}, // 绘制图片的大对象 sharePath: '' // 生成的分享图 }, methods: { handleStartDrawImg() { wx.showLoading({ title: '生成中' }) this.setData({ imgDraw: { width: '750rpx', height: '1334rpx', background: 'https://qiniu-image.qtshe.com/20190506share-bg.png', views: [ { type: 'image', url: 'https://qiniu-image.qtshe.com/1560248372315_467.jpg', css: { top: '32rpx', left: '30rpx', right: '32rpx', width: '688rpx', height: '420rpx', borderRadius: '16rpx' }, }, { type: 'image', url: this.data.userInfo.avatarUrl || 'https://qiniu-image.qtshe.com/default-avatar20170707.png', css: { top: '404rpx', left: '328rpx', width: '96rpx', height: '96rpx', borderWidth: '6rpx', borderColor: '#FFF', borderRadius: '96rpx' } }, { type: 'text', text: this.data.userInfo.nickName || '青团子', css: { top: '532rpx', fontSize: '28rpx', left: '375rpx', align: 'center', color: '#3c3c3c' } }, { type: 'text', text: `邀请您参与助力活动`, css: { top: '576rpx', left: '375rpx', align: 'center', fontSize: '28rpx', color: '#3c3c3c' } }, { type: 'text', text: `宇宙最萌蓝牙耳机测评员`, css: { top: '644rpx', left: '375rpx', maxLines: 1, align: 'center', fontWeight: 'bold', fontSize: '44rpx', color: '#3c3c3c' } }, { type: 'image', url: 'https://qiniu-image.qtshe.com/20190605index.jpg', css: { top: '834rpx', left: '470rpx', width: '200rpx', height: '200rpx' } } ] } }) }, onImgErr(e) { wx.hideLoading() wx.showToast({ title: '生成分享图失败,请刷新页面重试' }) //通知外部绘制完成,重置isCanDraw为false this.triggerEvent('initData') }, onImgOK(e) { wx.hideLoading() // 展示分享图 wx.showShareImageMenu({ path: e.detail.path, fail: err => { console.log(err) } }) //通知外部绘制完成,重置isCanDraw为false this.triggerEvent('initData') } } }) [代码] 那么我们该如何引用呢? 首先json里引用我们封装好的组件share-box [代码]{ "usingComponents": { "share-box": "/components/shareBox/index" } } [代码] 以下示例为获取用户头像昵称后再生成图。 [代码]<button class="intro" bindtap="getUserInfo">点我生成分享图</button> <share-box isCanDraw="{{isCanDraw}}" userInfo="{{userInfo}}" bind:initData="handleClose" /> [代码] 调用的地方: [代码]const app = getApp() Page({ data: { isCanDraw: false }, // 组件内部关掉或者绘制完成需重置状态 handleClose() { this.setData({ isCanDraw: !this.data.isCanDraw }) }, getUserInfo(e) { wx.getUserProfile({ desc: "获取您的头像昵称信息", success: res => { const { userInfo = {} } = res this.setData({ userInfo, isCanDraw: true // 开始绘制海报图 }) }, fail: err => { console.log(err) } }) } }) [代码] 最后绘制分享图的自定义组件就完成啦~效果图如下: [图片] tips: 文字居中实现可以看下代码片段 文字换行实现(maxLines)只需要设置宽度,maxLines如果设置为1,那么超出一行将会展示为省略号 代码片段:https://developers.weixin.qq.com/s/J38pKsmK7Qw5 附上painter可视化编辑代码工具:点我直达,因为涉及网络图片,代码片段设置不了downloadFile合法域名,建议真机开启调试模式,开发者工具 详情里开启不校验合法域名进行代码片段的运行查看。 最后看下面大家评论问的较多的问题:downLoadFile合法域名在小程序后台 开发>开发设置里配置,域名为你图片的域名前缀 比如我文章里的图https://qiniu-image.qtshe.com/20190605index.jpg。配置域名时填写https://qiniu-image.qtshe.com即可。如果你图片cdn地址为https://aaa.com/xxx.png, 那你就配置https://aaa.com即可。
2022-01-20