- 多形态小程序日历组件,轻松搞定项目需求
小程序日历组件 小程序日历组件,支持多种模式,简单易用好上手。 4种日历模式 3种日期选择方式 支持自定义节假日 支持自定义日期内容 懒加载保证渲染性能 支持农历 支持根据指定日期自动生成 支持跨无数据月份 [图片] [图片] [图片] [图片] [图片] 日历组件基础配置 wxml模板 [代码]<ui-calendar dataSource="{{config}}" /> [代码] 配置日历组件 [代码]Pager({ data: { source: { $$id: 'calendar', mode: 1, // 纵向日历 type: 'range', // 区域选择 tap: 'onTap', // page响应事件 total: 365, // 指定日历总天数 data: [], // 按给定日期计算total值,自动构建日历 rangeCount: 28, // 区选区间28天 rangeMode: 2, // 区选模式 rangeTip: ['入住', '离店'], // 区选提示 festival: true, // 开启节假日显示 alignMonth: false, // 月份对齐,swiper切换时 lunar: false, // 是否显示农历 date: [], // 指定日期显示的内容 value: ['2019-12-24', '2020-01-05'], // 默认值 toolbox: { monthHeader: true, // 是否显示月头 discontinue: false, // 自动构建时,是否省略无数据的月份 }, methods: { // 响应 tap事件 onTap(e, param, inst) { // param.date 选中的当前日期 // 当区选模式时 // param.range === 'start' 区选第一天 // param.range === 'end' 区选最后一天 } } } } }) [代码] github地址:https://github.com/webkixi/aotoo-xquery 小程序demo演示 [图片]
2020-06-30 - 内容安全检测图片API:openapi.security.imgSecCheck完美解决方案。
背景需求: 我个人做了一款小程序的小游戏,本质是小程序。里面有个自定义图片的功能。用户从本地相册选一张图片进行裁剪,之后保存到缓存中或者上传到服务器。然后用户再用这张图片作为素材进行其它操作。这里就涉及到内容安全了,提交审核没有通过也是因为这个没有做内容安全。防止一些色情低俗的事情发生。 正文: 思路:相册选图片 --> 裁剪小的图片 --> 内容安全检测 --> 通过 --> 裁剪大的图片 --> 保存。 失败的原因:绝大多数是因为检测图片不能大于1M,而导致超时,或者是errCode:-1,又或者是其它问题。 [图片] [图片] 核心代码图片: [代码]默认裁剪小尺寸图片 (我的业务需求是正方形图片,也可动态计算宽高比例) [代码] [图片] 检测图片 部分iOS不兼容encoding: ‘ucs2’。注释掉就好了 [图片] [图片] 云函数 [图片] 测试情况: 正常图片不含违法违规,测试20次,全部通过。小程序上线后暂无发现检测失败情况。百度搜索的“人体油画”等等均可通过。 PS:第一次写经验分享哈,看不懂可以问我。体验一下我的小程序想问我这个小程序其它的功能点也可以喔! 技术会迭代更新,用到的技术会有时效性,看编辑时间,可能当时的技术现在不适用了
2020-10-22 - 在线答题小程序使用帮助文档
产品介绍 在线答题小程序是一款以小程序为载体,在微信内部完成刷题、模拟考试的产品, 专为各类学校和培训机构提供考试系统,包括自测练习、组织统一考试、开展知识竞赛、布置课外作业或假期作业、智能组卷、答卷评阅与成绩管理等众多功能;也可用于政府机构、企事业单位内部的入职考试、员工考核、内部培训考试等。 适用场景 1 ·企业招聘考试。候选人等候时面试可手机扫码参加笔试,系统实时生成结果,一个简单的考核就可让面试官提前了解候选人的能力情况。在大规模校园聘会上公布考试地址,考生现场完成考试,现场出分,主办方可快速筛选合格考生参加面试,大大缩短招聘周期和成本。 2 ·员工晋升考核。员工专业技能是否达标,员工素质测评,安排一场考试即可对员工是否晋升进行有理的判断。全面电子化式考试,可大大缩短员工考核周期与成本。 3 ·培训认证考试。培训机构结业认证考核,行业从业资格认证,能力认证考核等,题答答提供从考生报名到参加考试的全流程功能。无限制题库刷题,错题训练,随机题序,答案解析,错题本重练,让刷题不止追求量,也有质的保障,帮助考生更熟练地掌握知识点,提高考试通过率。 题库管理 题库可用来对题目进行归类管理,题库下可加入多个题目,打开题库可以查看此题库下的所有题目。例如题库可以设置为:微信期末考。 题目导入 上传前请先下载模板,按照模板要求新建文档,或者修改已有文档的格式。模板下载地址:Excel模板 。 在线考试 该模块可随机从题库抽取固定数量的题目进行考试,考试时间,考试数量,都可以通过后台完成设置 20200609 目前在线考试模块已支持记忆功能,比如某用户小肥羊在某次100个题目的考试过程中做到第十题,中途退出了,那么下次进来考试从第11题开始。 20200612 新增考试得分支持按照不同题型不同得分来计算,比如单选题1分,多选题2分,判断题1分 40道单选题 20道多选题 20道判断题 40×1+20×2+20×1 = 100分 模拟考试 模拟考试主要用于日常考试用,不限制考试次数,不限制考试时间 顺序练习 顺序练习每次会展示当前题库的所有题目,答题过程会有记录,如果中途退出,下次进来练习,会从上次退出答题的题目开始练习,也就是所谓的中途退出答题记忆功能 模拟练习 模拟练习每次随机从题库抽取10道题目,方便日常刷题用。因为每次随机抽题,所以该模块可以改名为每日一练或者每日练习 20200609 模拟练习新增答题卡设计,用户可以通过答题卡进入具体某天进行答题或者核对当前答题情况 我的成绩 该模块用于展示在线考试的答题记录情况,考试得分、考试用时等相关信息 错题管理 用于展示在线考试模块,答错的题目,注意:顺序练习、模拟练习这两个模块做错题,不记录在我的错题里面 收藏管理 用于展示顺序练习、模拟练习两个模块中收藏的题目信息,在线考试不提供收藏功能 成绩排名 该模块用于根据在线考试模块答题情况进行排名展示,目前最多只展示前20秒的考生记录 报表导出 在线考试模块的考试记录可以通过后台导出,导出文件为Excel,该文件具体可包含考生信息、分数、考试时间等,截图如下: [图片] 如果需要其他更多信息也可支持 扫码体验 1 1 [图片] 1 其他 未完待续
2021-01-06 - 企业微信如何发送小程序消息
看了企业微信的开发文档。 我依旧没懂。 https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token= 中的access_token是什么,是小程序的accesstoken还是企业微信的accesstoken。 如果是小程序的accesstocken为什么又在https://work.weixin.qq.com/api/devtools/devtool.php中显示发送失败。 那企业微信获取accesstoken的时候的appid和secretid是什么,我在企业微信中找了半天都没找到。 官方所提供的测试id又发送不了微信通知推送。 小程序未开发完成不能发布,不发布又没有关联权限。 现在我很迷茫,请微信团队和企业微信团队指出一条活路。感谢。
2019-04-23 - 云开发如何实现管理员通知消息
需求描述 小程序目前的主要能力还都在小程序端实现,但是我们在进行开发的小程序不可能只有小程序端能力,我们也会有一些管理端能力。比如说,当用户在小程序中提交了消息以后,我们的小程序应该可以通知到小程序的管理员,以便让管理员进行下一步操作。 解决方案 架构说明 由于小程序本身不支持长久性的消息通知能力,因此,我们可以考虑借助一些第三方的服务和能力,来完成我们自己的需求。 这个需求很适合使用小程序新发布的长期订阅消息能力,但是目前该能力开放的类目还不足以支持我们的需要。 一般而言,使用短信是我们目前到达率比较高的能力,且更为普遍的能力,其他通道的能力大多受限或不符合国情,为了确保通知信息的到达率,我们这篇文章就使用短信来完成需求。 架构图示 [图片] 具体操作 1. 开通腾讯云短信服务并获取配置信息 我们想要发送短信,就需要先有一个短信服务,用于发送短信,这里我们可以使用腾讯云提供的云短信服务来发送短信。 开通腾讯云短信,并创建应用 首先,你需要访问 https://console.cloud.tencent.com/smsv2 ,点击开通腾讯云·云短信。 在开通完成后,点击界面中的【添加应用】,添加一个新的短信应用,你可以根据自己的实际情况,添加短信应用的名称和简介。 [图片] 获取 AppID、App Key 添加完成后,点击你创建好的应用,进入到应用详情页,在应用的详情页中的应用信息栏目中,你可以找到 AppID 和 AppKey ,复制并保存这两个值,稍候我们会用到。 [图片] 2. 配置短信模板、短信签名 开通了腾讯云短信服务以后,我们需要去创建短信模板,以及短信签名 腾讯云短信并不是让你随意发所有的内容的,而是你需要创建一个模板,并使用特定的模板来完成短信的发送。 短信签名则是原来让收到短信的用户知道他所收到的短信来自于他的那一个服务,一般来说,设置为产品的品名。 在腾讯云控制台中,进入到【云短信】控制台 创建短信签名 首先,点击【国内短信】,进入到短信的页面,点击【创建签名】,然后在弹出的窗口中输入你的签名的具体信息,比如这里我就是以公众号【程序百晓生】来创建签名。 [图片] 签名创建完成后,你需要等待腾讯云官方的审核,审核通过以后,你添加的签名才可以被使用。 创建短信模板 创建完签名,你需要创建一个短信的正文模板,用于发送短信。 输入模板名称、短信类型,然后选择标准模板中的模板,这里我们选择“您有新的{1}订单,请注意查收!”这个模板。 除了使用标准模板,你也可以自己编写一个模板,为了方便文章撰写,这里使用标准模板。 [图片] 然后点击提交,等待审核就可以了。 3.编写云函数发送短信 在完成了基础的配置后,我们在微信开发者工具中实现一个云函数,用于调用腾讯云的短信服务,实现具体的通知。 首先,我们创建一个新的云函数,名为 [代码]notifyAdmin[代码],意为用于通知管理员的云函数。 [图片] 然后,选择我们刚刚创建的 [代码]notifyAdmin[代码] 云函数,在函数上右击,选择【在终端中打开】,进入到控制台,并输入如下命令,安装所需的短信 SDK。 [代码]npm install --save sms-node-sdk [代码] [图片] 然后,修改云函数的 [代码]index.js[代码],加入如下代码 [代码]// 云函数入口文件 const cloud = require('wx-server-sdk') const { SmsClient } = require('sms-node-sdk'); const AppID = 1400286810; // SDK AppID是1400开头 // 短信应用SDK AppKey ,替换为你自己的 AppKey const AppKey = 'xxxx'; // 需要发送短信的手机号码 const phoneNumber = '10000000'; // 短信模板ID,需要在短信应用中申请 const templId = 476457; // 签名,替换为你自己申请的签名 const smsSign = '程序百晓生'; // 实例化smsClient cloud.init() // 云函数入口函数 exports.main = async (event, context) => { let orderId = event.orderId; let smsClient = new SmsClient({ AppID, AppKey }); return await smsClient.init({ action: 'SmsSingleSendTemplate', data: { nationCode: '86', phoneNumber, templId: templId, params: [orderId], sign: smsSign // 签名参数未提供或者为空时,会使用默认签名发送短信 } }) } [代码] 完成代码的修改后,就可以部署你的云函数了,右键你的云函数,选择【上传并部署云函数:云端安装依赖】 4. 在小程序端触发短信 在前面我们提到,在一些特定的场景下,我们希望用户的操作可以给管理员发送消息通知。在具体的实现的时候,我们可以根据自己的实际业务需求,来设定我们的通知发送的条件,比如说,在用户支付成功后发送消息,则相关代码如下: [代码]let orderId = 'this is a orderId'; wx.requestPayment({ success:res => { console.log("User Payment Success"); // 调用云函数发送短信 wx.cloud.callFunction({ name:"notifyAdmin", data:{ orderId: orderId } }); } }) [代码] 总结 经过本次的分享,我们了解到了如何借助短信服务,实现云开发的后台通知能力,实际上,除了短信服务,你还可以借助一些其他的工具,比如邮件、企业微信机器人等能力,实现后台管理信息的推送。 明天,我们将分享如何借助通过微信发送订单消息。
2019-11-19 - 纯云开发 使用一个小程序访问另一个小程序的云资源
由于工作需要,我需要使用一个小程序与另一个小程序共同享用同一套云资源。这就需要用到'tcb-admin-node'这个sdk来帮我实现这个功能。 这个sdk有详细的教程如下:https://github.com/TencentCloudBase/tcb-admin-node 作为一个新手,刚看这个文档感觉有些懵逼,不过在群友的帮助下,还是慢慢地实现了一小步的功能,就是小程序访问另一个小程序的云函数。 废话不多说,我的使用步骤如下: 1,你要有一个已经有在使用自己开通的云资源的小程序,称为小程序A;还要有一个空的小程序,称为小程序B。 2,为小程序B开通云开发。 3,小程序B创建云函数的方法我就不多说了。按照文档来说,你是需要每建一个云函数就安装一次tcb-admin-node的,但是最新版本的wx-server-sdk貌似已经集成了tcb-admin-node,所以你可以选择安装或者不安装。 4 ,不多说,代码如下图: [图片] 其中secretId和secretKey都是必须的,均为小程序A的secretId和secretKey,获取方式文档中有链接,即从腾讯云中获取你的api密匙。如下图:env为小程序A使用的环境ID [图片] 取一对就可以了,还有必须从你的小程序A进入。 name为你小程序A使用过的云函数,data为参数,与云函数所需参数一致。 5,这就封装完成了一个云函数。别忘记上传。,这时候在前台,就像普通云函数一样调用这个云函数就可以了。我的代码如下: [图片] 访问结果如下: [图片] 这时候小程序B就成功地访问了小程序A。 当然,这只是我实践的结果,成功了,于是把方法分享给大家。你们成功不成功,就看你们自己的实践了。 由于第一次发帖,可能写的有不好的地方,希望大家多多包涵,若有不妥可以纠正一下,谢谢大家。
2019-11-15 - 如何实现服务通知?非小程序服务通知
[图片]如上图的呗宝有钱推送的 会员卡积分变动通知。不能拒收通知,也不需要关注公众号、小程序就可以强制给微信用户发送通知。 请教这个是如何实现的?
2019-11-15 - 云服务器调用security.imgSecCheck完成代码分享
云服务器代码: // 云函数入口文件 const cloud = require(‘wx-server-sdk’) cloud.init() // 云函数入口函数 exports.main = async (event, context) => { const {value} = event; try { const res = await cloud.openapi.security.imgSecCheck({ media: { header: {‘Content-Type’: ‘application/octet-stream’}, contentType: ‘image/png’, value:Buffer.from(value) } }) return res; } catch (err) { return err; } } 本地函数: wx.chooseImage({count: 1}).then((res) => { if(!res.tempFilePaths[0]){ return; } console.log(JSON.stringify(res)) if (res.tempFiles[0] && res.tempFiles[0].size > 1024 * 1024) { wx.showToast({ title: ‘图片不能大于1M’, icon: ‘none’ }) return; } wx.getFileSystemManager().readFile({ filePath: res.tempFilePaths[0], success: buffer => { console.log(buffer.data) wx.cloud.callFunction({ name: ‘checkImg’, data: { value: buffer.data } }).then( imgRes => { console.log(JSON.stringify(imgRes)) if(imgRes.result.errorCode == ‘87014’){ wx.showToast({ title:‘图片含有违法违规内容’, icon:‘none’ }) return }else{ //图片正常 } [代码] } ) }, fail: err => { console.log(err) } } ) 我相信做出来的人很多,但是没有分享出来,我今天分享出来就是为了避免更多程序员不要在这种简单的问题上,浪费太多的时间,我就浪费了很多时间,兼职太坑爹了[代码]
2019-07-26 - 小程序开发常见问题及解决方案
一,input不触发bindinput事件 关于input使用bindinput事件时,没法获取用户输入信息的问题。 解决: 这个是官方2.9.3的bug,退到2.9.2后就好了,回退操作如下图 [图片] 二,getImageInfo:fail download image fail 出现这种问题,是因为没有给小程序的downloadFile配置域名白名单。 [图片] 三,获取小程序用户高清图像 [代码]//获取高清微信头像 headimgHD(imageUrl) { console.log('原来的头像', imageUrl); imageUrl = imageUrl.split('/'); //把头像的路径切成数组 //把大小数值为 46 || 64 || 96 || 132 的转换为0 if (imageUrl[imageUrl.length - 1] && (imageUrl[imageUrl.length - 1] == 46 || imageUrl[imageUrl.length - 1] == 64 || imageUrl[imageUrl.length - 1] == 96 || imageUrl[imageUrl.length - 1] == 132)) { imageUrl[imageUrl.length - 1] = 0; } imageUrl = imageUrl.join('/'); //重新拼接为字符串 console.log('高清的头像', imageUrl); return imageUrl; }, [代码]
2019-11-17 - 小程序海报生成工具,可视化编辑直接生成代码使用,你的海报你自己做主
开门见山 工具地址 点我直达>>painter-custom-poster 由于挂载在github page上,打开速度会慢一些,请耐心等待或自行解决git网速问题 背景 在做小程序时候,我们经常会有一个需求,需要将小程序分享到朋友圈,但是朋友圈是不允许直接分享小程序,那我们还有其他的办法解决吗?答案肯定是有的,即 canvas 生成个性化海报分享图片到朋友圈 分析 小程序中有大量的生成图片需求,但是使用过 canvas 的人,都会发现一些难以预料的问题>>有关小程序的坑 直接在 canvas 上绘制图形,对于普通开发者来说代码会特别凌乱并且难以维护,经常会花费很久的时间去优化代码 不同的环境渲染问题,例如在开发者工具看起来好好的,一到 Android 真机,就出现图片不显示,位置不对应等等问题 解决 那可不可以开发一款生成海报的插件库呢? 首先,只需要提供一份简单的参数配置文件即可 解决掉小程序Canvas遇到的一些大大小小的坑 有严苛的测试环节,解决各种环境和各种机型遇到的问题,并提供稳定的线上版本 长期维护,并有专人更新迭代更新颖的功能 以上的要求当然是可以的,曾经的我也想尝试开发一款出来,但是后来尝试了几款现成的工具之后就放弃了,毕竟轮子这个东西,是需要不断维护更新的,另外已经有这么多优秀现成的插件了,我为何还要费力去写呢,贡献代码岂不更美哉,以下是我收集的几款 小程序生成图片库,轻松通过 json 方式绘制一张可以发到朋友圈的图片>>Painter 小程序组件-小程序海报组件>>wxa-plugin-canvas 微信小程序:一个 json 帮你完成分享朋友圈图片>>mp_canvas_drawer 我想干什么 唠了这么多,好像提供给大家插件就没我什么事情了…想走是不可能的 为了能够制作出更酷炫的海报,我思考了许久 虽然有了插件后,只需要提供配置代码就能够制作出一款海报来,但是我发现还是有些许问题 制作海报效率还是不够高,微调一个元素的大小和位置,就需要不断的修改保存代码,等待片刻,查看效果,真的烦 一个小小的位置调整可能就需要来回调整无数次,这种最简单的机械化劳动,这辈子是不可能的 拿着完美的稿子,递给设计师看,这个位置不对,这个线太粗,这个颜色太重…你信不信我打死你 对于一些精美复杂的海报,实现起来真的不太现实 那我需要怎么做呢,请点击这个链接体验>>painter-custom-poster 点击左侧例子展示中的任意一个例子,然后导入代码就能看到效果图,这下你应该能猜到了我的想法了 如何实现 刚开始我想用简单的html和css加拖动功能实现,通过简单尝试之后就放弃了,因为这个功能真的太复杂了,简单的工具肯定是不行的 中间这个计划停滞了很长时间,一度已经放弃 直到发现了这个库fabric.js,真的太太优秀了,赞美之词无以言表,唯一的缺点就是中文教程太少,必须生啃英文加谷歌翻译 fabric介绍,你可以很容易地创建任何一个简单的形状,复杂的形状,图像;将它们添加到画布中,并以任何你想要的方式进行修改:位置、尺寸、角度、颜色、笔画、不透明度等 How To Use 目前工具一共分成4部分 例子展示 用来将一些用户设计的精美海报显示出来,通过点击对应的例子并将代码导入画布中 画布区 显示真实的海报效果,画布里添加的元素,都可以直接用鼠标进行拖动,旋转,缩放操作 操作区 第一排四个按钮 复制代码 将画布的展示效果转化成小程序海报插件库所需要的json配置代码,目前我使用的是Painter库,默认会转化成这个插件的配置代码,将代码直接复制到card.js即可 查看代码 这个功能用不用无所谓,可以直观的看到生成的代码 导出json 将画布转化成fabric所需要的json代码,方便将自己设计的海报代码保存下来 导入json 将第3步导出的json代码导入,会在画布上显示已设计的海报样式 第二排五个按钮 画布 画布的属性参数 详解见下方 文字 添加文字的属性参数 详解见下方 矩形 添加矩形的属性参数 详解见下方 图片 添加图片的属性参数 详解见下方 二维码 添加二维码的属性参数 详解见下方 第三排 各种元素的详细设置参数 激活区 激活对象是指鼠标点击画布上的元素,该对象会被蓝色的边框覆盖,此时该对象被激活,可以执行拖动 旋转 缩放等操作 激活区只有对象被激活才会出来,用来设置激活对象的各种配置参数,修改value值后,实时更新当前激活对象的对应状态,点击其他区域,此模块将隐藏 快捷键 ‘←’ 左移一像素 ‘→’ 右移一像素 ‘↑’ 上移一像素 ‘↓’ 下移一像素 ‘ctrl + z’ 撤销 ‘ctrl + y’ 恢复 ‘delete’ 删除 ‘[’ 提高元素的层级 ‘]’ 降低元素的层级 布局属性 通用布局属性 属性 说明 默认 rotate 旋转,按照顺时针旋转的度数 0 width、height view 的宽度和高度 top、left 如 css 中为 absolute 布局时的作用 0 background 背景颜色 rgba(0,0,0,0) borderRadius 边框圆角 0 borderWidth 边框宽 0 borderColor 边框颜色 #000000 shadow 阴影 ‘’ shadow 可以同时修饰 image、rect、text 等 。在修饰 text 时则相当于 text-shadow;修饰 image 和 rect 时相当于 box-shadow 使用方法: [代码]shadow: 'h-shadow v-shadow blur color'; h-shadow: 必需。水平阴影的位置。允许负值。 v-shadow: 必需。垂直阴影的位置。允许负值。 blur: 必需。模糊的距离。 color: 必需。阴影的颜色。 举例: shadow:10 10 5 #888888 [代码] 渐变色支持 你可以在画布的 background 属性中使用以下方式实现 css 3 的渐变色,其中 radial-gradient 渐变的圆心为 中点,半径为最长边,目前不支持自己设置。 [代码]linear-gradient(-135deg, blue 0%, rgba(18, 52, 86, 1) 20%, #987 80%) radial-gradient(rgba(0, 0, 0, 0) 5%, #0ff 15%, #f0f 60%) [代码] !!!注意:颜色后面的百分比一定得写。 画布属性 属性 说明 默认 times 控制生成插件代码的宽度大小,比如画布宽100,times为2,生成的值为200 1 文字属性 属性名称 说明 默认值 text 字体内容 别跟我谈感情,谈感情伤钱 maxLines 最大行数 不限,根据 width 来 lineHeight 行高(上下两行文字baseline的距离) 1.3 fontSize 字体大小 30 color 字体颜色 #000000 fontWeight 字体粗细。仅支持 normal, bold normal textDecoration 文本修饰,支持none underline、 overline、 linethrough none textStyle fill: 填充样式,stroke:镂空样式 fill fontFamily 字体 sans-serif textAlign 文字的对齐方式,分为 left, center, right left 备注: fontFamily,工具中的第一个例子支持文字字体,但是导入小程序为什么看不到呢,小程序官网加载网络字体方法>> 加载字体教程>> 文字高度 是maxLines lineHeight2个字段一起计算出来的 图片属性 属性 说明 默认 url 图片路径 mode 图片裁剪、缩放的模式 aspectFill mode参数详解 scaleToFill 缩放图片到固定的宽高 aspectFill 图片裁剪显示对应的宽高 auto 自动填充 宽度全显示 高度自适应居中显示 Tips(一定要看哦~) 本工具不考虑兼容性,如发现不兼容请使用google浏览器 painter现在只支持这几种图形,所以暂不支持圆,线等 如果编辑过程,一个元素被挡住了,无法操作,请选择对象并通过[ ]快捷键提高降低元素的层级 文字暂不支持直接缩放操作,因为文字大小和元素高度不容易计算,可以通过修改激活栏目maxLines lineHeight fontSize值来动态改变元素 如发现导出的代码一个元素被另一个元素挡住了,请手动调整元素的位置,json数组中元素越往后层级显示就越高,由于painter没有提供层级参数,所以目前只能这样做 本工具导出代码全是以px为单位,为什么不支持rpx, 因为painter在rpx单位下,阴影和边框宽会出现大小计算问题,由于原例子没有提供px生成图片方案,可以下载我这里修改过的demo>>Painter即可解决 文本宽度随着字数不同而动态变化,想在文本后面加个图标根据文本区域长度布局, 请参考Painter文档这块教程直接修改源码 由于本工具开发有些许难度,如出现bug,建议或者使用上的问题,请提issue,源码地址>>painter-custom-poster 海报贡献 如果你设计的海报很好看,并且愿意开源贡献,可以贡献你的海报代码和缩略图,例子代码文件在example中,按顺序排列,例如现在库里例子是example2.js,那你添加example3.js和example3.jpg图片,事例可以参考一下文件夹中源码,然后在index.js中导出一下 导出代码 代码不要格式化,会报错,请原模原样复制到json字段里 生成缩略图 刚开始我想在此工具中直接生成图片,但是由于浏览器图片跨域问题导致报错失败 所以请去小程序中生成保存图片,图片质量设置0.2,并去tinypng压缩一下图片 找到painter.js,替换下边这个方法,可以生成0.2质量的图片,代码如下 [代码] saveImgToLocal() { const that = this; setTimeout(() => { wx.canvasToTempFilePath( { canvasId: 'k-canvas', fileType: 'jpg', quality: 0.2, success: function(res) { that.getImageInfo(res.tempFilePath); }, fail: function(error) { console.error(`canvasToTempFilePath failed, ${JSON.stringify(error)}`); that.triggerEvent('imgErr', { error: error }); } }, this ); }, 300); } [代码] TODO 颜色值选择支持调色板工具 文字padding支持 缩放位置弹跳问题优化 假如需求大的话,支持其他几款插件库代码的生成 ~ 创作不易,如果对你有帮助,请给个星星 star✨✨ 谢谢 ~
2019-09-27 - 云开发,获取群ID——调试出来真的很简单。
1 app.js中 onLaunch: function (options) { if (!wx.cloud) console.error(‘请使用 2.2.3 或以上的基础库以使用云能力’) else wx.cloud.init({ traceUser: true, }) [代码]if (options.shareTicket) wx.getShareInfo({ shareTicket: options.shareTicket, success: function (res) { console.log('getShareTiket---shareTicket-->res', res) //获取cloudID let cID=res.cloudID //调用云函数mytest wx.cloud.callFunction({ name: 'mytest', // 这个 CloudID 值到云函数端会被替换 data: { weRunData: wx.cloud.CloudID(cID) }, success: function (res) { console.log('wx cloud mytest fun res', res); } }) } }) [代码] }, 2 云函数mytest const cloud = require(‘wx-server-sdk’) cloud.init() exports.main = (event, context) => { return { event } } /console.log(‘wx cloud mytest fun res’, res);查看打印出来的res, 真是一个惊喜。 不用npm,不用加密解密,不用传数据到自己开发服务器上。哎,一个群ID花了我好多时间啊,最后到底是迎来柳暗花明了。/
2019-09-24 - 几行代码实现小程序云开发提现功能
先看效果: [图片] 纯云开发实现,下面说使用步骤: 一:开通商户的企业付款到领取功能 说明地址: https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_1 使用条件 1、商户号(或同主体其他非服务商商户号)已入驻90日 2、截止今日回推30天,商户号(或同主体其他非服务商商户号)连续不间断保持有交易 使用条件是第一难,第二难在下面这里 [图片] 在网上找了很多,感觉是云开发这里的一个不完善地方,如果不填ip,会报这种错 [代码]{"errorCode":1,"errorMessage":"user code exception caught","stackTrace":"NO_AUTH"} [代码] [代码]<xml> <return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[此IP地址不允许调用接口,如有需要请登录微信支付商户平台更改配置]]></return_msg> <mch_appid><![CDATA[wx383426ad9ffe1111]]></mch_appid> <mchid><![CDATA[1536511111]]></mchid> <result_code><![CDATA[FAIL]]></result_code> <err_code><![CDATA[NO_AUTH]]></err_code> <err_code_des><![CDATA[此IP地址不允许调用接口,如有需要请登录微信支付商户平台更改配置]]></err_code_des> </xml> [代码] 云开发没有ip这个概念,所以这里有些无从下手,不过这里我采用了个替代方案,参考了社区帖子: https://developers.weixin.qq.com/community/develop/doc/00088cff3a40d87d80f7267b65b800 之后我也亲自验证了,基本上就是这几个,当然肯定不够,但是可以自己在逻辑上进行处理,ip以下: [代码]172.81.207.12 172.81.212.74 172.81.236.99 172.81.235.12 172.81.245.51 212.64.65.131 212.64.84.22 212.64.85.35 212.64.85.139 212.64.87.134 [代码] 接着,可以动手了 二、云开发部分 1、设置云存储 证书配置地址: [图片] 下载后有三个文件,我们只需要p12结尾的那个 [图片] 然后,将这个apiclient_cert.p12文件上传到你的云存储 [图片] 这里处理完了,我们只需要一个东西,就是fileID也就是常说的云存储ID(上图红框内容) 2、配置云函数 新建云函数ref云函数 [图片] 代码如下: [代码]const config = { appid: 'wx383426ad9ffe1111', //小程序Appid envName: 'zf-shcud', // 小程序云开发环境ID mchid: '1111111111', //商户号 partnerKey: '1111111111111111111111', //此处填服务商密钥 pfx: '', //证书初始化 fileID: 'cloud://zf-shcud.11111111111111111/apiclient_cert.p12' //证书云存储id }; const cloud = require('wx-server-sdk') cloud.init({ env: config.envName }) const db = cloud.database(); const tenpay = require('tenpay'); //支付核心模块 exports.main = async(event, context) => { //首先获取证书文件 const res = await cloud.downloadFile({ fileID: config.fileID, }) config.pfx = res.fileContent let pay = new tenpay(config,true) let result = await pay.transfers({ //这部分参数含义参考https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2 partner_trade_no: 'bookreflect' + Date.now() + event.num, openid: event.userinfo._openid, check_name: 'NO_CHECK', amount: parseInt(event.num) * 100, desc: '二手书小程序提现', }); if (result.result_code == 'SUCCESS') { //如果提现成功后的操作 //以下是进行余额计算 let re=await db.collection('user').doc(event.userinfo._id).update({ data: { parse: event.userinfo.parse - parseInt(event.num) } }); return re } } [代码] 需安装的依赖:wx-server-sdk、tenpay 这里只是实现了简单原始的提现操作,关于提现后,比如防止重复提交,提现限额这些,在开源二手书商城上有完整流程,地址: https://github.com/xuhuai66/used-book-pro 这种办法,不是每次都能成功提现,小概率遇到ip未在白名单情况,还是希望,云开发团队能尽快出一个更好的解决方案吧
2019-09-21 - 小程序上传图片到腾讯云对象存储COS的简单代码
const fs = require('fs') const COS = require('cos-nodejs-sdk-v5') const cos = new COS({ SecretId: 'SecretId', SecretKey: 'SecretKey', }) module.exports = async (ctx) => { const image = ctx.request.files.image //这里获得小程序wx.uploadFile上传的文件,文件标识名为image if(!image) return let ext = image.type.split('/')[1] let path = image.path let key = `image-${Date.now()}.${ext}`;//保存在cos的文件名 let TaskId; function p() { return new Promise((resolve, reject) => { cos.putObject({ Bucket: 'Bucket-1251490133', /* 必须 */ Region: 'cn-north', Key: key, /* 必须 */ Body: fs.createReadStream(path), ContentLength: fs.statSync(path).size }, function (err, data) { console.log(err || data); if (err) { reject(); } else { resolve("url/" + key); } fs.unlinkSync(path); }); }); } try{ ctx.body = await p() }catch (err){ console.log(err) } } [图片]
2020-10-20 - 云服务器调用msgSecCheck完成代码分享
云服务器代码: // 云函数入口文件 const cloud = require(‘wx-server-sdk’) cloud.init() // 云函数入口函数 exports.main = async (event, context) => { const {content} = event; try { const res = await cloud.openapi.security.msgSecCheck({ content:event.content }) return res; } catch (err) { return err; } } 本地函数: const cloudRes = await wx.cloud.callFunction({ name: ‘checkMsg’, data: { content:“我是要检测的文本” } }) if(cloudRes.result.errCode == ‘87014’){ wx.showToast({ title:‘内容含有违法违规内容’, icon:‘none’ }) return } [代码] 我相信做出来的人很多,但是没有分享出来,我今天分享出来就是为了避免更多程序员不要在这种简单的问题上,浪费太多的时间,我就浪费了很多时间,兼职太坑爹了[代码]
2019-12-04 - 巧用小程序·云开发实现邮件发送功能丨实战
先看效果图: [图片] 通过上面的日志,可以看出我们是158开头的邮箱给250开头的邮箱发送邮件,下面是成功接收到的邮件。 [图片] 准备工作 1、qq邮箱一个 2、开通你的qq邮箱的授权码(会具体讲解) 3、注册自己的小程序(因为只有注册的小程序才能使用云开发) 4、电脑要安装node(会用到npm命令行) 5、编写小程序代码 一、准备一个QQ邮箱,并启动SMTP服务 进入qq邮箱以后: 1、点击设置,然后点击账户 [图片] 2、开启POP3/SMTP服务,获取授权码 [图片] 具体操作可以看官方文档,官方文档有具体的讲解,这里我就不多说了。 官方文档:https://dwz.cn/SJCibDEi 我们获取的授权码如下图。请保存好这个授权码,我们后面发送邮件时会用到。 [图片] 二、注册小程序获取appid,创建一个小程序 关于小程序的注册和创建就不在此赘述,有需要的同学可以参照官方文档: https://dwz.cn/HpcWynVz 下图是我们创建好的小程序。 [图片] 代码很简单,就只有一个页面,页面上就一个按钮,我们点击这个按钮的时候实现邮件的发送。 三、初始化云开发,创建发送邮件的云函数 关于云开发初始化我这里也不在做具体讲解了,感兴趣或者不会的同学,可以去翻看腾讯云云开发公众号内菜单【技术交流-视频教程】中的教学视频。 初始化云开发环境时,需要注意以下几点: 1、一定要是注册的小程序有appid才可以使用云开发 2、一定要在app.js里初始化云开发环境id [图片] 3、在project.config.json里配置云函数目录,如下图箭头所示 [图片] 四、创建云函数 sendEmail 1、右键cloud文件,新建云函数: [图片] 这个函数名你可以随便起,只要是英文,并且调用的时候记得不要写错就行。我这里就用sendEmail。 2、创建完以后,右键sendEmail选择在终端里打开: [图片] 这里我们需要用npm安装一个依赖包 nodemailer 使用npm安装依赖包需要用到node,至于node的安装大家自行百度,一大堆的讲解文章。 3、在打开的命令行窗口里输入 npm install nodemailer: [图片] 4、等待 nodemailer类库的安装 [图片] 5、安装成功时,您能看到nodemailer的版本号 [图片] 五、编写发送邮件的核心代码 这里一定要注意填写你自己的qq邮箱的授权码: [图片] 代码里都有注释,直接把代码给大家贴出来。 [代码]const cloud = require('wx-server-sdk') cloud.init() //引入发送邮件的类库 var nodemailer = require('nodemailer') // 创建一个SMTP客户端配置 var config = { host: 'smtp.qq.com', //网易163邮箱 smtp.163.com port: 465, //网易邮箱端口 25 auth: { user: '1587072557@qq.com', //邮箱账号 pass: '这里要填你自己的授权码' //邮箱的授权码 } }; // 创建一个SMTP客户端对象 var transporter = nodemailer.createTransport(config); // 云函数入口函数 exports.main = async(event, context) => { // 创建一个邮件对象 var mail = { // 发件人 from: '来自小石头 <1587072557@qq.com>', // 主题 subject: '来自小石头的问候', // 收件人 to: '2501902696@qq.com', // 邮件内容,text或者html格式 text: '你好啊,编程小石头' //可以是链接,也可以是验证码 }; let res = await transporter.sendMail(mail); return res; } [代码] 六、上传云函数 编写完代码后,一定要记得上传云函数。 [图片] 七、调用云函数发送邮件 我们在index.wxml文件里写一个按钮,当点击这个按钮时就发送邮件。 [图片] 然后在index.js里调用我们的sendEmail云函数。 [图片] 八、点击发送邮件,查看效果 可以看到我们的控制台,打印里发送成功的日志信息: [图片] 然后到我们的邮箱里,可以看到新收到的邮件。 [图片] 到这里我们就完整的实现了微信小程序云开发使用云函数发送邮件的功能了。是不是很简单呢? 源码地址: https://github.com/TencentCloudBase/Good-practice-tutorial-recommended 如果你有关于使用云开发CloudBase相关的技术故事/技术实战经验想要跟大家分享,欢迎留言联系我们哦~比心! [图片]
2019-08-22 - 云函数发送email极简代码
const mailer = require('nodemailer-promise') exports.main = async (event, context) => { let sendEmail = mailer.config({ host: 'smtp.exmail.qq.com', //换成你邮箱的smtp port: 465, secure: true, //检查你邮箱的smpt服务器的设置 auth: { user: 'mailer@mycite.cn', //换成你的邮箱账号和密码 pass: 'Pwd' } }) let message = { from: 'anywords', to: event.to, subject: event.subject, text: event.text, } return await sendEmail(message) } [图片]
2020-10-20 - 云开发http api秒过的正确写法
let request = require('request-promise') let options = { method: 'POST', uri: 'https://api.weixin.qq.com/tcb/databasequery?access_token=' + access_token + '', body: { "env":'cloud-a8ee66', "query":`db.collection("col").doc("${colid}").get()`, }, json:true } let res = await request(options)
2019-08-22 - 极简代码之云开发的触底无限加载
js: [代码]const db = wx.cloud.database() const _ = db.command const col = "test" const sql = { _id: _.neq(1) } //获取所有记录 Page({ data: { isEndOfList: false, list: [], limit: 20 //每次拉取数量 }, onLoad: function(options) { this.getData() }, getData: function() { db.collection(col) .where(sql) .skip(this.data.list.length) .limit(this.data.limit) .get() .then(res => { this.setData({ list: [...this.data.list, ...res.data], //合并数据 isEndOfList: res.data.length < this.data.limit ? true : false //判断是否结束 }) }) }, onReachBottom: function() { this.data.isEndOfList || this.getData() } }) [代码] wxml [代码]<view style="height:100px" wx:for='{{list}}' wx:key='none'>{{index}}</view> <view style="padding:15px;text-align:center;color:grey" wx:if='{{list.length>limit}}'> <view wx:if='{{(!isEndOfList)}}'>正在加载数据...</view> <view wx:else>----END----</view> </view> [代码]
2020-06-16 - 如何实现一个自定义导航栏
自定义导航栏在刚出的时候已经有很多实现方案了,但是还有大哥在问,那这里再贴下代码及原理: 首先在App.js的 onLaunch中获取当前手机机型头部状态栏的高度,单位为px,存在内存中,操作如下: [代码]onLaunch() { wx.getSystemInfo({ success: (res) => { this.globalData.statusBarHeight = res.statusBarHeight this.globalData.titleBarHeight = wx.getMenuButtonBoundingClientRect().bottom + wx.getMenuButtonBoundingClientRect().top - (res.statusBarHeight * 2) }, failure() { this.globalData.statusBarHeight = 0 this.globalData.titleBarHeight = 0 } }) } [代码] 然后需要在目录下新建个components文件夹,里面存放此次需要演示的文件 navigateTitle WXML 文件如下: [代码]<view class="navigate-container"> <view style="height:{{statusBarHeight}}px"></view> <view class="navigate-bar" style="height:{{titleBarHeight}}px"> <view class="navigate-icon"> <navigator class="navigator-back" open-type="navigateBack" wx:if="{{!isShowHome}}" /> <navigator class="navigator-home" open-type="switchTab" url="/pages/index/index" wx:else /> </view> <view class="navigate-title">{{title}}</view> <view class="navigate-icon"></view> </view> </view> <view class="navigate-line" style="height: {{statusBarHeight + titleBarHeight}}px; width: 100%;"></view> [代码] WXSS文件如下: [代码].navigate-container { position: fixed; top: 0; width: 100%; z-index: 9999; background: #FFF; } .navigate-bar { width: 100%; display: flex; justify-content: space-around; } .navigate-icon { width: 100rpx; height: 100rpx; display: flex; justify-content: space-around; } .navigate-title { width: 550rpx; text-align: center; line-height: 100rpx; font-size: 34rpx; color: #3c3c3c; font-weight: bold; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; } /*箭头部分*/ .navigator-back { width: 36rpx; height: 36rpx; align-self: center; } .navigator-back:after { content: ''; display: block; width: 22rpx; height: 22rpx; border-right: 4rpx solid #000; border-top: 4rpx solid #000; transform: rotate(225deg); } .navigator-home { width: 56rpx; height: 56rpx; background: url(https://qiniu-image.qtshe.com/20190301home.png) no-repeat center center; background-size: 100% 100%; align-self: center; } [代码] JS如下: [代码]var app = getApp() Component({ data: { statusBarHeight: '', titleBarHeight: '', isShowHome: false }, properties: { //属性值可以在组件使用时指定 title: { type: String, value: '青团公益' } }, pageLifetimes: { // 组件所在页面的生命周期函数 show() { let pageContext = getCurrentPages() if (pageContext.length > 1) { this.setData({ isShowHome: false }) } else { this.setData({ isShowHome: true }) } } }, attached() { this.setData({ statusBarHeight: app.globalData.statusBarHeight, titleBarHeight: app.globalData.titleBarHeight }) }, methods: {} }) [代码] JSON如下: [代码]{ "component": true } [代码] 如何引用? 需要引用的页面JSON里配置: [代码]"navigationStyle": "custom", "usingComponents": { "navigate-title": "/pages/components/navigateTitle/index" } [代码] WXML [代码]<navigate-title title="青团社" /> [代码] 按上面步骤操作即可实现一个自定义的导航栏。 如何实现通栏的效果默认透明以及滚动更换title为白色背景,如下图所示: [图片] [图片] [图片] [图片] 最后代码片段如下: https://developers.weixin.qq.com/s/wi6Pglmv7s8P。 以下为收集到的社区老哥们的分享: @Yunior: 小程序顶部自定义导航组件实现原理及坑分享 @志军: 微信小程序自定义导航栏组件(完美适配所有手机),可自定义实现任何你想要的功能 @✨o0o有脾气的酸奶💤 [有点炫]自定义navigate+分包+自定义tabbar @安晓苏 分享一个自适应的自定义导航栏组件
2020-03-10 - 借助小程序云开发实现小程序支付功能(含源码)
我们在做小程序支付相关的开发时,总会遇到这些难题。小程序调用微信支付时,必须要有自己的服务器,有自己的备案域名,有自己的后台开发。这就导致我们做小程序支付时的成本很大。本节就来教大家如何使用小程序云开发实现小程序支付功能的开发。不用搭建自己的服务器,不用有自己的备案域名。只需要简简单单的使用小程序云开发。 老规矩先看效果图: [图片] 本节知识点 1,云开发的部署和使用 2,支付相关的云函数开发 3,商品列表 4,订单列表 5,微信支付与支付成功回调 支付成功给用户发送推送消息的功能会在后面讲解。 下面就来教大家如何借助云开发使用小程序支付功能。 支付所需要用到的配置信息 1,小程序appid 2,云开发环境id 3,微信商户号 4,商户密匙 一,准备工作 1,已经申请小程序,获取小程序 AppID 和 Secret 在小程序管理后台中,【设置】 →【开发设置】 下可以获取微信小程序 AppID 和 Secret。 [图片] 2,微信支付商户号,获取商户号和商户密钥在微信支付商户管理平台中,【账户中心】→【商户信息】 下可以获取微信支付商户号。 [图片] 在【账户中心】 ‒> 【API安全】 下可以设置商户密钥。 [图片] 这里特殊说明下,个人小程序是没有办法使用微信支付的。所以如果想使用微信支付功能,必须是非个人账号(当然个人可以办个体户工商执照来注册非个人小程序账号) 3,微信开发者 IDE https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html 4,开通小程序云开发功能:https://edu.csdn.net/course/play/9604/204526 二,商品列表的实现 效果图如下,由于本节重点是支付的实现,所以这里只简单贴出关键代码。 [图片] wxml布局如下: [代码]<view class="container"> <view class="good-item" wx:for="{{goods}}" wx:key="*this" ontap="getDetail" data-goodid="{{item._id}}"> <view class="good-image"> <image src="{{pic}}"></image> </view> <view class="good-detail"> <view class="title">商品: {{item.name}}</view> <view class="content">价格: {{item.price / 100}} 元 </view> <button class="button" type="primary" bindtap="makeOrder" data-goodid="{{item._id}}" >下单</button> </view> </view> </view> [代码] 我们所需要做的就是借助云开发获取云数据库里的商品信息,然后展示到商品列表,关于云开发获取商品列表并展示本节不做讲解(感兴趣的同学可以翻看我的历史博客,有写过的) 也有视频讲解: https://edu.csdn.net/course/detail/9604 [图片] 三,支付云函数的创建 首先看下我们支付云函数都包含那些内容 [图片] 简单先讲解下每个的用处 config下的index.js是做支付配置用的,主要配置支付相关的账号信息 lib是用的第三方的支付库,这里不做讲解。 重点讲解的是云函数入口 index.js 下面就来教大家如何去配置 1,配置config下的index.js, 这一步所需要做的就是把小程序appid,云开发环境ID,商户id,商户密匙。填进去。 [图片] 2,配置入口云函数 [图片] 详细代码如下,代码里注释很清除了,这里不再做单独讲解: [代码]const cloud = require('wx-server-sdk') cloud.init() const app = require('tcb-admin-node'); const pay = require('./lib/pay'); const { mpAppId, KEY } = require('./config/index'); const { WXPayConstants, WXPayUtil } = require('wx-js-utils'); const Res = require('./lib/res'); const ip = require('ip'); /** * * @param {obj} event * @param {string} event.type 功能类型 * @param {} userInfo.openId 用户的openid */ exports.main = async function(event, context) { const { type, data, userInfo } = event; const wxContext = cloud.getWXContext() const openid = userInfo.openId; app.init(); const db = app.database(); const goodCollection = db.collection('goods'); const orderCollection = db.collection('order'); // 订单文档的status 0 未支付 1 已支付 2 已关闭 switch (type) { // [在此处放置 unifiedorder 的相关代码] case 'unifiedorder': { // 查询该商品 ID 是否存在于数据库中,并将数据提取出来 const goodId = data.goodId let goods = await goodCollection.doc(goodId).get(); if (!goods.data.length) { return new Res({ code: 1, message: '找不到商品' }); } // 在云函数中提取数据,包括名称、价格才更合理安全, // 因为从端里传过来的商品数据都是不可靠的 let good = goods.data[0]; // 拼凑微信支付统一下单的参数 const curTime = Date.now(); const tradeNo = `${goodId}-${curTime}`; const body = good.name; const spbill_create_ip = ip.address() || '127.0.0.1'; // 云函数暂不支付 http 触发器,因此这里回调 notify_url 可以先随便填。 const notify_url = 'http://www.qq.com'; //'127.0.0.1'; const total_fee = good.price; const time_stamp = '' + Math.ceil(Date.now() / 1000); const out_trade_no = `${tradeNo}`; const sign_type = WXPayConstants.SIGN_TYPE_MD5; let orderParam = { body, spbill_create_ip, notify_url, out_trade_no, total_fee, openid, trade_type: 'JSAPI', timeStamp: time_stamp, }; // 调用 wx-js-utils 中的统一下单方法 const { return_code, ...restData } = await pay.unifiedOrder(orderParam); let order_id = null; if (return_code === 'SUCCESS' && restData.result_code === 'SUCCESS') { const { prepay_id, nonce_str } = restData; // 微信小程序支付要单独进地签名,并返回给小程序端 const sign = WXPayUtil.generateSignature({ appId: mpAppId, nonceStr: nonce_str, package: `prepay_id=${prepay_id}`, signType: 'MD5', timeStamp: time_stamp }, KEY); let orderData = { out_trade_no, time_stamp, nonce_str, sign, sign_type, body, total_fee, prepay_id, sign, status: 0, // 订单文档的status 0 未支付 1 已支付 2 已关闭 _openid: openid, }; let order = await orderCollection.add(orderData); order_id = order.id; } return new Res({ code: return_code === 'SUCCESS' ? 0 : 1, data: { out_trade_no, time_stamp, order_id, ...restData } }); } // [在此处放置 payorder 的相关代码] case 'payorder': { // 从端里出来相关的订单相信 const { out_trade_no, prepay_id, body, total_fee } = data; // 到微信支付侧查询是否存在该订单,并查询订单状态,看看是否已经支付成功了。 const { return_code, ...restData } = await pay.orderQuery({ out_trade_no }); // 若订单存在并支付成功,则开始处理支付 if (restData.trade_state === 'SUCCESS') { let result = await orderCollection .where({ out_trade_no }) .update({ status: 1, trade_state: restData.trade_state, trade_state_desc: restData.trade_state_desc }); let curDate = new Date(); let time = `${curDate.getFullYear()}-${curDate.getMonth() + 1}-${curDate.getDate()} ${curDate.getHours()}:${curDate.getMinutes()}:${curDate.getSeconds()}`; } return new Res({ code: return_code === 'SUCCESS' ? 0 : 1, data: restData }); } case 'orderquery': { const { transaction_id, out_trade_no } = data; // 查询订单 const { data: dbData } = await orderCollection .where({ out_trade_no }) .get(); const { return_code, ...restData } = await pay.orderQuery({ transaction_id, out_trade_no }); return new Res({ code: return_code === 'SUCCESS' ? 0 : 1, data: { ...restData, ...dbData[0] } }); } case 'closeorder': { // 关闭订单 const { out_trade_no } = data; const { return_code, ...restData } = await pay.closeOrder({ out_trade_no }); if (return_code === 'SUCCESS' && restData.result_code === 'SUCCESS') { await orderCollection .where({ out_trade_no }) .update({ status: 2, trade_state: 'CLOSED', trade_state_desc: '订单已关闭' }); } return new Res({ code: return_code === 'SUCCESS' ? 0 : 1, data: restData }); } } } [代码] 其实我们支付的关键功能都在上面这些代码里面了。 [图片] 再来看下,支付的相关流程截图 [图片] 上图就涉及到了我们的订单列表,支付状态,支付成功后的回调。 今天就先讲到这里,后面会继续给大家讲解支付的其他功能。比如支付成功后的消息推送,也是可以借助云开发实现的。 由于源码里涉及到一些私密信息,这里就不单独贴出源码下载链接了,大家感兴趣的话,可以私信我,或者在底部留言。单独找我要源码也行(微信2501902696) 视频讲解地址:https://edu.csdn.net/course/detail/24770
2019-06-11 - 借助云开发实现小程序模版消息推送(不用搭建服务器就可以实现微信消息推送)
上一节给大家将了借助云开发实现小程序支付功能,那么我们就要想了,能不能借助云开发实现小程序消息推送功能呢? 还别说,云开发还真能实现推送的功能。 一直关注我的同学肯定知道老师之前也写过借助java后台实现小程序消息推送的文章。 我们借助java后台虽然也能轻松的实现消息推送。但是呢?用java开发后台推送,必须要搭建服务器,学习java代码,部署java代码当然你就是做java开发的,或者学习过java,这没什么。 但是作为小程序开发人员来说,用java显得太重了。 传送门: 《借助小程序云开发实现小程序支付功能(含源码)》 《5行代码实现微信小程序模版消息推送 (含推送后台和小程序源码)》 下面就来教大家如何借助云开发实现小程序模版消息的推送功能。 老规矩,先看效果图 [图片] 下面来讲实现步骤 一,定义推送的云函数 由于我们的云推送功能只能在云函数里调用,所以我们这里必须要在云函数里实现推送功能。 1,首先我们定义一个云函数push0524。 如果你还不知道如何使用云开发,如何定义云函数,去翻下老师之前的文章。有写的。 [图片] 把完整的代码贴给大家 [代码]// 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init() // 云函数入口函数 exports.main = async(event, context) => { console.log(event) return sendTemplateMessage(event) } //小程序模版消息推送 async function sendTemplateMessage(event) { const { OPENID } = cloud.getWXContext() // 接下来将新增模板、发送模板消息、然后删除模板 // 注意:新增模板然后再删除并不是建议的做法,此处只是为了演示,模板 ID 应在添加后保存起来后续使用 const addResult = await cloud.openapi.templateMessage.addTemplate({ id: 'AT0002', keywordIdList: [3, 4, 5] }) const templateId = addResult.templateId //新增的模版id const sendResult = await cloud.openapi.templateMessage.send({ touser: OPENID, templateId, formId: event.formId, page: 'pages/index/index', data: { keyword1: { value: '云开发实现推送', }, keyword2: { value: '2019 年 5 月 24 日', }, keyword3: { value: '编程小石头', }, } }) //删除模版id await cloud.openapi.templateMessage.deleteTemplate({ templateId, }) return sendResult } [代码] 上面代码所实现的就是 1,创建模版,拿到模版id 2,使用模版ID,填充模版消息,发送模版 3,删除模版。 我们正常开发时,模版都是在小程序后台获取到的。这里是为例演示方便。所以正常开发时,只需要实现第二步就行了。 推送的关键代码就是这个方法: cloud.openapi.templateMessage.send 通常我们定义完push0524云函数以后,如果直接调用的话,会报错误的。 [图片] 来看下这个错误,看到红色框里的permission就知道,肯定是权限的问题。所以我们在定义完云函数以后,要在push0524云函数下面添加权限配置页面。如下图 [图片] 重要的就是这个: “templateMessage.send”, 推送权限。因为推送是云开发给我们提供的,我们这里调用时,必须配置相关权限,才能使用的。 到这里我们的推送功能就实现了。下面我们来验证下。 二,验证云开发推送 验证其实很简单,和我们之前的《5行代码实现微信小程序模版消息推送 (含推送后台和小程序源码)》 类似。只不过一个是在java后台推送,一个是在小城里推送。下面我们简单写个小程序里验证推送的demo。 功能很简单 1,获取formid,因为推送必须有formid的 2,点击调用push0524实现推送 [图片] 简单的贴下代码 [图片] [图片] 需要注意的一点:我们测试时,必须要真机测试。因为模拟器没法获取到formid的。 [图片] 我们在推送成功的success回调中打印下log。如果log中出现,send:ok字样,就代表我们推送成功了。来看下推送成功的效果。 微信聊天列表接收到了消息提醒 [图片] 消息内容 [图片] 到这里我们就用云开发实现完整的消息推送功能了。是不是很简单。 有任何关于编程的问题都可以加老师微信 2501902696(备注小程序)也可以找老师索要完整源码。 编程小石头码农一枚,非著名全栈开发人员。分享自己的一些经验,学习心得,希望后来人少走弯路,少填坑 视频讲解地址:https://edu.csdn.net/course/detail/24770
2019-06-11 - 关于一个身份证绑定上限为5个问题
以企业为主体注册小程序,能注册50个,而每个身份证只能绑定5个。 开发人员少的公司,每次登录小程序后台,还得去找不同的人要手机,扫码!(在后台可以进行开发人员设置,从而实现部分管理功能。然而这个规则确实不合理,假如公司注册几十个小程序,得找好几个人一起注册才行。万一涉及到类目等设置,还必须得用注册者的微信去扫码,非常非常不方便) 这样合理吗? 墙裂建议官方去掉身份证只能绑5个上限,或者有申请渠道可以多绑定一些!
2018-07-12