- 答题抽奖活动发零钱被薅的真实案例分析
答题抽奖活动发零钱被薅的真实案例分析 ~ 有山东地震局举办的防灾减灾宣传周答题活动已于昨天落下帷幕,整个活动6天时间,累计用户33万人,答题人次51万,活动期间第二天由于设计上的缺陷出现过2个小时的异常,整体还是很顺利的 整个活动六天未出现因个人逻辑导致的问题,也未更新新的版本 [图片] [图片] [图片] 图片占位 今天分析的重点是答题抽奖发红包过程中,红包差点被薅的一个细节 大家看下图 [图片] [图片] [图片] 通过上图大家看的很清晰了,该用户分别试探了三次提现发起请求,金额分别为100、20、10 也就是说用户在反复试探我们单日设置的金额大小 而我们根据该用户的openid,排查到用户仅仅中了一个3毛钱的小红包 虽然最后用户没有薅成功,但是这足以提醒我,目前发放红包鉴权机制是不安全的,很容易被人盗刷掉里面的资金 今天重新设计了下这个红包发放的校验规则 [图片] 其实这个生成签名方案已经很成熟了,应用在三方接口的鉴权上 图片占位 [图片]
2023-05-13 - 删除部分微信用户个人数据的通知,怎么处理?
尊敬的开发者: 由于部分微信用户已完成微信帐号注销程序,成功注销的微信用户将无法使用其微信帐号登录或使用你的移动应用、网站应用、公众号或小程序,现向你发出本通知,相关用户情况已经附于附件。 针对本通知附件所列的已注销微信用户,请依法依规及时履行相应个人信息保护义务,保护用户权益。 你也可以接入事件通知,实时接收授权用户注销完成通知: 小程序:小程序授权用户信息变更; 公众号:公众号授权用户信息变更; 移动应用:移动应用授权用户信息变更; 网站应用:网站应用授权用户信息变更。 微信团队 2022.12.19
2023-01-10 - 2022年小程序开发年终总结
2022年年终总结 ~ 今年还是深耕答题活动的一年,盘点下来主要做了这么几件事 1、打通了小程序答题-抽奖-下发红包的产品生态闭环流程; 2、承担了超过30万人的答题活动; 3、新推出二款答题活动小程序作品,基本按半年出一款产品的节奏,具体是以下二个 1)陕建 2)健康中国 恰逢二十大召开,这二款小程序在二十大答题活动中特别受欢迎。 [图片] [图片] [图片] 今年承担了太多的答题活动,趋势是总体向好的,但是由于疫情,部分线上活动也受影响没有落地,在这么多活动中印象深刻的有以下几个 1)威海答题活动 这个小程序是我做用户答题-抽奖-发零钱的第一个产品 但是活动过程中遇到羊毛党,由于产品存在疏漏导致在活动第一天活动被多薅走拉4000元的红包,这次问题出在并发上,针对该问题后面也针对性的进行了部分优化, 在后面的答题场景都是符合预期的。 2)某重工集团二十大答题活动 该活动由于使用个人资质搭建,导致在活动上线第一天便被下架了,造成了极其不好的影响 [图片] 具体见下文 文章1 健康中国知行大赛活动小程序? - 微信开放社区 https://developers.weixin.qq.com/community/develop/article/doc/000a42b88d07e8b6999e8f80f56013 文章2 党史知识学习答题小程序类目问题? - 微信开放社区 https://developers.weixin.qq.com/community/develop/article/doc/000eae071b48905ac4ce518b456013 ~ 2022年小程序开发年终总结
2022-12-11 - 还在为开发调试头疼?来来来,这里有一份微信支付APIv3脚本,真金白银开源了!
脚本名称: Name:微信支付 APIv3 脚本说明: 本脚本是基于 微信支付 APIv3 的 Postman请求前置脚本(Pre-Request Script)进行完善,补充了微信支付普通商户所有已知公开接口,每个接口请求预置了请求参数示例与请求成功返回的参数示例,帮助商户开发者、测试人员以及小白用户也可以快速上手。 仅修改原脚本变量为常用叫法,无其他修改部分: merchantId->mchid merchantSerialNo->merchant_serial_no merchantPrivateKey->apiclient_key.pem 使用前提条件 postman,建议注册一个账户,便于使用它各种功能,例如同步。 有一个微信支付商户号,支持微信支付直连普通商户、微信支付直连特约商户,不支持微信二级子商户。 商户 API 私钥与商户证书序列号:商户API私钥是在商家平台申请商户API证书时,会生成商户私钥,并保存在本地证书文件夹的文件 apiclient_key.pem 中,商户商户序列号可在商家平台->账户中心->API安全->管理API证书查询到。 快速开始 1、使用Fork 方式导入脚本 1.1、点击[图片]进入向导,如下图所示。 [图片] 1.2:点击 Fork Collection 进入下一步,填入标签 Fork Label 并选择目的工作台 Workspace。一般情况下,导入个人工作台 My Workspace 即可。 如未登录账户,会跳转到账户登录页面,如无账户建议先去注册一个 [图片] 1.3点击 Fork Collection 完成导入。在你指定的 workspace 中可以看到《微信支付 APIv3》了。 [图片] 2、配置Environment 环境(Environment) 是一组变量 (Varibles) 的集合。 脚本从环境中读取变量,用来计算请求的签名。 你可以从《微信支付 APIv3》提供的 商户参数模版 中 fork 一个空环境到自己的工作台。 [图片] 接下来,在你工作台的 Enviroments 中找到新建的环境,点击 Add a new varialbe 添加新的变量: 变量名 是否必填 描述 备注 server_url 必填 微信支付接口域名 固定值:https://api.mch.weixin.qq.com mchid 必填 微信支付商户号 纯数字 merchant_serial_no 必填 商户 API 证书序列号 apiclient_key.pem 必填 PEM 格式的商户 API 私钥 以 -----BEGIN PRIVATE KEY----- 开始的 PEM 格式的商户 API 私钥。 appid 必填 用于微信支付接口请求中的APPID APPID需要与填写的mchid有绑定关系 openid 选填 用于微信支付接口请求中的openid 如不配置全局变量,请求时需要将参数中的变量openid替换为实际openid值 一组常见配置如下图所示: [图片] 3、发送测试请求 此处建议,使用桌面版 Postman app 发送请求,速度更快,体验更好! 现在回到工作台的请求构造界面,填入请求方法、URL、请求参数、Body 等参数。 工作台预置了微信支付普通商户所有请求样例供开发者参考,开发者也可以参考请求样例,构造自己的请求。 最后,选择你之前配置的 Environment,再点击地址栏右侧的Send按钮,发送请求。 [图片] 常见问题 1、发送请求时遇到错误提示“Error: Too few bytes to parse DER.”或者“Too few bytes to read ASN.1 value.” A:通常是环境 Environments 里配置的变量 merchantPrivateKey 填写有误导致的。脚本接收的私钥,以 -----BEGIN PRIVATEKEY----- 开始,以 -----END PRIVATE KEY----- 结束的一串字符串。 2、为什么我发送请求很慢? A:如果你使用的网页版 Postman,请使用桌面版 Postman app。因为浏览器中跨域资源共享(CORS)的限制,网页版发送请求是由 Postman 后台中转的。 WeChatPay Developers QQ Group ID:684379275
2022-11-08 - 小程序用户头像昵称获取规则调整公告
更新时间:2022年11月9日由于 PC/macOS 平台「头像昵称填写能力」存在兼容性问题,对于来自低于2.27.1版本的访问,小程序通过 wx.getUserProfile 接口将正常返回用户头像昵称,插件通过 wx.getUserInfo 接口将正常返回用户头像昵称。 更新时间:2022年9月28日考虑到近期开发者对小程序用户头像昵称获取规则调整的相关反馈,平台将接口回收的截止时间由2022年10月25日延期至2022年11月8日24时。 调整背景在小程序内,开发者可以通过 wx.login 接口直接获取用户的 openId 与 unionId 信息,实现微信身份登录,支持开发者在多个小程序或其它应用间匿名关联同一用户。 同时,为了满足部分小程序业务中需要创建用户的昵称与头像的诉求,平台提供了 wx.getUserProfile 接口,支持在用户授权的前提下,快速使用自己的微信昵称头像。 但实践中发现有部分小程序,在用户刚打开小程序时就要求收集用户的微信昵称头像,或者在支付前等不合理路径上要求授权。如果用户拒绝授权,则无法使用小程序或相关功能。在已经获取用户的 openId 与 unionId 信息情况下,用户的微信昵称与头像并不是用户使用小程序的必要条件。为减少此类不合理的强迫授权情况,作出如下调整。 调整说明自 2022 年 10 月 25 日 24 时后(以下统称 “生效期” ),用户头像昵称获取规则将进行如下调整: 自生效期起,小程序 wx.getUserProfile 接口将被收回:生效期后发布的小程序新版本,通过 wx.getUserProfile 接口获取用户头像将统一返回默认灰色头像,昵称将统一返回 “微信用户”。生效期前发布的小程序版本不受影响,但如果要进行版本更新则需要进行适配。自生效期起,插件通过 wx.getUserInfo 接口获取用户昵称头像将被收回:生效期后发布的插件新版本,通过 wx.getUserInfo 接口获取用户头像将统一返回默认灰色头像,昵称将统一返回 “微信用户”。生效期前发布的插件版本不受影响,但如果要进行版本更新则需要进行适配。通过 wx.login 与 wx.getUserInfo 接口获取 openId、unionId 能力不受影响。「头像昵称填写能力」支持获取用户头像昵称:如业务需获取用户头像昵称,可以使用「头像昵称填写能力」(基础库 2.21.2 版本开始支持,覆盖iOS与安卓微信 8.0.16 以上版本),具体实践可见下方《最佳实践》。小程序 wx.getUserProfile 与插件 wx.getUserInfo 接口兼容基础库 2.27.1 以下版本的头像昵称获取需求:对于来自低版本的基础库与微信客户端的访问,小程序通过 wx.getUserProfile 接口将正常返回用户头像昵称,插件通过 wx.getUserInfo 接口将正常返回用户头像昵称,开发者可继续使用以上能力做向下兼容。对于上述 3,wx.getUserProfile 接口、wx.getUserInfo 接口、头像昵称填写能力的基础库版本支持能力详细对比见下表: [图片] *针对低版本基础库,兼容处理可参考 兼容文档 请已使用 wx.getUserProfile 接口的小程序开发者和已使用 wx.getUserInfo 接口的插件开发者尽快适配。小游戏不受本次调整影响。 最佳实践小程序可在个人中心或设置等页面使用头像昵称填写能力让用户完善个人资料: [图片] 微信团队 2022年5月9日
2023-09-26 - 小程序全局状态管理工具
项目说明 原生微信小程序全局状态管理工具,轻量,便捷,高性能,响应式。 npm链接 :https://www.npmjs.com/package/@savage181855/mini-store 安装 [代码]npm i @savage181855/mini-store -S [代码] 快速入门 在[代码]app.js[代码]文件调用全局 api,这一步是必须的!!! [代码]import { proxyPage, proxyComponent } from "@savage181855/mini-store"; // 代理页面,让页面可以使用状态管理工具 proxyPage(); // 代理页面,让组件可以使用状态管理工具 proxyComponent(); // 这样子就结束了,很简单 [代码] 定义[代码]store.js[代码]文件,模块化管理 [代码]import { defineStore } from "@savage181855/mini-store"; const useStore = defineStore({ state: { count: 0, }, actions: { increment() { this.count++; }, }, }); export default useStore; [代码] [代码]indexA.js[代码]页面 [代码]// 导入定义的 useStore import useStore from "../../store/store"; Page({ // 注意:这里使用 useStore 即可,可以在this.data.store 访问 store useStoreRef: useStore, // 表示需要使用的全局状态,会自动挂载在到当前data里面,自带响应式 mapState: ["count"], // 表示想要映射的全局actions,可以直接在当前页面调用 ,例如:this.increment() mapActions: ["increment"], watch: { count(oldValue, value) { // 可以访问当前页面的实例 this console.debug(this); console.debug(oldValue, value, "count change"); }, }, onIncrement1() { // 不推荐 this.data.store.count++; }, onIncrement2() { this.data.store.patch({ count: this.data.store.count + 1, }); }, onIncrement3() { this.data.store.patch((store) => { store.count++; }); }, onIncrement4() { this.data.store.increment(); }, }); [代码] [代码]indexA.wxml[代码] [代码]<view> <view>indexA</view> <view>{{count}}</view> <button type="primary" bindtap="increment">+1</button> <button type="primary" bindtap="onIncrement1">+1</button> <button type="primary" bindtap="onIncrement2">+1</button> <button type="primary" bindtap="onIncrement3">+1</button> <button type="primary" bindtap="onIncrement4">+1</button> </view> [代码] [代码]indexB.js[代码]页面 [代码]// 导入定义的 useStore import useStore from "../xxxx/store.js"; Page({ // 注意:这里使用 useStore 即可,可以在 this.data.store 访问 store useStoreRef: useStore, // 表示需要使用的全局状态,会自动挂载在到当前data里面,自带响应式 mapState: ["count"], }); [代码] [代码]indexB.wxml[代码] [代码]<view> <view>indexB</view> <view>{{count}}</view> </view> [代码] 全局混入 [代码]app.js[代码]文件 [代码]import { proxyPage, proxyComponent } from "@savage181855/mini-store"; // 这里的配置可以跟页面的配置一样,但是有一些规则 // 'onShow', 'onReady', 'onHide', 'onUnload', 'onPullDownRefresh', 'onReachBottom', // 'onPageScroll', 'onResize', 'onTabItemTap'等方法,全局的和页面会合并,其余的方法,页面会覆盖全局的。 proxyPage({ onLoad() { console.debug("global onLoad"); }, onReady() { console.debug("global onReady"); }, onShow() { console.debug("global onShow"); }, onShareAppMessage() { return { title: "我是标题-- 全局", }; }, }); // 这里的配置可以跟组件的配置一样,但是有一些规则 // 'created','ready','moved','error','lifetimes.created','lifetimes.ready', // 'lifetimes.moved','lifetimes.error','pageLifetimes.show','pageLifetimes.hide', // 'pageLifetimes.resize'等方法,全局的和组件会合并,其余的方法,组件会覆盖全局的。 proxyComponent({ lifetimes: { created() { console.debug("global lifetimes.created"); }, }, }); [代码] 代码片段 https://developers.weixin.qq.com/s/ZO0SX2mr7xDj
2022-10-15 - 视频号获取推流地址后它的有效期是多久?
刚刚 请问视频号的推流地址在开播前的有效期是多久? 我生成推流地址后几个小时才推,但是它好像失效了,得重新创建获取。 哪位大佬知道的话麻烦解答一下,谢谢~
2021-07-02 - 微信小程序实现i18n国际化能力的解决方案
需求背景介绍 现在有大量的外国客户会使用到我们的产品,从而产生了需要有通过切换语种达到显示不同语种文案的页面,用来满足外国客户的浏览使用。而如今市面上有很多流行的第三方库,可以实现这种能力,如vue-i18n。而微信原生小程序的运行环境是将WebViewe与AppService分层处理,所以需要自研一套支持在微信原生小程序技术框架上运行的i18n库。 设计概要 [图片] 主要模块。 实现一个下载进程器。保证多个相同的CDN请求时,只发一条CDN的正常下载。 实现一个观察者,用于在异步数据响应成功后通知相关的页面或组件进行更新。 实现一个缓存器,用于将CDN上获取的语言包内容缓存起来,避免重复请求。 实现一个i18n类,主要用于实例后的对外api整理。 实现一个package类,主要用于集成下载进程器、观察者、缓存器及实例后的api整理。 WXS(微信脚本),这个模块主要是实现i18n.t方法及与AppService层的通信。 主要的功能 i18n库提供install方法,用于集成在RPRM或未来的其它平台上。install方法返回一个i18n实例,该实例内置以下属性: 方法 作用描述 参数 备注 data 所有缓存的模块语言包内容,按package名分包。如:[代码]wx.rprm.i18n.data.package1[代码] [代码]wx.rprm.i18n.data.package2[代码] 不涉及 只缓存当前语种的语言包内容。 getCurrentLang() 获取当前语种的函数。 无 swtich({lang}) 全量切换语种。 {lang:string} use(options} 预加载模块语种 {package:string,version:string/number} globalConfig(config) 通过路由划分,实现全量配置模块描述。 object 开发者希望使用的方式 [代码]//语法 i18n.t('key','default',options:object|array) //具名格式 //对应的语言包格式 ... spec:'规格:{num}个' ... //I18n.t的使用方式 ... {{i18n.t('spec',{num:'100'})}} ... //结果 //规格:100个 //列表格式 //对应的语言包格式 ... spec:'规格:第{0}百零{1}个' ... //I18n.t的使用方式 ... {{i18n.t('spec', ['一','三'])}} ... //结果 //规格:第一百零三个 [代码] WXS(微信脚本) 由于i18n库涉及的模块比较多,所以这里说明WXS(微信脚本)模块是如何实现t方法及与AppService层实现通信能力。 如何在WXML上使用i18n.t方法 WXML上无法直接使用方法,所以要借助微信脚本(WXS)完成。声明一个WXS文件,在里面实现t方法,然后在WXML中引入这个WXS文件,其module的值设置为i18n。参考代码: [代码]//WXS function t(参数){ //实现功能 } module.exports = {t} [代码] [代码]//WXML <wxs src='路径/名称.wxs' module='i18n'></wxs> <view>{{i18n.t(参数)}}</view> [代码] 如何在微信脚本(WXS)上得到语言包内容 微信脚本(WXS)是WebView里的一个脚本,想得到AppService里的数据,是需要实现数据通信的能力。借助setData触发微信脚本(WXS)的WxspropObserver。 [图片] 参考代码: [代码]<wxs src='路径/名称.wxs' module='i18n'></wxs> <view change:prop="{{i18n.change}}" prop="{{langs}}"></view> [代码] [代码]//WXS function t(参数){ //实现功能 } function change(langs){ //langs参数就是AppService层的setData传递的值 } module.exports = {t} [代码] 上述代码的基本思路是,在view元素上的属性值绑定AppService层中data中的langs。用setData触发langs更新到Webview层的view元素上,然后用WxsPropObserver监听prop是否发生变化,变化了就触发i18n脚本模块中的change方法。change方法触发后会得到prop的值,也就是langs的值。 t方法格式化 [代码]... /** * 格式化列表 * 场景二:”Hello,{0}{1} = "Hello,world!" * */ var formatterByList = function(text, list = []) { //遍历数组 //利用正则将花括号内容捕获匹配的内容替换成对应下标的数组值。 return text; }; /** * 具名格式化 * 场景一:"Hello,{msg}" = "Hello,world“ * */ var formatterByName = function(text, names = {}) { //利用正则分析出花括号里的值 //在names对象里找到花括号里值的内容 return text; }; ... [代码] 总结 上述主要是说明如何在WXML使用t方法以及将语言包内容同步到微信脚本上。实际的项目中需要考虑到将i18n功能模块化,异步数据获取监听及通知到微信脚本,性能、缓存等问题。
2021-05-25 - 一种优雅的实现永久订阅的方法
一种优雅的实现永久订阅的方法 大家都知道,永久订阅是十分难申请的,对于普通企业或者个人那是不可能申请下来的,今天给大家推荐一个小程序,很优雅的通过一次性订阅消息,实现了永久订阅的目的 这也是我时常拿来学习的一个经典案例 ~ [图片] ~ 小程序一次性订阅还可以这样玩 [图片] ~ 确实,不然一次性订阅太难用了 [图片] ~
2022-03-29 - 小程序隐私协议内容大家一定要谨慎填写
隐私协议内容大家一定要谨慎填写 ~ 相信这几天有提审小程序的用户都知道,11月份开始新增了隐私协议,有时候大家可能很随意的写了,其实这个是公开的,所以有些信息尽量慎重填写 特别是联系方式 [图片] ~ 其实我也是无意发现的, 今天我开发的考研刷题小程序上线了,在小程序的个人资料页,有一个更多资料的入口,在里面就可以查看我们填写的隐私协议的全部内容,如果有填写手机号,那么很明显,这部分信息就被公开了 [图片] 具体截图如下所示 ~ [图片] ~ [图片] ~ [图片] ~ [图片] ~ 官方文档 https://developers.weixin.qq.com/miniprogram/dev/framework/user-privacy/ 2)https://mp.weixin.qq.com/cgi-bin/announce?action=getannouncement&announce_id=11635415206bnRKn&version=&lang=zh_CN&token= [图片] ~
2021-11-07 - 分享小程序在app.js中全局管理websocket方案
社区有网友提问怎么在路由切换时保持websocket连接不中断?,我在回答中分享了我在实际项目中使用websocket的方案,这边整理一下。 主要思路是在app.js中全局处理websocket的连接和接收消息,收到消息后再把消息转发到页面,实际用到消息的页面接收消息做后续处理。具体代码如下 要引入mitt.js,百度一下,一个很小的文件(具体代码在文章最后) app.js [代码]const mitt = require('./utils/mitt').mitt ... App({ ... onLaunch: function () { let that = this that.globalData.bus = mitt() ... //连接socket ... //收到消息的回调中 if (msg.length > 0) { that.globalData.bus.emit('_socketMsg', msg) } ... } ... }) [代码] 要用到消息的页面 [代码]const app = getApp() ... Page({ ... socketMsg: function(msg){ //实际处理收到的消息 }, onShow: function () { let that = this app.globalData.bus.on('_socketMsg', that.socketMsg) ... }, onHide: function () { let that = this app.globalData.bus.off('_socketMsg', that.socketMsg) ... }, ... }) [代码] 附:mitt.js [代码]function mitt(all) { all = all || Object.create(null); return { on(type, handler) { (all[type] || (all[type] = [])).push(handler); }, off(type, handler) { if (all[type]) { all[type].splice(all[type].indexOf(handler) >>> 0, 1); } }, emit(type, evt) { (all[type] || []).slice().map((handler) => { handler(evt); }); (all['*'] || []).slice().map((handler) => { handler(type, evt); }); } }; } module.exports = { mitt: mitt } [代码]
2021-07-08 - 变更开放平台,如何把开放平台下的小程序、公众号、APP从老账号切换为新账号,直接解绑后再绑定新的吗?
背景:当前开放平台老账户下有小程序、公众号、APP,需要都迁移到新的开放平台账号下,两个开放平台主体不一样。 问 1、迁移后,openID、unionID是否都会发生改变? 2、如何迁移?迁移过程是否会影响线上使用?
2020-08-07 - [拆弹时刻]4月13日前更新wx.getUserInfo和getUserProfile授权获取问题的解决方案
[图片] 论坛里有不少人疑惑新版的getUserProfile是不是已经上,同时发现开发环境中原有的老方法已经不支持了,这里我为大家集中解决下疑惑~ 1、线上是否已经不支持wx.getUserInfo老方法了? 支持!目前,根据官方文档说明:在4月13日前发布的,线上环境2.16.0基础库以下已经不支持老版方法。(4月8日更新,怀疑官方已提前发布) [图片] 本人今天4月6日10点半线上支持老方法,但是4月8日发布2.16.0以下低版本已经去掉弹窗授权了。请大家尽快更新发布新版方法 2、哪些环境已经是新方法了? 开发环境(包括但不限于IDE工具,真机调试),微信后台提供的体验版环境,且已不支持老办法。 3、新老两种方法是否并行? 线上环境:目前并行(4月13日前),但getUserProfile新方法 只在2.10.4以上版本支持。 开发环境和体验版:不并行,不支持左右横跳哈。 4、如何解决兼容性适配? 上才艺啦,呸,上代码。 先来看下原本代码的授权逻辑 [代码]//老的逻辑 wx.getSetting({ async success(res) { console.log(res.authSetting); //判断小程序用户是否授权 if (res.authSetting['scope.userInfo']) { //已授权 } else { //未授权情况 } } }) [代码] 之前主要通过wx.getSetting的方法来判断,而现在重大的改变是老方法getUserInfo不再弹窗,就算改成getUserProfile弹窗授权,新方法中getSetting中scope.userInfo 这个值并没有返回(这里跟文档有些出入,不知道官方后面会不会修正) [图片] [图片] 同时,这里需要做兼容判断,把获取到内容存在数据库中,避免反复弹窗骚扰用户。 [代码]//根据官方文档 做了一些修改 Page({ data: { userInfo: {}, hasUserInfo: false, canIUseGetUserProfile: false, }, onLoad() { //先请求自定义接口,获取上次存的useInfo wx.request({ url: 'test.api', //仅为示例,并非真实的接口地址 data: {}, success (res) { console.log(res.useInfo) //判断之前是否已获取并存储过用户信息 if(res.useInfo){ }else { //这里不要使用 wx.canIuse来判断,避免一些适配问题 if (wx.getUserProfile) { //直接使用官方推荐的方法 this.setData({ canIUseGetUserProfile: true }) } } } }) }, getUserProfile(e) { // 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认 // 开发者妥善保管用户快速填写的头像昵称,避免重复弹窗 wx.getUserProfile({ desc: '需要你的信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写 success: (res) => { //这里需要将获取的 res.userInfo 存起来,你可以存在数据库,也可以存在local storage里 //wx.request...请求接口 this.setData({ userInfo: res.userInfo, hasUserInfo: true }) } }) }, getUserInfo(e) { // 不推荐使用getUserInfo获取用户信息,预计自2021年4月13日起,getUserInfo将不再弹出弹窗,并直接返回匿名的用户个人信息 this.setData({ userInfo: e.detail.userInfo, hasUserInfo: true }) }, }) [代码] [代码]<!-- html部分 ---> <block wx:if="{{!hasUserInfo}}"> <button wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile"> 获取头像昵称 </button> <button wx:else open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 获取头像昵称 </button> </block> <block wx:else> <image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image> <text class="userinfo-nickname">{{userInfo.nickName}}</text> </block> [代码] [图片] 5、如何更新用户信息? 首先,目前的规则如果不弹窗,肯定是无法每次拿到用户的最新信息,为了避免每次弹窗请求授权骚扰用户,所以最好根据产品规划,定期获取用户的信息(看心情)。 6、官方接口文档 https://developers.weixin.qq.com/community/develop/doc/000cacfa20ce88df04cb468bc52801 觉得有用,请点个赞哦,让我继续分享更有动力~
2021-04-08 - 纪录一个增加订阅次数的交互方案
普通小程序没有长期订阅消息,只能按照用户订阅次数发送订阅消息。如果订阅次数用完了怎么办呢? 可以让用户多点几次订阅,就可以做到了,但是这个操作对用户来说还是不太方便。怎样设计交互,让用户做起来不那么麻烦,是需要好好考虑的事情。 最近正好看到ReadHub的订阅方式,截图纪录一下。 [图片][图片][图片] 首先提醒用户,通知次数用完了,需要手动点击订阅,增加订阅次数。第一次会申请两个订阅,“每日早报提醒”和“订阅次数耗尽提醒”。用户点击允许以后,会发现可以接收的次数变成1了。 [图片][图片] 再次点击增加通知次数,从第二次开始,只申请一个“每日早报提醒”,每操作一次,订阅次数+1。点多了以后,嫌麻烦索性选中“总是保持以上选择,不再询问”,然后狂按增加订阅次数,会发现增加的次数并没有那么快,应该是每次订阅服务器端都要纪录一下才能展示出来,也就是说每次点击都落到数据库了。这样大概每秒1次,我点这21下也花了接近一分钟时间,不是一个可以忽略的操作。 更多参考: 云开发·多次订阅一次性订阅消息后定时发送
2021-03-08 - 微信 schema 跳转之非官方文档
微信“应该”是最近开放了 schema 跳转小程序 的能力,大大方便了短信、邮件、外部网页等唤起微信小程序。 schema 链接格式大体是这样:[代码]weixin://dl/business/?ticket=l69894d682fa8dbafe724a0ca3950741e[代码],但是这段文本在安卓端无法识别。小规模测试结果如下: [图片] 后来想到用一个正常能够识别的网页地址,内容是重定向到指定的 schema 链接。这就是擅长的领域了,query 参数上带上 schema 链接,location.href 一下不就行了。这里就不 show 代码了,能看到文章的你一定行。 但是,发现在部分安卓手机下(如小米)还是没反应,原来简单的 schema 跳转水这么深的,于是百度谷歌了一下,找到了下面两份关键材料: H5唤起APP进行分享的尝试 AlanZhang001/H5CallUpNative: H5端唤醒移动客户端程序 看源码也不多,总结下来,因不同系统和浏览器对 schema 规范的理解不同,还有一些商业因素,不同环境下面需要用不同的方式进行跳转,甚至有的环境你根本就跳不了。 时间紧,任务重。简单处理吧,不同方式都来一遍,谁好使就用谁。所以简单总结了下,能用的几种方式: location 跳转 a 链接跳转 iframe 跳转 以上三种方式,逐一试用,最后实在不行就不行吧,简单处理,看有没有大神补充的。 相关代码如下: location [代码]location.href = "weixin://dl/business/?ticket=l69894d682fa8dbafe724a0ca3950741e"; [代码] a 链接跳转 [代码]var aLink = document.createElement("a"); aLink.className = 'call_up_a_link'; aLink.href = "weixin://dl/business/?ticket=l69894d682fa8dbafe724a0ca3950741e"; aLink.style.cssText = "display:none;width:0px;height:0px;"; document.body.appendChild(aLink); aLink.click(); [代码] iframe [代码]var iframe = document.createElement('iframe'); iframe.className = 'call_up_iframe'; iframe.src = "weixin://dl/business/?ticket=l69894d682fa8dbafe724a0ca3950741e"; iframe.style.cssText = "display:none;width:0px;height:0px;"; document.body.appendChild(iframe); [代码] 以上代码均可从参考资料中找到出处,感谢 是直接一进来就执行,还是事件触发,都可以。或者是一开始进来就执行,失败了显示几个可选跳转按钮让用户手动触发跳转。 但是关键问题还有一个,如何判断是可以成功唤起了呢?上述 github 代码里提到了一个根据页面 hidden 状态,但不够精准,如果用户没有选择跳转到微信呢?这是另一个需要深究的问题。 出于时间考虑,先以业务交付优先,如果有朋友知道的也可以一起讨论下。 另行文时间短,以技术交流为主,若有瑕疵,欢迎指出。 附上 vue 版本源码:微信 schema 跳转 参考链接: 微信官方文档:urlscheme.generate H5唤起APP进行分享的尝试 AlanZhang001/H5CallUpNative: H5端唤醒移动客户端程序 安卓端,微信schema无法跳转微信小程序?
2021-01-04 - 优雅解决:关于app.js的onLaunch 与 页面的onLoad 的异步问题
// 常见的场景:打开小程序时要先获取用户数据,再调其他接口 // 步骤: // 1、获取openid // 2、根据openid获取用户数据 // 3、获取到用户数据后 再 调取其他接口 啥也别说,直接看代码吧: 实际开发会把很多步骤合并,我这展示就每一步详细说明 [图片] [图片] [图片] [图片] -------分割线--------------------- 以上为app.js页面------------ 页面index.js(打开小程序页面栈的第一个页面) [图片] 总结:原理就是跨页面调用而已。该方法也可以使用在扫码进入的场景。只需在目标页面加上接收数据的函数init即可。
2020-12-16 - 《小程序云开发挑战赛获奖作品》 附体验二维码.附链接
校园赛道 [图片] 职业赛道 [图片] 校园赛道1. QSCamera微信小程序QSCamera面向浙江大学校级学生组织求是潮的摄影部及视频团队两个部门,用于部门内或跨部门的器材借还登记、借用记录查询、当前器材状态查询等场景,本文从12个方面全面的介绍了该款小程序 https://developers.weixin.qq.com/community/develop/article/doc/0006a8dd4f89684f45fad49fc56c13 [图片] 2.BJUT活动助手BJUT活动助手 Activity Helper,一个基于北京工业大学校园内的各项信息开发的一款集报名、统计、汇总、浏览于一体的活动助手小程序。 https://developers.weixin.qq.com/community/develop/article/doc/0000a40f544cc8ecaefadfaab56813 [图片] 3. 校园二手购 为了方便广大学生用户,不用在贴吧等地方发布二手交易,而是有一个官方的、专门的平台来提供给学生。小程序的使用者可以在校园二手购平台上发布闲置的物品,以供大家购买。用户可以浏览全部发布的商品,在自己喜欢的商品下面留言以取得和售主的联系,在双方都谈妥之后,就可以进行线下交易。 https://developers.weixin.qq.com/community/develop/article/doc/000e0676d484384bb1fa76e2156413 [图片] 4.大学校园闲置物品交易平台在大学校园闲置物品交易平台中,大学生能够在不涉及线上支付的情况下安全快捷地出售与购买二手物品。 https://developers.weixin.qq.com/community/develop/article/doc/000a04e79a4778f919fa2674e56413 5. 校拍我们的校拍小程序和同名公众号主要是为了展示用户的学校的校园美景以及分享各种摄影入门小技巧,吸引更多的摄影爱好者来使用我们的小程序,通过发布自己拍的美景以及视频来更好的宣传用户的学校。 https://developers.weixin.qq.com/community/develop/article/doc/0008ce45f6c5d010c0faaab4c5b013 [图片] 职业赛道1. 情侣券恋爱必备 https://developers.weixin.qq.com/community/develop/article/doc/000002afb882701ca0fa756585b813 [图片] 2. 宝宝约玩 实现线下绘本馆线上线下一体化,将常规绘本馆的会员体系、仓储管理线上化,同时增加线上借阅服务及社区能力,实现绘本馆的线上线下一体化服务,为绘本馆打造借阅一站式服务解决方案。 https://developers.weixin.qq.com/community/develop/article/doc/000c6a6abb4cd81ab1faad17c5d013 [图片] 3.我存我存小程序,留住世间一切美好.实现线下绘本馆线上线下一体化,将常规绘本馆的会员体系、仓储管理线上化,同时增加线上借阅服务及社区能力,实现绘本馆的线上线下一体化服务,为绘本馆打造借阅一站式服务解决方案。 https://developers.weixin.qq.com/community/develop/article/doc/000228e8948d68897bfa0d2f75b413 [图片] 4. 魅力单词魅力单词是一款面向学生的背单词小程序,提供了丰富的单词词库以及好玩的背单词模式。 https://developers.weixin.qq.com/community/develop/article/doc/0000ca7a0806d0e584fa11f055f413 [图片] 5. 自助心理成长利用自己的力量,觉察自己的内心,应用心理学知识,使我们此刻更心安,未来更幸福 https://developers.weixin.qq.com/community/develop/article/doc/0000ceafce43c010c7fa7cf4d58c13 [图片] 感谢您的阅读~
2020-11-06 - 开源成语答题小程序安装教程 小白搭建教程
搭建开源成语答题小程序,首先需要以下几个准备工作: [图片] 一、注册微信小程序 注册地址:https://mp.weixin.qq.com/cgi-bin/registermidpage?action=index&lang=zh_CN&token= 二、下载微信开发者工具 下载地址:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html 三、下载开源成语答题小程序代码 下载地址:https://gitee.com/yingwuniao/chengyu [图片] 点击其中的下载按钮就可以下载成语答题小程序文件,下载需要登录账号,没有码云账号可以注册一个,最后希望大家给作者点个star [图片] 准备工作完成后,下面我们就开始搭建成语答题小程序 打开微信开发者工具,点击左上角头像用微信扫码登录后 ,点击新建项目-》会弹出新建页面 [图片] 点击图中的加号按钮,会弹出新建项目节目 [图片] 项目名称输入你注册小程序的名称,项目目录选择一个电脑上的空文件夹,或新建一个文件夹选择。AppID填写小程序注册后的appid。 在微信公众平台登录小程序后查看,到开发->开发设置里面就可以看到appid,如图: [图片] 输入appid后,后端服务选择云开发,点击新建按钮就可以生成小程序项目文件,然后将下载好的成语答题小程序文件解压,将文件全部复制到刚才新建项目的那个目录,会弹出[图片] 点击是全部覆盖,然后打开微信开发者工具,就默认打开这个项目,没有打开就点击项目重新打开 打开后可能大家和我的界面不一样,这是因为你们还没有开通云服务,点击下图中的箭头, [图片] 点击云开发会弹出一个开通云环境的界面,已经开通的可以省略,点击开通,输入环境id(这个环境id随便输字母,主要是为了给环境起名字)。 开通好后就进入云控制台,如下图: [图片] 点击数据库按钮后打开下图: [图片] 点击箭头的加好,弹出新建集合,输入chengyu,点击确定 [图片] 依次新建集合 chengyu goods user setting moreapp 建好后如下图显示: [图片] 点击上图中的数据权限依次改为所有用户可读,仅创建者可读写。如下图: [图片] 修改好集合和权限后就是导入数据了,点击集合名称,比如点击chengyu集合后会出现导入按钮,点击导入,弹出上传文件按钮,点击上传 [图片] 找到项目目录下的data目录,找到chengyu.json文件,如下图 [图片] 点击打开,然后确定就会导入数据,依次点击其他集合导入数据。成语答题小程序就正式配置完了。 以上有不懂的朋友可以联系锤哥解答,或到程序员锤哥公众号提问。 下期我会出成语答题小程序后台操作教程。如果你觉得好,欢迎打赏锤哥。
2020-10-25 - 开源成语答题小程序
开源成语答题小程序采用云开发,无需搭建服务器,无需域名即可使用云端能力。目前小程序集成微信banner广告,视频广告,插屏广告,激励视频广告等功能,方便运营者赚取广告收益.。 本开源成语答题小程序模仿成语答题赚小程序,首先感谢成语答题赚小程序作者能开发出如此好的作品,可以让我们更好的借鉴和学习。 猜成语答题小程序一直被很多人休闲娱乐,成语小秀才更是占据整个小程序榜单首位,成语简单又可以学习,让很多人都钟情于它。 本开源答题小程序代码有几大特点: 开发过程中考虑到云开发的免费额度,所以开发设计中以减少数据请求次数,减少云函数调用为特点,用更少的调用次数服务更多的用户。让免费额度可以服务更多的用户。 图片展示:[图片] [图片] [图片] 成语答题已完成功能 成语答题小程序成语答题发放红包(可设置几题发放红包,每题设置红包数额)观看激励视频获取金币(限制每天观看次数)成语答题小程序排行榜红包兑换物品设置更多软件推广集成banner 视频广告,插屏广告,激励视频广告等 开源成语答题小程序:https://gitee.com/yingwuniao/chengyu 开源闯关答题小程序:https://gitee.com/yingwuniao/chuangguan
2020-10-25 - 《我的军装照》用腾讯云AI人脸融合、腾讯云云开发军装照小程序
本文背景 迎庆建党100周年,建国71周年,建军93周年,营造爱党爱国爱军氛围.一键生成属于我的军装照. 小程序效果预览 [图片] 最终生成军装照效果 [图片] 资源准备 一、新建小程序云开发项目,并开通“珊瑚”图片内容安全 [图片] 二、登录腾讯云 AI 并开通人脸融合 API [图片] 三: 开通腾讯云云开发CMS [图片] 四、 云函数调用AI接口 ``` const tencentcloud = require("tencentcloud-sdk-nodejs"); const CvmClient = tencentcloud.cvm.v20170312.Client; const models = tencentcloud.cvm.v20170312.Models; const Credential = tencentcloud.common.Credential; let cred = new Credential("secretId", "secretKey"); let client = new CvmClient(cred, "ap-shanghai"); let req = new models.DescribeZonesRequest(); client.DescribeZones(req, function(err, response) { if (err) { console.log(err); return; } console.log(response.to_json_string()); }); ``` 总结 《我的军装照》开发核心内容有:小程序云开发、云开发 CMS 内容管理系统、腾讯 AI 开放平台、“珊瑚”图片内容安全。 [图片]
2020-10-01 - 开源 黑白图片上色 模糊照片变清晰
背景 之前给人家外包的黑白照片,这个哥们负了一点点款,然后开发完了就不要了 。没办法,到现在也没人要,我只能开源了,大家可以互相学习。欢迎start 使用到的技术 微信开发平台的云开发 以及第三方Api 百度Api 配置 云函数的配置 请先了解小程序云开发 百度key的配置 想审核ai平台的权限。需要[黑白图像上色]和【图像清晰度增强】这二个接口权限。 在云函数 getBaiduAccessToken的index.js中 把apiKey 替换为百度ai申请的appkey 把 secretKey替换成为 百度ai审核的secret秘钥然后更新云函数即可。 云数据库的配置 首先要创建token,index,user三个数据集 其他问题 简单的问题自行百度。如果还是不明白请留言 [图片][图片][图片] 开源地址:https://gitee.com/sunqi/bw
2020-09-25 - 基于微信小程序.云开发,互联网+餐饮解决方案
小程序码农们的福利来了! 第一次接触微信小程序云开发,就迷恋上她了。首先,她提供免费的基础版,降低用户的使用成本,无需考虑服务器的问题。其次,她融入了微信的生态,可以利用很多的资源。如果能够把云开发技术潜能激发,可以产生巨大的效益。我相信云开发在未来一两年会把大量SaaS平台干掉。在如此的诱惑下,我就产生了创业的念头,云开发+餐饮的解决方案。一方面通过成为微信支付服务商,发展特约商户,获得支付流水;另一方面为餐饮客户提供小程序定制服务。然而,梦想很美好,现实很残酷。新冠肺炎的爆发,餐饮行业受到重创,倒闭的倒闭,停业的停业。因此,我们的业务很难开展,粮草不足,创业失败! 经过一段时间的思想斗争,决定把项目开源,让更多的码农兄弟感受云开发的强大,同时避免采坑。 项目地址:https://git.weixin.qq.com/bmwkj/waiter-dev https://github.com/kem709394/waiter-dev 产品介绍:http://www.bmwkj.ltd [视频] [图片][图片][图片] 为特餐饮助手 基于微信小程序.云开发(serverless)技术 结合物联网云打印服务,实现低成本,高效能的互联网+餐饮解决方案 无需租用服务器,开通微信提供的云开发基础套餐(免费),即可搭建整套系统方案 为特餐饮助手的特点:简单、易用、高效、稳定、安全,最重要的是低成本。 功能特色: 点餐:扫描点餐、预定点餐、协助点餐、呼叫服务 外卖:配送外卖、自提外卖 订桌:预定餐桌 排队:排队取号 配送:配送跟踪 后台功能: 服务中心,提供服务员常用的功能,如服务员帮助客人下单,菜品状态更新,查看餐桌状况,自定义菜品价格(当菜品价格为时价,通过扫码获取价格),订单处理(接单、制作、取消、退款、完成等功能),排队取号和餐桌呼叫的处理,配送跟踪辅助功能(扫码取件,完成订单,退回订单,订阅派单通知等) 用户管理,管理微信用户的信息 职员管理,管理商户的职员,根据职务分配相应的操作权限 厨房管理,分配厨房打印机,如果厨房用到打印机,需要在此功能进入绑定 餐桌管理,管理餐桌的信息,可以在线生成点餐码 栏目管理,管理菜品的栏目,对菜品进行分类 菜品管理,管理所有的菜品,包括普通菜品、时价菜品(没有固定价格,通过扫码获取价格)、套餐菜品(由普通菜品进行组合),普通菜品和时价菜品可以设置出菜厨房,普通菜品可以设置多种规格和多种可选属性。 订单管理,管理所有的订单,包括点餐、外卖、订桌 公告管理,管理小程序的公告内容 反馈管理,管理用户提交的反馈内容 打印管理,管理云打印,绑定打印机的设备码,可以测试打印机 配送记录,管理配送记录,跟踪配送信息 支付记录,管理支付记录 统计报表,可统计内容包括订单数量,菜品销量,配送数量,有年月日三个维度选择 系统设置,对系统的参数进行设置 麻雀虽小五脏俱全,本解决方案能够满足大部分餐饮行业商户的需求。 由于微信提供的免费资源有限,本应用通过了长时间优化和验证,满足每天300单一下的商户免费使用。 serverless毕竟是新技术,使用过程中肯定会遇到很多坑,但总有解决的办法。 技术支持 [图片]
2020-07-20 - 微信小程序UI组件库合集
UI组件库合集,大家有遇到好的组件库,欢迎留言评论然后加入到文档里。 第一款: 官方WeUI组件库,地址 https://developers.weixin.qq.com/miniprogram/dev/extended/weui/ 预览码: [图片] 第二款: ColorUI:地址 https://github.com/weilanwl/ColorUI 预览码: [图片] 第三款: vantUI(又名:ZanUI):地址 https://youzan.github.io/vant-weapp/#/intro 预览码: [图片] 第四款: MinUI: 地址 https://meili.github.io/min/docs/minui/index.html 预览码: [图片] 第五款: iview-weapp:地址 https://weapp.iviewui.com/docs/guide/start 预览码: [图片] 第六款: WXRUI:暂无地址 预览码: [图片] 第七款: WuxUI:地址https://www.wuxui.com/#/introduce 预览码: [图片] 第八款: WussUI:地址 https://phonycode.github.io/wuss-weapp/quickstart.html 预览码: [图片] 第九款: TouchUI:地址 https://github.com/uileader/touchwx 预览码: [图片] 第十款: Hello UniApp: 地址 https://m3w.cn/uniapp 预览码: [图片] 第十一款: TaroUI:地址 https://taro-ui.jd.com/#/docs/introduction 预览码: [图片] 第十二款: Thor UI: 地址 https://thorui.cn/doc/ 预览码: [图片] 第十三款: GUI:https://github.com/Gensp/GUI 预览码: [图片] 第十四款: QyUI:暂无地址 预览码: [图片] 第十五款: WxaUI:暂无地址 预览码: [图片] 第十六款: kaiUI: github地址 https://github.com/Chaunjie/kai-ui 组件库文档:https://chaunjie.github.io/kui/dist/#/start 预览码: [图片] 第十七款: YsUI:暂无地址 预览码: [图片] 第十八款: BeeUI:git地址 http://ued.local.17173.com/gitlab/wxc/beeui.git 预览码: [图片] 第十九款: AntUI: 暂无地址 预览码: [图片] 第二十款: BleuUI:暂无地址 预览码: [图片] 第二十一款: uniydUI:暂无地址 预览码: [图片] 第二十二款: RovingUI:暂无地址 预览码: [图片] 第二十三款: DojayUI:暂无地址 预览码: [图片] 第二十四款: SkyUI:暂无地址 预览码: [图片] 第二十五款: YuUI:暂无地址 预览码: [图片] 第二十六款: wePyUI:暂无地址 预览码: [图片] 第二十七款: WXDUI:暂无地址 预览码: [图片] 第二十八款: XviewUI:暂无地址 预览码: [图片] 第二十九款: MinaUI:暂无地址 预览码: [图片] 第三十款: InyUI:暂无地址 预览码: [图片] 第三十一款: easyUI:地址 https://github.com/qq865738120/easyUI 预览码: [图片] 第三十二款 Kbone-UI: 地址 https://wechat-miniprogram.github.io/kboneui/ui/#/ 暂无预览码 第三十三款 VtuUi: 地址 https://github.com/jisida/VtuWeapp 预览码: [图片] 第三十四款 Lin-UI 地址:http://doc.mini.talelin.com/ 预览码: [图片] 第三十五款 GraceUI 地址: http://grace.hcoder.net/ 这个是收费的哦~ 预览码: [图片] 第三十六款 anna-remax-ui npm:https://www.npmjs.com/package/anna-remax-ui/v/1.0.12 anna-remax-ui 地址: https://annasearl.github.io/anna-remax-ui/components/general/button 预览码 [图片] 第三十七款 Olympus UI 地址:暂无 网易严选出品。 预览码 [图片] 第三十八款 AiYunXiaoUI 地址暂无 预览码 [图片] 第三十九款 visionUI npm:https://www.npmjs.com/package/vision-ui 预览码: [图片] 第四十款 AnimaUI(灵动UI) 地址:https://github.com/AnimaUI/wechat-miniprogram 预览码: [图片] 第四十一款 uView 地址:http://uviewui.com/components/quickstart.html 预览码: [图片] 第四十二款 firstUI 地址:https://www.firstui.cn/ 预览码: [图片]
2023-01-10 - 开源小程序-头像加口罩
来吧,请不要吝啬你的star [图片] 1、我不是作者,但是作者同意我在社区发帖,想联系作者的私聊我吧 2、开发环境:基于uniapp使用VUE快速实现 3、这个小程序从起名字到运营,基本走的是我的运营思路,2月份的时候我说过这个小程序,目前衍生比较完整,每月差不多4位数收益,累计用户10W+ [图片] 4、有图片安全检测,可放心使用 5、部分功能预览 [图片] [图片] https://github.com/infinityu/mina-wear-mask 不要吝啬你的STAR
2020-07-05 - 字符串转日期大坑请绕行
问题来源是这样的,由于最近开发的党建答题小程序的用时数据不对,我发了个版本来修复整个问题,但是发布上去之后,用我的苹果手机答题,用时竟然报NAN的的现象,但是我观察版本发布后,其他用户的答题用时数据却是正常的,具体看下面截图,用时这个地方,我们不难发现问题 [图片] 问题描述在苹果手机里面字符串转成日期的时候,会有问题,具体看下面截图 在下面截图里面date1、date2分别是通过time1、time2转换来的,但是都不是预期的效果, [图片] 参考文章小程序开发中,IOS与Android的坑,你踩过几个?? - 微信开放社区 https://developers.weixin.qq.com/community/develop/article/doc/000aee0c6c8f004bb41a77dfa5b413 微信小程序中的日期格式在Android和iOS真机下兼容性问题的坑? - 微信开放社区 https://developers.weixin.qq.com/community/develop/article/doc/000e2e82d14cd80838c9cb8b552013 微信小程序中的日期格式在Android和iOS真机下兼容性问题的坑? - 微信开放社区 https://developers.weixin.qq.com/community/develop/article/doc/000e2e82d14cd80838c9cb8b552013 不同手机对于字符串转换成日期处理不一样? - 微信开放社区 https://developers.weixin.qq.com/community/develop/doc/000a84689607b8cfe8474423f51c00 https://blog.csdn.net/xinyi_jin/article/details/88047165 解决方案将字符串里面的-进行替换,具体看下面代码 [图片] 总结真的没有想到,在测试都很到位的情况下,遇到了苹果手机的兼容性问题,而且在本地开发环境还不好发现。 所幸的是这次党建答题活动的用户并不多,具体到苹果用户那就更少了,我手工修复的还能凑合,目前修复版本已经提交了,希望快快审核通过吧 [图片][图片] 备注目前版本已发布,生产运行良好
2020-06-29 - 关于计时器,读秒,倒计时相关功能说明(wxTimer)
我推荐一个倒计时插件wxTimer,这个倒计时插件运用原生写法写了一个原型倒计时js,可拓展性十分的强大,但是网上资料甚少导致一些初学者看不懂文档,先放文档链接github: https://github.com/baqihg/wxTimer 文档里的内容还是要掰扯一下的,大家可能好奇,为什么我用了这一段倒计时不动了 var wxTimer = new timer({ beginTime:"00:00:10" }) wxTimer.start(this); wxTimer.stop(); wxTimer.stop();这个是停止的语法,在他的js文件原型里可以清楚的看到是包裹在外面的所以写在这里就是启动了一次又把他停止了,只需要去掉这个语法就可以读秒了。 还有就是写了一个button 绑定了bindtap事件去控制wxTimer.stop();可以发现并不生效,原因查看原型可知是wxTimer.stop();读不到停止的那个原型对象,如果你设定了倒计时为wxTimer,那你必须要要在page({})的外面事先声明这个量比如写var wxTimer 这样你就可以通过if(wxTimer ){wxTimer.stop();}找到这个计时器去停止这个倒计时了 这个倒计时是很好用的,页面隐藏后倒计时还是会进行,对读秒跳转和计时的功能有一定的帮助,可以添加在小程序的各个生命周期里,不过要事先做好销毁停止的处理
2020-06-16 - 如何实现快速生成朋友圈海报分享图
由于我们无法将小程序直接分享到朋友圈,但分享到朋友圈的需求又很多,业界目前的做法是利用小程序的 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 - 腾讯云智服客服系统快速上手指南
一、注册登录 1、首次注册 进入腾讯云智服官网yzf.qq.com,点击首页“注册”按钮,使用微信进行扫码,同意腾讯云智服的登录授权。(注:此扫码微信号即超级管理员账号。) Step1:进入官网,点击注册微信扫码,在手机上点击同意授权。 Step2:填写企业相关信息,所有信息均可在后台【设置】→【企业设置】修改,完成后点击下一步。 (温馨提示:腾讯云智服承诺对您填写的信息绝对保密,未经用户许可腾讯不会向第三方公开、透露用户个人和公司信息。腾讯对相关信息采用专业加密存储与传输方式,保障您和企业信息的安全。) Step3:注册完成后,点击“开始体验”登录,开始设置您的专属客服平台。(每个微信号最多可注册 50 个云智服帐号,可轻松管理多个企业。) 2、登录 使用微信扫码即可登录腾讯云智服。 二、邀请成员加入 服务团队基本成员角色包括:管理员、客服专员、机器人训练师。所有受邀同事的角色和每个角色可用权限均可由管理员修改。 首先设置客服分组和该组客服最大接入用户数量,以保证服务质量。 设置入口:【设置】→【团队设置】→【客服管理】 新建自定义分组,设置分组的名称与最大接入数。 [图片] 客服分组设置完成后,就可以邀请您的同事加入了。 设置入口:【设置】→【客服管理】→【邀请成员】 [图片] 将“邀请成员”页面的二维码或链接发送给同事,让其填写信息后提交申请。 同事完成申请后,管理员进入【申请列表】中审核。选择该同事对应的角色(必选、多选)与组别。 若一开始邀请成员后未设置分组,该同事归入默认分组。可在默认分组中选择该同事,点击【编辑】修改成员姓名、组别和角色。 三、接入渠道 腾讯云智服支持接入渠道有微信渠道(公众号、小程序)和网站渠道,可在以上渠道接入人工服务与机器人服务。 3.1微信渠道接入 接入微信渠道后,可在公众号、小程序中便捷配置在线人工、机器人服务。 设置入口:【设置】→【渠道设置】→【微信渠道】 [图片] (1)公众号渠道接入 开始之前,您需要有已认证的公众号管理员账号。由于微信限制,仅支持微信认证公众号接入人工服务。详细接入设置 Step1 点击公众号授权,使用管理员微信扫码授权。 Step2 接入微信公众号渠道成功后,默认不接入机器人服务,接入默认分组人工服务,可在【设置机器人】、【设置人工】中修改。 Step3接入成功后可在公众号下留言,测试能否成功发送消息。 (2)小程序渠道接入 开始之前,您需要有小程序管理员账号,且小程序需有客服入口,客服入口需要在小程序内设置好,可参考公众号官方添加小程序按钮的指引。 Step1 点击小程序授权,使用小程序管理员个人微信扫码授权。 Step2 接入小程序渠道成功后,默认不接入机器人服务,接入默认分组人工服务,可在【设置机器人】、【设置人工】中修改。 Step3接入成功后可点击小程序客服入口留言,测试能否成功发送消息。 3.2网站渠道接入 网站提供两种部署方式:网站链接(URL链接)、内嵌插件(Web JS)。开发者通过地址调用或简短代码,可在网站中接入客服。网站详细接入设置 设置入口:【设置】→【渠道设置】→【网站设置】→【新增网站】 新建一个网站渠道,输入网站名称和使用场景。 两种方式接入网站渠道: (1)新建内嵌插件 在新建网站界面,点击【复制】内嵌插件代码粘贴到您的网站的</body>标签之前,即可完成部署。目前暂不支持内嵌插件自定义外观,可使用腾讯云智服内嵌插件默认样式、颜色外观及固定位置,支持自定义网站入口显示位置。 内嵌插件代码,示例如下: uid:为用户唯一标识,如没有可不填写 data:用户传递用户信息,最多支持五个,参数名分别为c1,c2,c3,c4,c5 selector: css选择器,用于替换默认的常驻客服入口 callback(type, data):回调函数,type表示事件类型,data表示事件相关数据 type支持的类型:newmsg有新消息,error腾讯云智服页面发生错误, close聊天窗口关闭 若您需要传送相关数据,可通过在链接后追加参数,包括用户id(uid)与自定义用户信息参数(c1、c2、c3、c4、c5)传递。 (2)新建网站链接 在新建网站界面,点击【复制】对应链接地址,用户点击该链接即可进入咨询。 若您需要传送相关数据,可通过在链接后追加参数,包括用户id(uid)与自定义用户信息参数(c1、c2、c3、c4、c5)传递。 部署聊天页链接,示例如下: [图片] 四、开始服务 进入【人工】,切换状态为“在线”后即可接入用户。(需确保当前客服所在组别和渠道设置的人工组别保持一致) 客服人员可使用PC工作台和小程序工作台服务用户。关注公众号:腾讯云智服,在底部菜单【工作台】进入小程序,即可接入用户开始服务。
2019-11-14 - 微信小程序Page间数据传递解决方案分析
内容概要 利用微信小程序的路由堆栈信息解决小程序内Page间的数据(或事件)传递的问题。通过对各种方案的对比、分析、总结,得出我们的升华版解决方案,满足你的不满足。 场景再现 工作中我们经常会遇到B页面需要A页面内的部分或全部数据;C页面内的一个函数执行完之后需要改变B页面内的显示样式;也或者是A和B两个页面用到了同样的网络数据,在其中一个页面做出修改后另一个页面也要随之改变以保证回传服务器时数据的准确性,等等诸如此类的页面间数据传递的问题。 现有方案梳理 当然针对上面场景中各种问题我们可以有很多种的解决方案。例如利用微信API中reLaunch、redirectTo、navigateTo 函数的url路径携带参数到目标页面;利用EventChannel信道实现打开页面与被打开页面通信;利用全局文件共享数据;利用路由堆栈获取目标页面实例等等,我目前用过的方案就以上四种,如果你用过其他方案也可以提出来我们一起讨论学习。接下来我们就针对以上四种方案进行一个简略的分析。 方案一:reLaunch、redirectTo、navigateTo 函数url路径携带参数到目标页面 这种方案大家应该都用过,在页面跳转过程中传递一些简单的数据还是十分方便的,但是它的缺点也很明显,在五个路由函数中只有三个可以在跳转路径上携带参数,而且参数不可以是对象类型,在遇到携带"?"等特殊字符的参数还需要进行转码操作。对于跨多个页面的数据传递比较繁琐。归纳如下: 优点:操作简单方便。 缺点:单项传递;复杂数据传递局限性较大;跨多页面数据传递繁琐;只能在reLaunch、redirectTo、navigateTo 三个函数中使用。 适用情况:页面间简单数据的单项传递。 方案二:EventChannel信道实现打开页面与被打开页面通信 从基础库2.7.3开始支持EventChannel。开发者可以通过navigateTo路由函数在页面跳转切换过程中自定义两个页面的数据交互函数。至于EventChannel自定义规则可参考微信API中的 navigateTo 函数。该方案解决了方案一中的复杂数据传递的局限性。可是它仅限于navigateTo函数中使用,并且在跨多页面传递时操作起来复杂性仍然很高。归纳如下: 优点:使用灵活性较高;可传递较复杂数据;可双向传递; 缺点:跨多页面数据传递繁琐;只能在navigateTo一个函数中使用。 适用情况:由navigateTo控制路由的两个页面间数据传递。 方案三:全局文件共享数据 全局共享数据无非就是定义一份谁都可以使用和修改的数据。这个方案很简单,而且很轻松的解决了方案一和方案二中的跨多个页面的数据传递问题。可是数据处理的及时性却大打折扣,只能期待各个页面自己触发自身的事件。归纳如下: 优点:实现简单,可跨多页面。 缺点:及时性欠缺,灵活度不够。 适用情况:不要求事件的及时性和功能比较集中的模块。 方案四:利用路由堆栈获取目标页面实例 兵法中常说“擒贼先擒王”,如果我们拿到了某个页面的实例索引,那就相当于是在战场上控制了敌方的将领,我们说要粮草他就得给粮草,我们说要兵器他就得乖乖的给兵器。所以该方案我们也可以戏称为“擒王方案”。如果我们给“擒王方案”做一个归纳的话,应该是这样的: 优点:灵活性/及时性高;数据类型不限;可跨多页面使用; 缺点:代码重复性较高;不在堆栈内的页面无法进行操作; 适用情况: 确定页面实例在堆栈内的交互性比较强多页面。 提炼升华 在上一节中我们对四个方案进行了一下简单的梳理,每个方案也各有优缺点,上述四种方案可能已经满足了我们工作中的使用,可是作为程序员的我们不应该停下追逐更优更好的脚步。我们尽量把上述方案的优点集中起来,并且规避掉缺点。整理出一个相对完善的方案。首先自定义一个跨页面(当然也可在页面内使用)的事件处理类,暂时命名其为funbus。具体的处理逻辑如下: 一:定义全局事件缓存Map。 [代码]// 事件缓存 const events = {}; [代码] 二:根据 getCurrentPages() 函数获取被操作页面实例。 [代码]/** * 同步执行,会立即执行并拿到被执行函数的返回结果 * * pagePath 页面名称或路径 * method 执行的方法名 * params 方法参数 */ function callFun(pagePath, method, params) { let pages = getCurrentPages(); let page = null; for (let i = 0; i < pages.length; i++) { if (pages[i].route.indexOf(pagePath) > -1) { page = pages[i]; break; } } if (page) { try { return page[method](...params); } catch (err) { console.error('FunBus Error: ', err); return null; } } return null; } [代码] 三:当然我们也需要处理如果被操作的页面不在堆栈内的情况。 1.事件注册和解绑。 [代码]/** * 注册事件 * * key 值命名规则 页面名称-描述 (如: index-refresh) * event 是一个对象: {path: '被注册事件发生的页面路径', method: '被注册的方法名称', params: [...被注册的方法需要的参数]} * * 调用范例: subscribe("index-refresh", {path:"pages/index", method:"refreshPage", params: [1,2,3]}); */ function subscribe(key, event) { events[key] = event; } /** * 解除绑定 */ function unSubscribe(key) { delete events[key]; } [代码] 2.之前未在堆栈内的页面加入到堆栈时(即展示到前台时)在适当时机触发之前缓存的事件。 [代码]/** * 唤醒/执行之前订阅的事件 */ function notifyEvent(key, remove) { let event = events[key]; if (event) { // 只有remove的值是布尔类型的false时才不会移除当前事件,其他任何值该事件都会被移除 if (!remove && remove !== false) { remove = true; } remove && delete events[key]; return callFun(event.path, event.method, event.params) } return null; } [代码] 四:工具类的使用 1. 直接使用 [代码]let result = funbus.callFun('a/a', 'returnBpageData', [1, 2]); this.setData({ astring: result, }); [代码] 2. 页面未在堆栈内的使用 [代码]// C页面内 // 由于B页面跳转C是重定向 redirectTo 跳过来的,所以B页面不在路由堆栈内,我们要先注册,然后再B页面里适当的时机出发该函数。 funbus.subscribe('b-changebgc', { path: 'b/b', method: 'changeBgColor', params:['yellow']}); // B页面内 // 触发在C页面注册的函数 funbus.notifyEvent('b-changebgc'); [代码] 五:传送门 Demo 下载 总结 本文大致可以分为两个重点部分。前一部分我们把页面之间进行数据传递的四种常用的方案做了一个简要的分析总结。后一部分主要是根据前一部分的优缺点整理得出一个通用的数据传递和事件处理的工具类,并对其实现和使用进行了简要说明。在文末也提供了Demo的github地址,若使用中有什么不合理不完善的地方还请不吝指出。
2019-11-14