- 教你怎么监听小程序的返回键
更新:2020年7月28日08:51:11 基础库2.12.0起,可以调用wx.enableAlertBeforeUnload监听原生右上角返回、物理返回以及wx.navigateBack时弹框提示 AIP详情请看: https://developers.weixin.qq.com/miniprogram/dev/api/ui/interaction/wx.enableAlertBeforeUnload.html //======================================== 怎么监听小程序的返回键? 应该有很多人想要监听用户的这个动作吧,但是很遗憾,小程序不会给你这个API的,那是不是就没辙了? 幸好我们还可以自定义导航栏,这样一来我们就可以监听用户的这一动作了。 什么?这你已经知道啦? 那好咱们就不说自定义导航栏的返回监听了,说一下物理返回和左滑?右滑?(不管了,反正是滑)返回上一页怎么监听。 监听物理返回 首先说一下这个监听方法的缺点,虽说是监听,但是还是无法真正意义上的监听并拦截来阻止页面跳转,页面还是会返回上一页,而后重新载入刚刚的页面,如果这不是你想要的,那可以不用往下看了 其次说一下用到什么东西: wx.onAppRoute、wx.showModal 最后是一些主要代码: 重写wx.showModal,主要是加个confirmStay参数和使wx.showModal Promise化 [代码]const { showModal } = wx; Object.defineProperty(wx, 'showModal', { configurable: false, // 是否可以配置 enumerable: false, // 是否可迭代 writable: false, // 是否可重写 value(...param) { return new Promise(function (rs, rj) { let { success, fail, complete, confirmStay } = param[0] param[0].success = (res) => { res.navBack = (res.confirm && !confirmStay) || (res.cancel && confirmStay) wx.setStorageSync('showBackModal', !res.navBack) success && success(res) rs(res) } param[0].fail = (res) => { fail && fail(res) rj(res) } param[0].complete = (res) => { complete && complete(res) (res.confirm || res.cancel) ? rs(res) : rj(res) } return showModal.apply(this, param); // 原样移交函数参数和this }.bind(this)) } }); [代码] 使用wx.onAppRoute实现返回原来的页面 [代码]wx.onAppRoute(function (res) { var a = getApp(), ps = getCurrentPages(), t = ps[ps.length - 1], b = a && a.globalData && a.globalData.pageBeforeBacks || {}, c = a && a.globalData && a.globalData.lastPage || {} if (res.openType == 'navigateBack') { var showBackModal = wx.getStorageSync('showBackModal') if (c.route && showBackModal && typeof b[c.route] == 'function') { wx.navigateTo({ url: '/' + c.route + '?useCache=1', }) b[c.route]().then(res => { if (res.navBack){ a.globalData.pageBeforeBacks = {} wx.navigateBack({ delta: 1 }) } }) } } else if (res.openType == 'navigateTo' || res.openType == 'redirectTo') { if (!a.hasOwnProperty('globalData')) a.globalData = {} if (!a.globalData.hasOwnProperty('lastPage')) a.globalData.lastPage = {} if (!a.globalData.hasOwnProperty('pageBeforeBacks')) a.globalData.pageBeforeBacks = {} if (ps.length >= 2 && t.onBeforeBack && typeof t.onBeforeBack == 'function') { let { onUnload } = t wx.setStorageSync('showBackModal', !0) t.onUnload = function () { a.globalData.lastPage = { route: t.route, data: t.data } onUnload() } } t.onBeforeBack && typeof t.onBeforeBack == 'function' && (a.globalData.pageBeforeBacks[t.route] = t.onBeforeBack) } }) [代码] 改造Page [代码]const myPage = Page Page = function(e){ let { onLoad, onShow, onUnload } = e e.onLoad = (() => { return function (res) { this.app = getApp() this.app.globalData = this.app.globalData || {} let reinit = () => { if (this.app.globalData.lastPage && this.app.globalData.lastPage.route == this.route) { this.app.globalData.lastPage.data && this.setData(this.app.globalData.lastPage.data) Object.assign(this, this.app.globalData.lastPage.syncProps || {}) } } this.useCache = res.useCache res.useCache ? reinit() : (onLoad && onLoad.call(this, res)) } })() e.onShow = (() => { return function (res) { !this.useCache && onShow && onShow.call(this, res) } })() e.onUnload = (() => { return function (res) { this.app.globalData = Object.assign(this.app.globalData || {}, { lastPage: this }) onUnload && onUnload.call(this, res) } })() return myPage.call(this, e) } [代码] 在需要监听的页面加个onBeforeBack方法,方法返回Promise化的wx.showModal [代码]onBeforeBack: function () { return wx.showModal({ title: '提示', content: '信息尚未保存,确定要返回吗?', confirmStay: !1 //结合content意思,点击确定按钮,是否留在原来页面,confirmStay默认false }) } [代码] 运行测试,Oj8K 是不是很简单,马上去试试水吧,效果图就不放了,静态图也看不出效果,动态图懒得弄,想看效果的自己运行代码片段吧 代码片段 https://developers.weixin.qq.com/s/hc2tyrmw79hg
2020-07-28 - 胶囊的复制链接 有页面报 ‘请检查网络后重试’?
[图片]把页面分享出去再进入 就可以复制链接,直接进入点到该页面复制链接不行。
2024-05-30 - 微信支付新服务器证书兼容性验证指引
1. 背景介绍 微信支付使用HTTPS来保证通信安全,商户与微信支付服务器通信前,要在客户端的操作系统或者执行环境(如JRE等)中部署权威机构的根证书。 商户调用微信支付API的过程中,会用根证书来校验微信支付服务器及域名的真实性。 受Mozilla信任库的根证书最新信任策略(全球所有 CA 的可信根证书生成后最少 15 年更换一次,超过时间的可信根会逐渐被 Mozilla 停止信任)影响,DigiCert 将逐步停用旧根体系(G1)颁发 TLS/SSL 证书,并开始使用新根体系(G2)颁发 TLS/SSL 证书。 当前微信支付服务器证书的颁发根CA是Digicert Global Root CA (G1),微信支付计划于2024年8月5日0:00开始,逐步启用采用DigiCert Global Root G2根CA颁发的新服务器证书,商户的技术开发人员应仔细阅读本指引,并完成相关验证和修正,以免影响正常交易。 注意: 与微信支付系统直接对接(自行开发、外包开发)通信的商户可能受影响,商户需在2024年8月5日0:00之前参考指引完成相关验证和修正。服务商下属特约商户等间接对接微信支付的商户不受影响; 大多数操作系统和执行环境都默认内置了DigiCert Global Root G2根证书,因此大多数系统无需改动即可兼容新服务器证书。但如果商户的服务器/终端设备未内置G2根证书,或程序代码指定使用旧的G1根证书,则会受到影响,将出现服务中断的问题。请及时移除指定旧根证书操作,改用系统自带的信任库进行验证,并确保有DigiCert Global Root G2根证书; 新的 G2 根体系采用更高安全性的 SHA256 签名算法,且依然兼容当前主流的操作系统和移动设备,主流环境兼容情况如下: [图片] 对应的根证书文件请参考: Baltimore CyberTrust Root:Download PEM、Download DER/CRT Digicert Global Root CA:Download PEM 、Download DER/CRT Digicert Global Root G2:Download PEM、Download DER/CRT 2. 商户须知 商户需确认与微信支付对接的系统或终端设备可兼容新的服务器证书,并参考“验证指引”章节的方法,在2024年8月5日0:00日之前完成验证: 如果验证结果正常,商户不需要做其他任何事情 如果验证结果异常,商户需要修改相关的系统实现或配置,且需最晚于2024年8月5日0:00之前完成修正,否则商户的业务系统与微信支付系统之间将不能正常进行HTTPS通讯,将影响业务正常运行。 商户在验证和修正过程中遇到问题,可在证书与密钥专区发帖咨询,我们会有专人进行解答回复。 3. 验证指引 验证方式:绑定host,请求已部署新证书的微信支付服务器 商户可通过修改操作系统的hosts文件来绑定IP,例如,可在hosts文件中新增一行如下内容,实现将域名"api.mch.weixin.qq.com"绑定到新证书环境: 43.142.224.50 api.mch.weixin.qq.com 在linux系统下,hosts文件的完整路径为"/etc/hosts",在Windows系统下,hosts文件的完整路径为"C:\Windows\System32\drivers\etc\hosts"。 商户应根据当前实际对接使用的域名来修改hosts文件配置,已部署新服务器证书的验证环境host和IP对应关系如下: [图片] 注意: 1. host环境可以访问的接口与正式环境完全一致,且真实生效,被视为生产正式业务。在验证之前,请充分评估对贵司业务系统以及业务的影响; 2. 验证完成后,请及时恢复服务器上的host配置,微信支付服务器证书更新完成后,此处使用的IP会被关停; 3. 需要用跟生产环境相同的操作系统、执行环境、开发语言及程序逻辑进行验证。使用curl等命令行工具验证成功,并不代表你的系统支持了新的服务器证书; 4. 逐一验证所有正在使用的微信支付接口,如果均能正常使用,说明你的系统支持微信支付新的服务器证书。反之,则需要根据修正指引排查问题并修正。 4. 修正指引 大部分情况下,验证失败是以下两种情况导致的: 情况一:程序中指定了根证书,但是指定的根证书中仅包含了旧的G1根证书; 情况二:服务器上没有部署新的G2根证书。 可通过以下两个方案修正: 方案一:删除指定根证书的代码。当程序中不指定根证书时,会使用系统自带的根证书。绝大部分系统中已内置了新的G2根证书,所以删除指定根证书的代码,不会影响到你的现有业务 方案二:更新根证书。往truststore或者根证书信任文件中追加新的G2根证书(注意:追加新的根证书时,需要保留老的G1根证书) 推荐使用“方案一”来修正,该方案的兼容性更好。原因是:新的G2根证书将于 2029年4月15日不再被Mozilla信任,到时候同样要更换新的根证书。使用方案一修复的话,你的系统中很可能已内置了后续需更换使用的根证书,从而不受影响。如果使用方案二进行修复的话,在 2029年4月15日仍可能需安装新的根证书。 下面介绍各种开发语言可能碰到的问题及解决方法: JAVA常见错误: [代码]javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target [代码] 可能原因:代码中设置了[代码]javax.net.ssl.trustStore[代码], 可以在代码中搜索关键字[代码]trustStore[代码]或者[代码]TrustManager[代码]来确认。 解决方法: 方法一:删除掉指定[代码]javax.net.ssl.trustStore[代码]的代码 方法二:安装新的根证书, 往指定的[代码]trustStore[代码]中添加新的根证书。操作命令:keytool -importcert -keystore cacerts -storepass changeit -noprompt -file ./DigiCertGlobalRootG2.crt -alias digicertglobalrootg2 C++常见错误: [代码]cURL error 60: SSL certificate: unable to get local issuer certificate. CURLE_SSL_CACERT (60) peer certificate cannot be authenticated with known CA certificates. [代码] 可能原因:代码中设置了[代码]CURLOPT_CAINFO[代码], 可以在代码中搜索关键字[代码]CURLOPT_CAINFO[代码]来确认。 解决方法: 方法一:删除掉[代码]curl_easy_setopt(pCurl,CURLOPT_CAINFO,"./rootca.pem");[代码]相关的代码 方法二:更新rootca.pem,用libcurl官网最新的替换即可 PHP常见错误: [代码]cURL error 60: SSL certificate: unable to get local issuer certificate. CURLE_SSL_CACERT (60) peer certificate cannot be authenticated with known CA certificates. [代码] 可能原因:使用libcurl时设置了[代码]CURLOPT_CAINFO[代码],可以在代码中搜索关键字[代码]CURLOPT_CAINFO[代码]来确认。 解决方法: 方法一:删除掉类似[代码]curl_setopt(pCurl,CURLOPT_CAINFO,"./rootca.pem");[代码]的代码 方法二:更新rootca.pem,用libcurl官网最新的替换即可 C#常见错误: [代码]RemoteCertificateValidationCallback[代码]设置的回调函数返回[代码]false[代码] 可能原因:操作系统中没有新的根CA 解决方法:安装新的根证书 Python常见错误: [代码]SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:581) [代码] 可能原因:代码中用[代码]verify[代码]指定了根证书文件,可以在代码中搜索关键字“verify”来确认。类似的代码如: [代码]response = requests.post( "https://api.mch.weixin.qq.com/secapi/pay/refund", verify="./rootca.pem", …… ); [代码] 解决方法: 方法一:删除[代码]verify[代码]参数 方法二:更新rootca.pem,用libcurl官网最新的替换即可 go常见错误: [代码]x509: certificate signed by unknown authority . [代码] 可能原因:发起https时, 用[代码]RootCAs[代码]指定了根证书文件,可以在代码中搜索关键字[代码]RootCAs[代码]来确认。类似的代码如: [代码]roots := x509.NewCertPool() roots.AppendCertsFromPEM([]byte(rootPEM)) tr := &http.Transport{ TLSClientConfig: &tls.Config{RootCAs: roots}, } client := &http.Client{Transport: tr} [代码] 解决方法: 方法一:删除配置项[代码]RootCAs[代码] 方法二:更新rootca.pem,用libcurl官网最新的替换即可 Ruby常见错误: [代码]SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed [代码] 可能原因:发起https时, 用[代码]ssl_ca_file[代码]或者[代码]cert_store[代码]指定了根证书文件,可以在代码中搜索关键字[代码]ssl_ca_file[代码] 或者[代码]cert_store[代码]来确认。类似的代码如: [代码]response = RestClient::Resource.new( "https://api.mch.weixin.qq.com/secapi/pay/refund", :ssl_client_cert => OpenSSL::X509::Certificate.new(File.read("./apiclient_cert.pem ")), :ssl_client_key => OpenSSL::PKey::RSA.new(File.read("./apiclient_key.pem ")), :ssl_ca_file => "./rootca.pem", :verify_ssl=>OpenSSL::SSL::VERIFY_PEER).post(data); [代码] 或者 [代码] sock.cert_store.add_path('/usr/lib/ssl/certs/weixin') sock.cert_store.add_file('/usr/lib/ssl/certs/weixin/rootca.pem') [代码] 解决方法: 方法一:删除[代码]ssl_ca_file[代码]及[代码]cert_store[代码]指定的参数 方法二:更新rootca.pem,用libcurl官网最新的替换即可 NodeJs常见错误: [代码]Caught exception: Error: CERT_UNTRUSTED [代码] 可能原因:代码中用[代码]ca[代码]指定了根证书文件。 可以在代码中搜索关键字[代码]ca[代码]或者[代码]rootca[代码]来确认。类似的代码如: [代码]const options = { hostname: api.mch.weixin.qq.com ', pfx: await readFile('./apiclient_cert.p12'), ca: await readFile('./rootca.pem'), }; const req = https.request(options, (res) => { …… [代码] 解决方法: 方法一:删除[代码]ca[代码]指定的参数 方法二:更新rootca.pem,用libcurl官网最新的替换即可 其它语言请参考对应的TLS/SSL库相关手册。 5. 常见问题 Q1:什么是服务器证书? A:服务器证书通常又叫“SSL证书”、“HTTPS证书”,它由权威CA机构颁发,用于对网站进行身份鉴定,并使客户端与网站之间通过TLS/SSL协议建立起安全传输通道。微信支付的服务器证书是由权威机构DigiCert颁发,商户调用微信支付API时,能通过该证书来认证微信支付的身份。 Q2:什么是根证书? A:根证书是权威CA机构给自己颁发的证书,是信任链的起始点,是证书颁发机构(CA)与用户建立信任关系的基础。操作系统、浏览器、TLS/SSL开发库通常随软件发行包预置其信任的权威机构的根证书。 Q3:根证书和API证书是同一个吗? A:不是,两者没有关系。“根证书”是用来校验微信支付的域名及服务器的真实性, 通常内置在操作系统或者执行环境(如JRE等)中;“API证书”是用来证实商户身份的,通常在调用微信支付v2的出资金类接口(如:退款、企业红包、企业付款等)或v3接口时,才会使用到API证书。 Q4:微信支付为什么要更换服务器证书? A:根证书存在有效期,根证书到期后无法继续被用来校验服务器证书。 因此,微信支付跟权威机构(CA)申请了新的服务器证书。避免在老的根证书过期后,商户调用微信支付API时出现问题。 Q5:微信支付更换服务器证书,需要商户配合做哪些事情? A:需要商户的开发技术人员做以下事情: 验证你的系统是否兼容微信支付新的服务器证书。 若支持的话,不需要做任何操作。若不支持,需要参考修正指引排查原因并修正。 注意: 商户按指引进行验证或安装新的根证书, 不会产生任何费用; 商户平台的API证书也不需要更换; 商户正在使用的其它https证书不需要更换或者升级。 Q6:商户如何核实服务器上是否已内置了G2根证书? A:以Linux系统为例。Linux系统信任根证书库的保存位置因发行版本不同而有所差异:Debian/Ubuntu:/etc/ssl/certs/ca-certificates.crt CentOS/RHEL/Fedora/TencentOS:/etc/pki/tls/certs/ca-bundle.crt 商户可以使用以下命令来核实系统是否已内置了G2根证书: [代码]grep "DigiCert Global Root" /etc/pki/tls/certs/ca-bundle.crt # DigiCert Global Root CA # DigiCert Global Root G2 [代码] 备注:示例显示系统已内置了G1和G2根证书 Q7:微信支付更换证书前,可以提前安装根CA证书吗? A:必须提前安装,且建议在2024年8月5日0:00之前提前安装。因为从2024年8月5日0:00开始,微信支付会在生产环境逐步灰度启用新服务器证书,以校验商户的系统是否兼容新证书。微信支付在更换新证书的过程中,会同时使用新老两个服务器证书,商户要能正常处理这种情况。因此,商户的服务器上需要包含新老两个根证书。 Q8:商户需在什么时候完成验证和修正?不验证会有什么影响? A:商户应在2024年8月5日0:00之前完成验证和修正。如果商户侧系统的实现方式已能兼容新的服务器证书,那么不会影响业务;如果商户侧系统的实现方式不能兼容新的服务器证书,那么会导致商户的系统与微信支付的系统不能正常交互,影响业务。 Q9:如果商户无法按时完成兼容性修正,在微信支付灰度新证书时遇到异常应如何处理? A:如果商户的系统经验证是不能兼容新证书的,商户应在2024年8月5日0:00之前完成修正。如果无法按时完成修正,我们可提供仍使用旧证书的临时环境,商户可通过host绑定IP的方式使用,以临时规避证书更换产生的影响。请务必在2024年11月30日0:00之前完成系统修正,并取消绑定临时环境IP,恢复以正常的方式对接微信支付的生产正式环境。 临时环境host和IP对应关系如下: [图片] 6. 特别提醒 为提前发现商户“是否会受到证书更换的影响?”“有没有升级完根证书?”,微信支付将于2024年8月5日0:00开始,把商户的部分请求转发到部署了新证书的服务器上,并逐步提升灰度比例。当商户不支持新的服务器证书时,会出现SSL相关的错误,通常情况下重试即可恢复; 根证书升级仅跟服务器和应用程序相关,与商户号没关系。只要在同一台服务器升级完成后,该服务器上使用的所有商户号都可以正常使用的; 如果你是通过代理服务器向微信支付发起请求的话,那么需要修改代理服务器的配置。 7. 联系我们 如果商户在验证或者修正问题的过程中遇到困难,可在证书与密钥专区发帖咨询,我们会有专人进行解答回复。 8. 附录 DigiCert 原文公告:DIGICERT ROOT AND INTERMEDIATE CA CERTIFICATE UPDATES 2023
2024-09-03 - 微信网页授权能力调整公告
微信网页授权 能力是为了优化用户在微信内登录网站应用的体验而设计的。为进一步规范能力使用,保障用户合法权益,平台将对能力进行调整。 当开发者在网页中在不规范使用发起 snsapi_userinfo 网页授权时,微信将默认打开网页快照页模式进行基础浏览。能力调整将于 2022 年 7 月 12 日 24 时生效。 网页快照页模式介绍快照页将会默认对用户屏蔽网页授权弹窗,用户在快照页中仅可进行滑动浏览操作,其他交互将被限制,并提示用户 “该网页需获取个人信息才可使用完整服务,当前仅可浏览部分内容”。用户如需要使用完整网页服务,可轻触右下角 “使用完整服务” 按钮触发授权弹窗,用户确认后进入原网页。 开发者在快照页内所获取的头像、昵称、openId、unionId 均为虚拟账号数据;快照页与正常页面不共用缓存,快照页的缓存会在用户离开快照页时被清理;快照页内也无法使用微信其它 JS-SDK 的能力。 [图片] 微信网页授权规范授权流程需引导清晰、准确:在申请获取用户信息的弹窗出现前,应该清晰、准确地告知用户获取信息的范围及获取信息的目的;必要场景申请:在必须获取用户信息时才申请,而不是用户尚未了解服务前就强制弹窗。如使用医院挂号时才需要获取用户信息;不强制登录:提供游客模式,供用户了解网页提供的基础服务,不强制用户允许网页获取用户信息后才能使用网页服务。 常见的微信网页授权不规范使用案例强制登录:在用户打开网页时立即要求用户授权,用户拒绝后无法使用网页提供的服务;违规收集个人信息:未在网页提前告知使用个人信息的目的、方式和范围;非必要收集:非必要获取用户信息的网页,如文章、视频等,要求用户在浏览内容前登录;差别对待微信用户:同样的网页在浏览器内可以无需登录直接访问,在微信内却要求用户先登录才可访问。 微信团队 2022年5月9日
2022-05-10 - 微信开放平台创建第三方平台并绑定管理员账号后,为什么无法生成appsecret和加入告警群?
微信开放平台创建第三方平台(appid:wxd5586a2fc1debc60)并绑定管理员账号后,为什么无法生成appsecret和加入告警群? 页面上看到已经绑定了管理员。 [图片] 但是扫码后仍然提示:“请使用绑定的管理员微信号进行验证” [图片] [图片] 同时告警群无法扫码进入,提示:“Invitation is invalid as the inviter has violated the WeChat Acceptable Use Policy.” [图片]
2021-10-13 - [第三方平台]授权后回调URI对redirect_uri中的自定义参数转义错误导致回调失败
在该页面内,有如下说明: https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Authorization_Process_Technical_Description.html “方式二:点击移动端链接快速授权 第三方平台方可以生成授权链接,将链接通过移动端直接发给授权管理员,管理员确认后即授权成功。” 其中,参数“redirect_uri”在“步骤 4:授权后回调 URI,得到授权码(authorization_code)和过期时间”时,如果redirect_uri中存在自定义参数并按&拼接,则其&会被微信服务器变成&,导致回调失败。 例子: 假设用户的redirect_uri为: http://127.0.0.1/test/?a=1&b=2&c=3 通过RFC 3986 URL编码后成为 http%3A%2F%2F127.0.0.1%2Ftest%2F%3Fa%3D1%26b%3D2%26c%3D3 拼接后得到移动授权链接: https://mp.weixin.qq.com/safe/bindcomponent?action=bindcomponent&auth_type=3&no_scan=1&component_appid=xxxx&pre_auth_code=xxxxx&redirect_uri=http%3A%2F%2F127.0.0.1%2Ftest%2F%3Fa%3D1%26b%3D2%26c%3D3&auth_type=xxx&biz_appid=xxxx#wechat_redirect 最终回调时,微信服务器把redirect_uri中的&变成&,导致返回如下地址: http://127.0.0.1/test/?a=1&b=2&c=3&auth_code=xxxxxxxxxxxxxxxxxx&expires_in=3600 结果第三方平台无法获取自定义参数b和c,导致回调业务失败。 =============== 查了查,这个bug似乎很早有人提,但不知道为什么没人受理。 相关例子:https://developers.weixin.qq.com/community/develop/doc/0004a019c24f48fdfba74d84551000
2020-05-19