- 菜鸟教程 - 如何实现 邀请好友送金币
这期菜鸟教程我们会用一个具体的产品方案来为大家解答以下这些问题—— 1. 小游戏基于关系链的互动玩法有哪些? 2. 邀请好友的后续互动, 如何通过关系链互动 和 定向分享能力实现? 3. 开放数据域UI绘制太麻烦了,怎么办? 产品方案 · 在游戏内,定向邀请未注册的特定微信好友加入游戏;(也可以是游戏自定义条件的已注册好友,例如7天未登陆游戏的好友) · 成功邀请后,开发者可监听成功事件。 · 邀请者可获取已邀请的好友信息。 [图片] 案例实现 1 邀请好友 | 获取未玩过该游戏的好友 开发者需要在开放数据域通过 wx.getPotentialFriendList接口获取可能对游戏感兴趣的未注册的好友名单。该接口可以一次获取至多5个非同玩好友,每次拉去都会刷新名单。开发者拿到好友的openid、昵称和头像等数据,然后就可以开始提示玩家邀请啦! [代码]wx.getPotentialFriendList({[代码][代码] [代码][代码]success: (data) => {[代码][代码] [代码][代码]let list = data.list || [];[代码] [代码] [代码][代码]console.log([代码][代码]'getPotentialFriendList'[代码][代码], data);[代码][代码] [代码][代码]}[代码][代码]});[代码] | 向指定用户发起分享 获取到好友数据之后,在开放数据域,通过wx.shareMessageToFriend接口可以给指定好友定向分享。 [代码]wx.shareMessageToFriend({[代码][代码] [代码][代码]openId : [代码][代码]''[代码][代码], [代码][代码]// 这里填写好友的openid[代码][代码] [代码][代码]title : [代码][代码]'快来探索浩瀚星空'[代码][代码],[代码][代码] [代码][代码]imageUrl: [代码][代码]'https://mmocgame.qpic.cn/wechatgame/TKicR7oWel4znvwMdwOpuwoy1ntVB44kT9ZSse2u0xNcO5SaxIS2UwU0GdUfA2Al0/0'[代码][代码]})[代码] | 设置分享参数 wx.shareMessageToFriend的分享参数,只能从主域传入。 故拉起开放数据域前,开发者需要先通过wx.setMessageToFriendQuery 接口设置。目前该接口只允许传入一个参数 shareMessageToFriendScene,并且仅可以在游戏域使用。 [代码]// 设置定向分享参数(这里假设1代表的是邀请新玩家场景值)[代码][代码]wx.setMessageToFriendQuery({[代码][代码] [代码][代码]shareMessageToFriendScene: 1[代码][代码]});[代码] | 监听邀请成功事件 用户发起定向分享之后,在基础库2.9.4以上支持通过接口wx.onShareMessageToFriend监听邀请成功事件(链接待补充),给予邀请者激励。 [代码]wx.onShareMessageToFriend && wx.onShareMessageToFriend((res) => {[代码][代码] [代码][代码]console.log([代码][代码]'wx.shareMessageToFriend'[代码][代码], res);[代码][代码] [代码][代码]let tips = res.success ? [代码][代码]'分享成功'[代码] [代码]: [代码][代码]'分享失败'[代码][代码];[代码] [代码] [代码][代码]wx.showToast({[代码][代码] [代码][代码]title : tips,[代码][代码] [代码][代码]icon : [代码][代码]'none'[代码][代码],[代码][代码] [代码][代码]duration: [代码][代码]2000[代码][代码] [代码][代码]});[代码][代码] [代码][代码]// 这里可触发游戏逻辑[代码][代码]});[代码] | 小结 至此,拉取好友、定向分享、监听成功通知的操作就完成了,几个接口的调用顺序如下,我们通过一个图来简单梳理这里的流程: [图片] 2 新玩家加入游戏,双方领奖励 | STEP1: 接受邀请 新玩家点击卡片进入游戏,开发者可通过 wx.getLaunchOptionsSync接口获取启动时候的信息,返回的对象中会有 query 参数,之前邀请者设置的 shareMessageToFriendScene 就会出现在 query 里了。我们直接判断这个值是否为 1(前文,我们设置了1为邀请新玩家场景值),然后发送事件给开放数据域,表明接收到了邀请。 [代码]wx.onShow((options) => {[代码][代码] [代码][代码]console.log([代码][代码]'onShow options'[代码][代码], options);[代码] [代码] [代码][代码]// 玩家通过被邀请的卡片进入,向子域发送消息,要求修改开放数据域消息[代码][代码] [代码][代码]if[代码] [代码](options && options.query.shareMessageToFriendScene === [代码][代码]'1'[代码] [代码]) {[代码][代码] [代码][代码]this[代码][代码].openDataContext.postMessage({[代码][代码] [代码][代码]event: [代码][代码]'reciveInvite'[代码][代码],[代码][代码] [代码][代码]});[代码][代码] [代码][代码]}[代码][代码]});[代码] | STEP2: 修改卡片分享人的托管数据 敲小黑板了!关键点来了!最多人问就是这里了!分享点进来不知道谁分享的,怎么办? 开放数据域收到 event 为 ‘reciveInvite’ 的消息之后,开发者可通过wx.modifyFriendInteractiveStorage接口修改邀请者的托管数据来做回馈。这个时候需要带上一个特别的参数 quiet: true 来表示修改卡片分享人的数据。设置了quiet:true的互动,开发者无需填入touser,用户侧也无需确认噢。 [代码]wx.modifyFriendInteractiveStorage({[代码][代码] [代码][代码]// 这里定义key“2”代表邀请玩家的数量[代码][代码] [代码][代码]key :[代码][代码]'2'[代码][代码],[代码][代码] [代码][代码]opNum : 1,[代码][代码] [代码][代码]operation: [代码][代码]'add'[代码][代码],[代码][代码] [代码][代码]// 静默修改需要用户通过快捷分享消息卡片进入才有效,代表分享反馈操作,无需填写 toUser,直接修改分享者与被分享者交互数据[代码][代码] [代码][代码]quiet : [代码][代码]true[代码][代码],[代码][代码] [代码][代码]complete:(res) => {[代码][代码] [代码][代码]console.log([代码][代码]'modifyFriendInteractiveStorage'[代码][代码], res);[代码][代码] [代码][代码]}[代码][代码]});[代码] | STEP3: 数据校验 及 记录赠送关系 通过wx.modifyFriendInteractiveStorage我们可以修改卡片分享人的互动型托管数据,但是这个API看起来并没有记录邀请人和被邀请人,只是简单修改卡片分享人的数据,如果我想校验下哪些用户是已经邀请过的,或者想展示邀请记录该怎么做呢? 这里我们需要了解下JSServer: wx.modifyFriendInteractiveData接口在具体写入操作之前会默认执行开发者托管在JSServer上的一段代码,要求开发者使用开发者工具上传文件checkInteractiveData.js。 而在JSServer运行环境下,可以调用wx.getOpenId()、wx.getFriendUserStorage()和wx.setFriendUserStorage()这几个接口,此外还可以拿到用户本人openid:wx.getOpenId()、目标好友openid:toUser和增加的数据opNum,这样除了执行校验,还可以顺带将邀请和被邀请记录写入普通托管数据,如下图所示(JSServer的校验逻辑可以参考本文附上的源码): [图片] || TIPS:游戏过审发布后,记得在工具上将checkInteractiveData.js文件发布上线,校验才会在正式环境生效。否则,修改互动型托管数据也会失败。 [图片] | STEP4: 触发邀请成功后游戏逻辑 按照上面的步骤,互动型托管数据和邀请记录都已经记录起来了。 但这些数据都是在开放数据域才能拿到的,如果想在主域根据这些邀请记录来做发放奖励逻辑该怎么做呢?这里我们在主域提供了wx.getUserInteractiveStorage接口,可以拉取互动性关系链数据。 [代码]// 获取用户的加密交互数据[代码][代码]wx.getUserInteractiveStorage({[代码][代码] [代码][代码]keyList: [[代码][代码]'2'[代码][代码]],[代码][代码] [代码][代码]success: ({cloudID}) => {[代码][代码] [代码][代码]// 该接口拿到的是加密数据,数据解密可以通过开发者自己的后台也可以通过云函数,这里演示云函数[代码][代码] [代码][代码]wx.cloud.callFunction({[代码][代码] [代码][代码]name: [代码][代码]'getUserInteractiveStorage'[代码][代码],[代码][代码] [代码][代码]data: {[代码][代码] [代码][代码]userInteractive: wx.cloud.CloudID(cloudID),[代码][代码] [代码][代码]}[代码][代码] [代码][代码]}).then(res => {[代码][代码] [代码][代码]console.log([代码][代码]'cloud getUserInteractiveStorage'[代码][代码], res);[代码][代码] [代码][代码]});[代码][代码] [代码][代码]}[代码][代码]});[代码] 通过上述接口拿到的最终数据如下,代表邀请了3个玩家,开发者根据这个数据就可以给玩家发放奖励了! [代码]{[代码][代码] [代码][代码]"data"[代码][代码]:{[代码][代码] [代码][代码]"kv_list"[代码][代码]:[[代码][代码] [代码][代码]{[代码][代码] [代码][代码]"key"[代码][代码]:[代码][代码]"2"[代码][代码],[代码][代码] [代码][代码]"value"[代码][代码]:[代码][代码]"3"[代码][代码] [代码][代码]}[代码][代码] [代码][代码]][代码][代码] [代码][代码]},[代码][代码] [代码][代码]"openid"[代码][代码]:[代码][代码]"xxxxx"[代码][代码]}[代码] 至此,如何实现邀请好友,双方激励的案例实践讲完啦!而且,我们的开发GG还把上面的示例代码提供给大家,下载换个APPID,做个UI就可以跑咯,源码链接 [图片] 上面的case能力都是在开放数据域实现,但我们有收到很多反馈:在开放数据域做UI界面太难了!! “我只是想绘制一个简单的好友列表,最多加个赠送或者邀请按钮,在开放数据域做UI界面太难了!!” “开放数据域引入一个独立的游戏引擎会占据好多代码包体积” “纯canvas开发真的太麻烦,代码可读性差,事件处理也很麻烦” 这是很多开发者的心声。 为此,开发哥哥们也提供了开放数据域UI绘制的解决方案——轻量级的canvas渲染引擎。 体积小!性能还杠杠的!上面的demo就是用它完成的。 轻量级的canvas渲染引擎 这款轻量级的canvas渲染引擎,它具有以下特点: · 引擎体积很小,压缩之后仅~50kb; · 类Web开发,只需提供XML + CSS即可渲染界面,提高代码可维护性; · 性能强大:长列表滚动可跑满60帧; [图片] | 使用教程: · step 1:克隆本项目到合适的文件夹,引用引擎 [代码]// 通过Git的方式安装[代码][代码]git clone https:[代码][代码]//github.com/wechat-miniprogram/minigame-canvas-engine[代码] [代码]// 引用渲染引擎[代码][代码]import Layout from [代码][代码]'minigame-canvas-engine'[代码] · step 2:为UI界面编写模板和样式 [代码]let template = `[代码][代码]<view >[代码][代码] [代码][代码]<text value=[代码][代码]"hello canvas"[代码][代码]> </text>[代码][代码]</view>[代码][代码]`[代码] [代码]let style = {[代码][代码] [代码][代码]container: {[代码][代码] [代码][代码]width: 200,[代码][代码] [代码][代码]height: 100,[代码][代码] [代码][代码]backgroundColor: [代码][代码]'#ffffff'[代码][代码],[代码][代码] [代码][代码]justContent: [代码][代码]'center'[代码][代码],[代码][代码] [代码][代码]alignItems: [代码][代码]'center'[代码][代码],[代码][代码] [代码][代码]},[代码][代码] [代码][代码]testText: {[代码][代码] [代码][代码]color: [代码][代码]'#ff0000'[代码][代码],[代码][代码] [代码][代码]width: 200,[代码][代码] [代码][代码]height: 100,[代码][代码] [代码][代码]lineHeight: 100,[代码][代码] [代码][代码]fontSize: 30,[代码][代码] [代码][代码]textAlign: [代码][代码]'center'[代码][代码],[代码][代码] [代码][代码]}[代码][代码]}[代码] · step 3:调用渲染API,执行真正的渲染 [代码]// 将模板和样式传给渲染引擎,渲染引擎会生成布局树和渲染树等,准备渲染到canvas上面[代码][代码]Layout.init(template, style);[代码][代码] [代码] [代码]// sharedContext自行创建[代码][代码]Layout.layout(sharedContext);[代码] [代码]/**[代码][代码] [代码][代码]* 设置sharedCancas在主域绘制的物理尺寸和位置信息,这一步非常重要,[代码][代码] [代码][代码]* 因为子域渲染引擎并不关心外部使用的引擎是什么,而是自己监听触摸事件来进行事件处理,[代码][代码] [代码][代码]* 因此需要拿到真实的物理尺寸、位置信息来执行事件处理。[代码][代码] [代码][代码]*/[代码][代码]Layout.updateViewPort({[代码][代码] [代码][代码]width : 200,[代码][代码] [代码][代码]height: 100,[代码][代码] [代码][代码]x : 100,[代码][代码] [代码][代码]y : 100[代码][代码]});[代码] · step 4:效果预览 [图片] || TIPS: 详细的教程可以查看文档; 为了方便调试,还可以使用在线编辑功能; 上面的邀请好友获得激励的demo示例,也是用这个canvas渲染引擎实现的喔。 对定向分享奖励还有什么疑问或者经验分享?希望了解哪些方面的实践教程?欢迎在评论区留言。
2019-12-09 - 实战分享: 小程序云开发玩转订阅消息(二)
[图片]这是实战分享: 小程序云开发玩转订阅消息的第二部分 第一部分链接 《实战分享: 小程序云开发玩转订阅消息(一)》 将订阅消息存入云开发数据库接下来我们创建一个云函数 [代码]subscribe[代码] ,这个云函数的作用是将用户的订阅信息存入云开发数据库的集合 [代码]messages[代码] 中,等待将来需要通知用户时进行调用。 在微信开发者工具的云开发面板中创建数据库集合 [代码]messages[代码] [图片]微信开发者工具新增数据库集合 创建一个 [代码]subscribe[代码] 云函数,在云函数中我们将小程序端发送过来的课程订阅信息,存储在云开发数据库集合中,开发完成后,在微信开发者工具中右键上传并部署云函数。 cloudfunctions/subscribe/index.js [代码]const cloud = require('wx-server-sdk'); cloud.init(); const db = cloud.database(); exports.main = async (event, context) => { try { const {OPENID} = cloud.getWXContext(); // 在云开发数据库中存储用户订阅的课程 const result = await db.collection('messages').add({ data: { touser: OPENID, // 订阅者的openid page: 'index', // 订阅消息卡片点击后会打开小程序的哪个页面 data: event.data, // 订阅消息的数据 templateId: event.templateId, // 订阅消息模板ID done: false, // 消息发送状态设置为 false }, }); return result; } catch (err) { console.log(err); return err; } }; [代码]利用定时触发器来定期发送订阅消息接下来我们需要实现一个定时执行的云函数[代码]send[代码],来检查数据库中是否有需要发送给用户的订阅消息。如果有需要发送的订阅消息,会通过云调用 [代码]cloud.openapi.subscribeMessage.send[代码] 将订阅消息发送给用户。 创建一个名叫 [代码]send[代码] 的云函数,首先要配置云函数,在 [代码]config.json[代码] 的 [代码]permissions[代码] 中新增 [代码]subscribeMessage.send[代码]的云调用权限,然后新增一个 [代码]sendMessagerTimer[代码] 的定时触发器,定时触发器的语法和 [代码]linux[代码] 的 [代码]crontab[代码] 类似,比如,我们配置的 [代码]"0 * * * * * *"[代码] 代表每分钟执行一次云函数。 cloudfunctions/send/config.json [代码]{ "permissions": { "openapi": ["subscribeMessage.send"] }, "triggers": [ { "name": "sendMessagerTimer", "type": "timer", "config": "0 * * * * * *" } ] } [代码]接下来是实现发送订阅消息的云函数,这个云函数会从云开发数据库集合[代码]messages[代码]中查询等待发送的消息列表,检查数据库中是否有需要发送给用户的订阅消息,发送条件可以根据自己的业务实现,比如开课提醒可以根据课程开课日期来检查是否需要发送订阅消息,在我们下面的代码示例里做了简化,筛选条件只检查了状态为未发送。 查询到待发送的消息列表之后,我们会循环消息列表,依次发送每条订阅消息,发送成功后将数据库中消息的状态改为已发送。 cloudfunctions/send/index.js [代码]const cloud = require('wx-server-sdk'); exports.main = async (event, context) => { cloud.init(); const db = cloud.database(); try { // 从云开发数据库中查询等待发送的消息列表 const messages = await db .collection('messages') // 查询条件这里做了简化,只查找了状态为未发送的消息 // 在真正的生产环境,可以根据开课日期等条件筛选应该发送哪些消息 .where({ done: false, }) .get(); // 循环消息列表 const sendPromises = messages.data.map(async message => { try { // 发送订阅消息 await cloud.openapi.subscribeMessage.send({ touser: message.touser, page: message.page, data: message.data, templateId: message.templateId, }); // 发送成功后将消息的状态改为已发送 return db .collection('messages') .doc(message._id) .update({ data: { done: true, }, }); } catch (e) { return e; } }); return Promise.all(sendPromises); } catch (err) { console.log(err); return err; } }; [代码]最终效果 [图片]开课提醒订阅消息截图 源代码https://github.com/binggg/tcb-subscribe-demo[3] 参考资料 [1]注册小程序帐号: https://tencentcloudbase.github.io/2019-09-03-wx-dev-guide-register/ [2]开通云开发服务: https://tencentcloudbase.github.io/2019-09-03-wx-dev-guide-service/ [3]https://github.com/binggg/tcb-subscribe-demo: https://github.com/binggg/tcb-subscribe-demo
2019-10-23