- 前辈们,云函数删除数据库表(集合)怎么做呀?
db.team_id.drop() db.collection('team_id_01').remove() 试了几种方法,报错: Cannot read property 'remove' of undefined Cannot read property 'drop' of undefined
2023-05-28 - App分享小程序卡片,如何能够禁止/识别二次转发?
需求:在App分享小程序卡片给用户/群聊后,禁止该卡片被二次转发,或者能够识别出该小程序卡片被二次转发过。 问题背景:我查阅了微信的“私密消息”文档【1】,文档上只介绍了从小程序中进行转发设置私密消息的能力,看上去私密消息能够满足禁止/识别二次转发的需求。但是在安卓的SDK【2】中,我没有找到设置activityId和将转发设置为私密消息的选项,因此不确定在App分享小程序卡片,能否有办法实现这个需求? 具体问题: 从App中分享的小程序卡片是否支持私密消息?如果App分享不支持私密消息,有什么办法禁止/识别分享的小程序卡片被二次转发? 恳请大家帮忙解答,求助官方~ 【1】私密消息:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/share/private-message.html#_2-%E9%AA%8C%E8%AF%81 【2】安卓SDK文档:https://dev.weixin.qq.com/docs/framework/dev/jsapi/miniapp/shareMiniProgramMessage.html?utm_source=Share_and_Favorites_iOS
2023-10-31 - 云开发聚合函数group,能否对多个字段进行group分组?
我想要从以下记录中,先按task_id分组,再按stuClass分组,最后统计出status=1(只有0、1二值)的总和。求大佬指点一二。 我用group聚合函数,只能统计某一个字段的分组额... [图片]
2019-11-10 - 云开发聚合函数group,如何对按照日期字段进行group分组?
如下图,左边是静态页面显示的数据格式,右边是某个相册数据表。请问如何根据createTime字段分组。 [图片] 期望查询出来的数据格式: [图片] 别人实现参考:https://developers.weixin.qq.com/community/develop/doc/000c42f02783600cff69816075bc00?highLine=%25E4%25BA%2591%25E5%25BC%2580%25E5%258F%2591%2520%25E6%2597%25A5%25E6%259C%259F%25E5%2588%2586%25E7%25BB%2584
2020-05-08 - 做好私域,小商户需要具备哪三个要素?
[视频] 什么样的小餐饮商户,适合做好私域呢? 收钱吧根据众多商户的经验总结,发现只要具有以下三大要素,小餐饮商户一样可以运作好自己的私域,获得不错的订单量。 第一:门店有不错的顾客复购率基础,顾客的消费频次较高。要做到这一点,口味、分量、价格、卫生等多方面因素不能有短板,最好有长板。 第二:顾客群在地理位置上有较高的集中度。高校、写字楼、办公园区、封闭厂区等人员密度高的地区,都是不错的选择。 第三:商户经营者愿意花时间经营维护自己的私域客户,经常和客户互动,与客户有好的关系。 如果具备这些要素,不妨尝试建立自己的私域,让自己的生意更多的掌握在自己手上。
2022-08-22 - 小程序功能全景图
[视频] 未来,我会从这五个角度,向你介绍微信小程序的都有哪些功能。 首先核心是「用小程序来做服务」,小程序有各种功能,你可以用小程序给你的客户提供各种服务。例如,商城、点餐、支付、停车、连接Wi-Fi 这样的服务。做小程序前或许你得想清楚,你希望到底想用小程序来做什么? 紧接着,我会回答这几个问题,客户为什么要来小程序,怎么拉到更多客户;如何给小程序客户发消息,让他们持续回来,客户来了小程序,我们要做什么提高转化化率,有什么玩法。这就对应着三个问题,如何「给小程序拉客户」、「给客户发消息」、「小程序内的玩法」。 最后,我会给大家说,小程序都有哪些基础工具可以帮助大家提高运营效率,拓展使用场景。
2022-08-22 - 怎么查看个人小程序的累计独立访客(UV)?
累计独立访客(UV)不低于1000,这个在哪来看呢?小程序数据助手上没看到这个指标
2020-02-06 - 云开发点赞功能设计思路?
想做一个关于点赞的功能,目前云数据库有了文章的_id, 有个点赞的数量count,每次点赞的时候数量也会增加, 但是根据不同的用户,打开这个页面时,怎么判断是否已经点赞了? 数据库里还需要什么字段呢?每个用户点赞,要把用户的信息也存入数据库么? 不太懂这个数据库该怎么设计,求大家帮助!
2020-03-14 - 【干货】如何做好小程序数据埋点
背景:在接触过上百家头部客户中,诊断和参与了数百次的数据体系搭建工作。几乎80%的App都没有科学的埋点规划,只采集显性数据,而更深层的与事件、参数相关的隐性数据,都没有采集到。埋点规划并不难!但为什么大部分企业都做的不太好?埋点规划需要整合产品、运营、技术和业务等跨部门的需求,运营同学不太懂技术、技术同学不太懂业务、产品同学不太懂埋点,这问题该如何解?在友盟+《战疫求生,开发者的危与机》直播公开课上,友盟+业务专家张跃梳理一套方法论。带你从埋点的坑、结构化的埋点方案、高效的事件管理入手进行结构化埋点。 一、 在埋点前,先带你避开埋点的深坑 第一坑:遗漏,指的是埋点采集不全面,有可能重要的数据并没有采集到,会对数据分析造成比较直接的影响,出现这个问题的原因是前期数据分析需求不清晰。 第二坑:杂乱。指的是数据采集比较零散,可以理解为前期并没有进行事件结构化的设计,通常是想到一个需求,就把这个需求提供给技术进行埋点。这种称之为“扁平化”的埋点方式,例如:某一个位置或者某一个功能的点击行为,就当做一个事件进行采集,看上去采集和查看很容易,但随着时间跟需求的增加,当采集了大量零散的事件之后,需要在统计工具中通过分组分析时,就会比较麻烦。 第三坑:低效。不同于杂乱,杂乱是任何行为数据都会直接当事件去进行采集,没有利用参数去进行结构化的设计。低效指的是在事件设计的时候,会去做结构化处理。但事件设计的参数逻辑会有问题,通常都是以大的页面这种框架的思维去进行设计。 举个例子:部分客户在设计时,会按照页面的思路去进行事件采集,页面上有推荐位,还有很多功能按钮的点击,那么就会把这个页面所有的点击行为都归到一个事件,并且点击具体的按钮和内容都当做参数传回来。但这里埋着两个雷区:1、在分析数据时,例如想了解整个用户浏览内容的情况,或者是想了解某个功能(搜索引擎)整体使用情况,按照如上设计,内容和功能的采集都分布在每一个事件中了,这样后面再归类、分析就非常不方便。2、当产品结构产生变化时,原有事件调整概率会比较大,因为之前都是按页面结构去设计,页面的调整直接影响事件采集。 第四坑:无用。指的是数据虽然采集了,但分析时根本用不上,这个问题主要有2个原因导致,一是前期需求不太清晰,另一个是之前的采集需求都是由不同人提出的,由于中间人员变动,很多采集需求就不清楚了,并且也不敢下掉,因为并不清楚这个事件是否还有人使用。 第五坑:复用。指的是事件重复采集,或者是需求重复,这个同样是与多个人提需求有关,并没有一个人去做整合管理,或者是说,没有一个工具去帮忙我们做管理。 二、如果想要避免这些坑,就需要坚守五个原则: 1、需求清晰。 2、合理设计。 3、实施规范。 4、结果可验 5、规范管理。 三、 埋点方法论——五步一全(ODEIIC),需要多角色参与统筹决策 第一、需求梳理。在梳理埋点设计的时候,通常会以产品、运营和市场以及KPI三个视角去切入。通常,产品关注的核心业务点会聚焦在内容和功能上,运营和市场关注的业务点在拉新、留存、促活和转化上,KPI视角会聚焦在转化与收入上,但也需要根据客户的实际情况而定。 同时,会把不同视角的业务需求再转化成需要关注的核心数据,如产品运营在内容上所需要关注用户浏览、内容的转发或者是偏好,针对功能使用会关注注册、登录、搜索等这些功能的使用情况。 [图片] 业务需求拆解成核心数据后,针对每一个核心数据进行维度的细分,如内容方面:会按照标题、频道或者是标签,进行拆分分析。那么我们针对功能方面,会按照功能使用情况以及步骤的转化去进行分析。通过要分析的关键点,就可以把细分维度拆出来,最后还会再加上一些通用的维度,例如可以对单个用户或者某一个地区的用户进行深度分析。 以产品视角的需求样例,产品通常情况下会聚焦内容与功能上的使用,但在需求收集时都是分散和抽象的,例如:业务需要分析内容偏好和推荐效果以及内容受欢迎的程度。那在这个环节就需要先做需求拆解,也就是说要去找到能分析这个需求的核心数据与能够帮助判断业务变化的一些指标,细分维度在这里的作用更多的是做需求详细的拆解,可以理解为是去做核心数据的多维度明细展示,那么目的就是从更细的维度去满足业务分析需求; 总结:先要找到能满足这个需求的核心数据,再找到核心数据分析时所需要涉及的细分维度,如图: [图片] 第二、事件设计。可以通过这3个步骤去完成事件的结构化设计,第一个步骤是要了解产品结构,也就是先要了解分析的范围是什么,例如需要知道对哪些页面或者哪些功能有分析需求;第二步,就是要针对这些锁定的范围,去明确我们要分析用户的行为有哪些;第三步,要把这些行为,落实到具体的分析维度上; 后面会通过指标体系、分析需求、分析方法这3个角度,在去结合这三个步骤,进行事件结构化设计的详细说明。 [图片] 在介绍按照指标体系去进行结构化事件设计前,我们先看下指标体系的样例,通常会按照这几个模块去搭建指标体系,分为:概况、营销、用户价值、运营和核心功能。 1、概况可以理解日常关注的核心数据,比如:新增、启动、日活、周活、月活以及会员数据、注册数据以及使用黏性、使用时长、留存等,还包括技术、产品较为关注的稳定性数据。总的来说:就是将核心或常看的数据放在概况的大板块中。 [图片] 2、营销。通常会把广告数据,例如:广告的曝光、点击率以及广告点击排行,媒体排行、展示排行信息会放在第二个板块。 3、用户价值。通常会把新用户的次留、成本以及用户回本周期模型和生命周期模型放在用户价值模块。 4、运营。主要关注内容与转化,通常会分析内容的热度,任务的交互与会员的转化,针对会员还会分析会员新增、会员累计、会员续费等维度。 5、核心功能。是产品岗位较为关注的,例如:导航位、导航按钮,被用户点击的情况、使用的情况,对应核心功能,比如说搜索功能或者是注册功能,整个功能的入口、被点击的情况和转化率等相关的这些数据会放到这个板块。 从指标体系到事件设计 [图片] 如何通过指标体系去进行结构化设计?指标体系可以理解为指标与报表的一个组合,整个指标体系对应到产品结构上,可以分为对产品页面和产品功能的分析需求。下面先从产品页面的角度去进行事件设计说明: [图片] 第一步,会先锁定页面的范围,比如产品里有活动页、内容页、如果是视频App的话会有播放页,小说App会有阅读或者是听书页面。 第二步,范围圈定后就需要找分析行为,用户看到内容是否有点击行为,进入页面后的浏览行为,以及是否有分享、评论等行为。 第三步,确定了要分析的行为后,就需要进行分析维度的细化,如要分析用户浏览(浏览完成行为)内容都有哪些,还想分析用户是哪个入口(来源)进入到页面等等,这些都是针对用户行为要分析的维度; 按照这三步梳理清楚后,事件设计中与产品页面相关的事件和参数就能整理出来了,如页面范围对应的“内容页”和分析行为对应的“点击”行为,就能够清楚我们要采集的事件为“内容点击”,在根据这个事件需要分析的维度是页面名称、页面分类以及页面来源,这个事件所需要的参数也就找到了。 下图中是以内容页和活动页梳理的结构化事件样例。 [图片] 以产品功能的角度去进行事件设计说明: [图片] 同样,第一步先找到要分析哪些功能。比如:搜索、登录、注册、会员、付费、签到等,第一步找到监测功能的范围。 第二步在找行为,功能层面的行为比内容会稍微简单一些,主要是点击行为或者是完成状态。 第三步是维度,例如:搜索功能,想分析搜索入口的点击情况,搜索的关键词是什么,针对登录与充值的话,需要分析帐号登录的类型、充值的方式等等。 页面功能所产出的结构化事件样例[图片] 以搜索引擎为例:搜索引擎监测的行为是点击和完成,通常会用两个事件进行监测,搜索引擎功能在很多页面都会有入口, 通常会建议在这里增加一个参数叫搜索位置,可以辨识用户点击哪些搜索位的按钮,另外可增加参数叫用户ID,去了解具体是哪些用户进行的点击。 重点说一下功能按钮点击事件。通常情况下,会将核心要分析的功能都抽离成单独的事件进行统计。如登录、注册、付费或者是会员购买等,这些属于核心要关注的功能,并且会为这些核心功能事件单独设计要分析的参数; 但如扫一扫、加载更多以及一些Tab键,只需要监测用户点击即可 ,不需要监测功能背后的参数信息。通常会将这些点击行为放在一个事件下,定义名称叫功能按钮点击,会通过“按钮名称“与“所属页面”等参数去锁定用户点的具体按钮是哪个。 小结,通过指标体系去进行事件设计,就能够把大部分需要采集的页面与功能都能覆盖到,并且可以满足后期看数据的需求。 从分析需求到事件设计 [图片] 先引用小说行业的一个需求举例,近期上架了新书,要分析新书对用户的吸引力如何。那么第一步,就要把需求进行转义,也就是需要知道哪些数据和维度,能证明用户对新书的吸引力。 针对这个需求,分析思路是:今天新上架的小说,用户看了多少章节和时间,明天会不会继续来看,可以通过这几个维度去判断出新书吸引力。那么在落实到事件设计的三个步骤中,第一步采集的页面范围是小说页面,第二步采集的行为就是阅读,这两步对应出我们需要采集的事件就是小说阅读,第三步需要分析的维度就是阅读章节、阅读时长、小说名称以及上线日期,这些维度就可以转化成参数在事件中设计进来。 另外,一般做内容事件时,通常还会增加来源参数,比如:来源页面、来源版块、来源位置,这些参数可以帮我们定位到用户是从那些入口获取到内容的,便于后期去分析各入口的导流效率。 从分析方法到事件设计 [图片] 这部分指的是根据核心目标,在利用一套分析方法去解决问题时,如何找到解决问题环节中所需要采集的事件。 比如,目标锁定是要提升用户留存或者是提升付费转化率,那么,首先要找到不同的人群,针对人群找差异(功能使用、内容偏好的差异),找到不同的人群在功能使用、以及转化路径的差异后,在去找问题,如某一些功能对于非留存用户或者是非付费用户体验不好或推荐的内容用户不感兴趣,找到问题后,就需要进行优化,并进行验证;针对分析方法中的每个环节,其实都能对应到需要分析的事件,如找问题的环节会对入口的点击、完成的情况,内容浏览的来源等等进行事件采集,在分人群环节,会对用户的付费行为进行事件采集等等。 通过每个环节找到对应需要分析的行为后,就可以把相关信息以事件或者是参数的形式,补充到现有结构化埋点方案中了。 按照指标、需求、方法这3个角度去做了事件设计方法的介绍,总体可归纳为:有了指标体系与分析需求,整个结构化埋点方案的框架就能设计出来了。分析方法更多的作用是做分析思路上的贯穿,可以帮我们发现埋点设计中缺少或者遗漏的环节,整体上我们就可以理解为,指标体系+分析需求+分析方法这三部分的结合,才能得到一个非常贴合业务的埋点方案。 [图片] 小结:“事件采集“就是要知道谁在什么时候做了什么事情,设计思路可以分为三步,首先,了解产品结构(产品结构的范围,页面结构、功能结构)其次,了解用户行为(点击行为、完成行为、曝光行为等)最后,行为可以细分哪些维度,按照三步结构化事件就可以设计完成了。 同时,总结三个避坑的Tips: 一,需求。如果前期需求不是很明确时,可以先把这个指标体系梳理起来,比如:核心关注的指标,采集方案是可以满足暂时看数的需求,后期可以根据对分析需求的升级再去补充。 二,归类。在事件设计时要合理的进行归类,尽量用一个事件满足多个分析需求。比如,了解用户都是从哪些入口获取内容的,和内容浏览的热度排行。是可以通过一个事件来实现的,只需要通过内容名称和来源页面两个参数,就能够满足这两个需求了。 三,范围,在参数设计中两个范围需要注意,即来源和点击按钮,内容采集会涉及三个来源:来源页面、来源板块和来源位置,是为了去锁定到底内容从哪里点过来,开发也会要求将入口信息梳理清楚,从而进行埋点的开发工作。点击按钮,将按钮都归属到一个事件中,将参数设置为按钮名称,梳理出具体的按钮采集的范围给到开发,才能去进行后续的埋点。 埋点设计不是简单的事件与参数的结合,而是需要贴合业务、贴合分析场景去进行设计。 结构化事件设计完成后,下一步就是要交付给技术进行开发,下图为一个资讯行业的事件埋点模版,可以参照这个模板去进行梳理并提交给技术。友盟+开发者数据银行产品中的智能采集平台就可以按照这个模板,直接帮我们生成对应的埋点方案,并协助我们进行后续的事件管理。 [图片] 三、埋点实施 市场上主流支持的四种埋点方式,分别是代码埋点、服务端埋点、可视化埋点和全埋点。 代码埋点,支持事件与参数这种结构化的使用方式,弊端是想增加或修改事件,都需要重新发版,用户更新后才能采集。 服务端埋点,通常用于业务数据的采集,例如:付费成功、用户注册等,这个场景会选择用服务埋点进行采集。 可视化埋点和全埋点,都是解决整个App前端操作的一些点击行为,例如说某些按钮、页面,每一个点击都能监测。但差异点在于可视化埋点只能看到圈定后的数据,那么全埋点则是在圈定时,历史数据也能去追溯。 但这两个埋点的弊端是散点采集,每一个点击行为都是一个事件,在数据分析时,事件的量级会较大,不易于分析,而且它只能是取这种点击行为的事件,并不能把参数带过来,你可以理解为它就是一个纯扁平化的一个事件采集。 针对需求的不同,数据采集方式应该是结合使用的,以友盟+为例,友盟+现在支持两种埋点方式,代码埋点和可视化埋点,开发者可以结合使用,去满足事件方案的采集需求。 [图片] 四、看板校验。埋点后可通过三种方式验证,一、打印日志,开启debug去打印Log,去验证触发事件log是否有上报,这种方式需要技术来配合验证。 二、集成测试,以友盟+为例,只需要让技术注册一个测试设备,就可在你这个测试设备上去启用你的App,在去触发事件,产品、运营的同学就可直接测试埋点情况。三,也可以使用市场上智能验证的工具,以友盟+为例,可先注册设备,自动去识别整个埋点的情况,且日志是实时的,可产出事件的验证报告。 五、智能验证,可以帮您智能验证这些事件的点是否采集了,是否有遗漏,最后会定期给出体检报告,详细的明细都会有。在友盟+的智能采集页面就可以智能验证埋点,只需要注册一个测试设备,这个测试设备填加完之后会实时把客户这些埋点的数据进行验证,到底是成功还是异常,以及测试的时间是什么都会有详细的数据。 综上所述:一个公司的埋点要可见、可控、可管,如果一家公司不清楚自己的埋点结构,便是在错误的数据上长期持续经营业务,越走越错。合理的埋点方案,可以使埋点能够智能调试和验证,大幅降低埋点采集的成本,从而最终达成数据质量的根本性提升。
2020-08-14 - 如何使用云开发实现发送邮件功能
新手:因为是刚接触云开发,所以有说的不对的地方,大佬帮忙指正。 背景:摆脱每周五晚写周报的烦恼。 目标:本次小目标就先实现小程序云函数发送邮件功能。 终极目标,写一个todolist小程序,每周五汇总本周工作,下周工作,使用云函数定时器触发,定时发送邮件。 [图片] 首先给大家介绍一个发邮件的第三方模块,nodemailer Nodemailer Github地址 Nodemailer官方文档 找到官方文档最下面,有一串示例代码。这次我们要用到的就是它了。 使用nodemailer我们需要使用到的传输方式:SMTP 文档如下:https://nodemailer.com/smtp/ 这里有介绍如何使用,示例代码我就不给大家复制过来了。 何为SMTP? 这里给大家百度了一发: SMTP是一种提供可靠且有效的电子邮件传输的协议。SMTP是建立在FTP文件传输服务上的一种邮件服务,主要用于系统之间的邮件信息传递,并提供有关来信的通知。SMTP独立于特定的传输子系统,且只需要可靠有序的数据流信道支持,SMTP的重要特性之一是其能跨越网络传输邮件,即“SMTP邮件中继”。使用SMTP,可实现相同网络处理进程之间的邮件传输,也可通过中继器或网关实现某处理进程与其他网络之间的邮件传输。 [图片] 怎么开启SMTP服务? 自己搭建邮件服务器是非常麻烦的,我们可以借助于QQ邮箱、Gmail、163个人邮件系统或企业邮件系统开启SMTP服务,SMTP也就是简单邮件传输协议,通过它可以控制邮件的中转方式,帮助计算机在发送或中转信件时找到下一个目的地,也就是发送邮件。 不同的邮件系统有着不同的smtp发送邮件服务器,端口号也会有所不同。 我这边以QQ邮箱为示例操作下。 在QQ邮箱的设置>账户 [图片] [图片] 我们可以看到IMAP/SMTP的开启和关闭,这里我们先开启,然后你会得到一串授权码,保存下这个授权码,我们后续会用到。QQ邮箱的发送邮件服务器:smtp.qq.com,使用SSL,端口号465或587。 [图片] 使用云函数发送邮件 首先我们创建一个云函数,比如就叫sendMail 吧。在该云函数的package.json里添加如下代码。右键点击sendMail云函数,在终端中打开,或者本地终端cd到该云函数文件夹内也可。输入npm install 安装nodemailer最新版依赖。 [代码] "dependencies": { "wx-server-sdk": "~2.1.2", "nodemailer": "latest" } [代码] 然后在index.js中添加如下代码: [代码]const cloud = require('wx-server-sdk') cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV, }) exports.main = async (event) => { const nodemailer = require("nodemailer"); let transporter = nodemailer.createTransport({ host: "smtp.qq.com", //SMTP服务器地址 port: 465, //端口号,通常为465,587,25,不同的邮件客户端端口号可能不一样 secure: true, //如果端口是465,就为true;如果是587、25,就填false auth: { user: "8662054@qq.com", //这是我的邮箱账号,改为你们的即可。 pass: "myukmlybjotjbghh" //这里是我们上面说要用到的授权码,不是QQ邮箱的密码 } }); let postMsg = { from: event.from, //发件邮箱 to:event.to, //收件人 subject: event.subject, text: event.text, html: event.html // text 和 html只能同时存在一个。 }; let res = await transporter.sendMail(postMsg); return res; } [代码] 右键部署上传云函数。 到这里我们的发送邮件云函数就完成啦。 [图片] 如何调用发送邮件云函数? 调用方式也很简单: [代码]<input type="text" placeholder="请输入收件人邮件地址" bindinput="handleToAddress"/> <input type="text" placeholder="请输入邮件主题" bindinput="handleSubject"/> <textarea placeholder="请输入邮件内容" auto-height bindinput="handleTextarea" /> <button bindtap="handleClick">发送邮件</button> [代码] [图片] 这里因为我们绑定了 发件人是我的固定邮箱,所以没有增加发送人的输入框。 textarea 我有尝试使用editor组件生成富文本进行操作,最后发现弄出来样式太龊,就干掉了。 [代码]对了差点忘了: 邮件是支持: html:富文本 cc: 支持 抄送 bcc: 支持 密送 attachments: 支持多种附件形式,可以是String, Buffer或Stream 目前我这边用不到,就不展示了,有需要的可查看官方文档,或者评论给你示例代码。 [代码] 至于我们调用的地方: 首先拿到输入的值,然后调用云函数发送。 [代码]Page({ data: { }, handleToAddress(e) { this.setData({ toAddress: e.detail.value }) }, handleSubject(e) { this.setData({ toSubject: e.detail.value }) }, handleTextarea(e) { this.setData({ toTextArea: e.detail.value }) }, handleClick() { wx.showLoading({ title: '发送中' }) const {toAddress, toSubject, toTextArea} = this.data wx.cloud.callFunction({ name: 'sendMail', data: { from: '8662054@qq.com', to: toAddress, subject: toSubject, text: toTextArea // html: '<p><b>你好:</b><img src=""></p>' +'<p>欢迎欢迎<br/></p>' }, success: res => { wx.hideLoading() console.log(res) wx.showToast({ title: '发送成功' }) }, fail: err =>{ wx.hideLoading() console.log(err) } }) } }) [代码] 实现效果图 [图片] [图片] [图片] 以上就完成了使用云开发实现发送邮件功能。 有不懂的欢迎评论留言。 老规矩结尾的代码片段 没了 😂 。 代码仓库地址:https://github.com/minchangyong/wx-cloud-demo 最后感谢李东bbsky 大佬指导。
2020-07-09 - 微信小程序发送邮件,小程序云开发使用云函数发送邮件
上一节给大家讲了借助小程序云开发的云函数管理mysql数据库,这一节,就来给大家讲一讲使用云开发云函数实现邮件发送的功能。 老规矩,先看效果图 [图片] 通过上面的日志,可以看出我们是158的邮箱给250的邮箱发送邮件,下面是成功接收到的邮件。 [图片] 准备工作 1,qq邮箱一个 2,开通你的qq邮箱的授权码(会具体讲解) 3,注册自己的小程序(因为只有注册的小程序才能使用云开发) 4,电脑要安装node(会用到npm命令行) 5,跟着老师编写小程序代码 一,准备一个qq邮箱,并启动SMTP服务 这个我不做具体讲解了。你进入你的qq邮箱以后, 1,点击设置,然后点击账户 [图片] 2,开启POP3/SMTP服务,获取授权码。 [图片] 具体操作可以看官方文档,官方文档有具体的讲解,这里我就不多说了。 官方文档:https://service.mail.qq.com/cgi-bin/help?subtype=1&&no=1001256&&id=28 我们获取的授权码如下图。这个授权码,我们后面发送邮件时会用到。 [图片] 二,注册小程序获取appid,创建一个小程序。 关于小程序的注册,和创建小程序我就不在做具体讲解,感兴趣的同学或者还不会的同学可以翻看我前面的文章学习,也可以看我的零基础入门小程序的视频:https://edu.csdn.net/course/detail/9531 下图是我们创建好的小程序。 [图片] 代码很简单,就只有一个页面,页面上就一个按钮,我们点击这个按钮的时候实现邮件的发送。 三,初始化云开发,创建发送邮件的云函数。 关于云开发初始化我这里也不在做具体讲解了,感兴趣或者不会的同学,可以去看我录制的云开发入门视频:https://edu.csdn.net/course/detail/9604 初始化云开发环境时,有下面几点注意事项给大家说下。 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云函数。 [图片] 八,点击发送邮件,查看效果。 可以看到我们的控制台,打印里发送成功的日志信息 [图片] 然后到我们的邮箱里,可以看到新收到的邮件。 [图片] 到这里我们就完整的实现了微信小程序云开发使用云函数发送邮件的功能了。是不是很简单呢。 源码我也已经给大家准备好了。大家先试着自己敲下,看能不能实现,如果实现不了再来找我要源码。 有任何关于小程序相关的问题,也可以加我微信 2501902696(备注小程序)
2019-08-06 - 小商店,商品列表应该怎么实现?通过后端接口吗?
说明: 1、使用了小程序商店,接入了插件; 2、展示商品详情、购物袋、订单、订单详情; 问题: 商品详情的入口应该是商品列表,前端并没有直接可以 使用的能力。 是通过后端获取商品列表后返回前端吗? 亲测可用: 店铺首页:plugin-private://wx34345ae5855f892d/pages/home/home 店铺首页的商品列表:plugin-private://wx34345ae5855f892d/pages/homeContent/homeContent 商品类目列表:plugin-private://wx34345ae5855f892d/pages/category/category 单个类目下的商品列表:plugin-private://wx34345ae5855f892d/pages/categoryProductList/categoryProductList?productId=spuid&categoryName=名称 使用方式: 1、组件引用 { "navigationBarTitleText": "我的", "usingComponents": { "wx-mini-category": "plugin-private://wx34345ae5855f892d/pages/category/category", } } 2、直接跳转页面: wx.navigateTo({ url: 'plugin-private://wx34345ae5855f892d/pages/categoryProductList/categoryProductList?productId=id1,id2,id3&categoryName=分类中文名', });
2023-04-21 - 首测微信小商店开放组件
目前微信小店开放组件已经申请成功,且第一时间去体验了一把。 想介入 微信小店开放组件的开发者可以点击下方链接提交申请 https://developers.weixin.qq.com/doc/ministore/minishopopencomponent/Introduction.html 官方在审核完成后会推送申请成功的模板消息,且拉入官方组件问题反馈群 你的微信小程序后台也会增加小商店店开放组件 [图片] 点击去管理会打开对应小程序的小商店后台,此后台是对应你小程序申请的插件版小店后台 与 单独申请的小店后台不互通,需要单独提交资质审核签约 官方提供了几个组件开发者可通过路由跳转进入对应的组件页面 例如下方商品详情 const productId = [商品id] // 填写具体的商品Id wx.navigateTo({ url: plugin-private://wx34345ae5855f892d/pages/productDetail/productDetail?productId=${productId}, }); 文档的接入方式我不多赘述,可自行看文档,这里说一下文档没得 鄙人使用的是uni-app框架开发小程序所以说一下uniapp介入方式 找到manifest.json文件源码视图找到微信小程序配置 "mp-weixin": { /* 小程序特有相关 */ "appid": "wx2afea6afe2d23263", "setting": { "urlCheck": false, "es6": true, "postcss": true, "minified": true }, "permission": { "scope.userLocation": { "desc": "你的位置信息将用于定位您是否位于图书馆范围内" } }, "requiredBackgroundModes": [ "audio" ], "usingComponents": true, "plugins": { "mini-shop-plugin": { "version": "1.0.63", // 必须是小程序购物组件最新版本号,微信开发者工具调试时可获取最新版本号(复制时请去掉注释) "provider": "wx34345ae5855f892d" // 必须填小程序购物组件appid,不要修改(复制时请去掉注释) } } }, 官方文档里提到的组件版本是1.1.0,介入后控制台报错提示找不到1.1.0,最终找到小程序插件信息最新版本才更新到1.0.63,不得不说这文档有点坑 附上插件的信息链接 https://mp.weixin.qq.com/wxopen/pluginbasicprofile?action=intro&appid=wx34345ae5855f892d&token=1836153220&lang=zh_CN 此时已经可以在小程序内使用插件了 去尝试一下 先在后台提交上架商品拿到SpuId [图片] /** * 商品详情 * @Author: wkiwi * @function: productDetail */ productDetail(productId){ uni.navigateTo({ url:`plugin-private://wx34345ae5855f892d/pages/productDetail/productDetail?productId=${productId}` }) }, 调用方法进入商品详情 [图片] 体验完美,可以说几分钟时间就集成了一个官方商城出来。 但是别高兴的太早,总结了本次介入的问题 1.文档问题,还在内测阶段可能不完善 存在版本问题 以及跳转说明问题 下方官方说默认不传tabId会进入全部分类 [图片] 可是并不如此,会toast提示tabId必须为 all/pendingPay/pendingRecevied/afterSale 中的一项 2.产品层面问题 在小程序内介入小店,大多应该就是充当官方商城的吧,但是商品列表组件竟然未提供,这是让开发者徒手再撸一个商品列表首页吗???? 目前用户想进入到商品列表必须通过商品详情左下方的店铺按钮才可以进入商品列表,造成入口较深,体验不佳 此时点击 店铺按钮 又造成另外一个问题,跳转进入商品列表也就是微信小商店的首页,此时头部没有返回按钮,点击手机的返回按钮会直接退出小程序 [图片] 猜测 店铺首页为小商店的tab页面,导致无法返回 此问题导致小程序退出率大大增加,运营辛辛苦苦留存的用户这么轻而易举让用户退出了?????? 此时小程序想浏览小程序本身的首页是必须通过清除小程序后台,重新点击进入才能回到小程序层级,否则你只能在插件版本的小商店内跳转!!! 本次体验整体感觉微信小商店 给小程序一个快速集成官方商城的一个解决方案,但是在产品上还有些问题,本阶段上述产品问题未解决我是不可能接入的,希望官方尽快完善上述问题 ----------------------------------接更新---------------------------------- 详情页点击首页按钮无法返回小程序首页解决方案 const miniShopPlugin = requirePlugin('mini-shop-plugin') miniShopPlugin.initHomePath('/pages/index/index') // /pages/index/index为自己小程序首页路径 进入小商店组件首页路径 wx.navigateTo({ url: `plugin-private://wx34345ae5855f892d/pages/home/home`, });
2020-10-30 - 使用‘小程序购物组件’进入home页面后无法返回?
在小程序使用小程序购物组件’。 在小程序tabBar其中的一栏放置商店icon;用户点击该tab的商店icon,在事件onTabItemTap()里直接跳转到商店首页: wx.navigateTo({url: 'plugin-private://wx34345ae5855f892d/pages/home/home',}) 进入商店首页后,商店首页左上角出现小程序的图标和名称,但是无法返回啦,只能老老实实呆在商店。 请问,是否能够自定义左上角返回到小程序哪一个页面? 请问,是否能够自定义左上角返回到小程序哪一个页面? 请问,是否能够自定义左上角返回到小程序哪一个页面?
2020-11-13 - 微信小商店·商家成长学习资料
内含开店指引、店铺运营和平台规则,帮你快速掌握小商店经营秘诀。
09-05 - 跳转小商店出现界面空白问题?
无论代码直接跳转到小商店, wx.navigateTo({url: 'plugin-private://wx34345ae5855f892d/pages/home/home'}); 或者分享商品详情页后打开 也都是出现界面空白问题 测试了5个手机,只有1个手机可以正常显示,其他都是空白 appId 是 wx98faa8383991cb96 请帮忙看下是什么问题导致的?
2023-10-10 - 小商店分享页面无法跳回小程序主页问题解决
上次在论坛碰到一大神,提供了一个解决思路,做为菜鸟,各种尝试,今天终于解决,现在提交代码奉上,感谢各位大神提供的帮助。 在app.js中增加以下代码。 //app.js const miniShopPlugin = requirePlugin('mini-shop-plugin'); 在onLaunch函数中增加跳转主页菜单 onLaunch: function () { miniShopPlugin.initApp(this, wx); miniShopPlugin.initHomePath('plugin-private://wx34345ae5855f892d/pages/home/home'); }
2021-03-08 - 微信红包封面如何过审,整理下我踩过的坑,未通过审核的各种原因及应对方法。
此贴仅纪念下近一个月申请红包封面的踩坑之旅。。。 言归正传,如下图所示,经过99八十一次的驳回之后,踩过了各种审核的坑之后,终于通过了两款红包封面,过程是艰辛的 结果是甜甜的,哈哈~ [图片] 一次审核需要3到4个工作日,中间被驳回3次,半个月时间就没了。。。想准点上个活动的我,失眠了好几天 为减少大家踩坑,先分享下我踩过的坑~~ 1.语文能力好点的人(我不是),一般都不会犯。这是对活动规则的基础理解,不过很多人都会犯,封面的名称不能随便取,只能是你公众号(视频号)的名字或是公司主体名称。 [图片] 2.这个坑,是最容易掉进去的,但是你知道的话 完全可以避免。 首先,微信系统会自动给上传的封面加上“恭喜发财,大吉大利 ”的系统字样。系统内容是固定不变的,所有要求封面的内容不能跟系统区域有重叠,如果不能完全避免也需要设置不同的背景颜色,以突出系统内容。不然会被毙掉。 其次,就是对于品牌方来讲,多数人都希望能加上自己的公司的产品或是服务。记住,可以加!但是要去掉广告词,宣传语。什么买一送二,年末送礼这样的词就别想了。最多是加一个“产品图”,是产品图,不是商品图。这个还是有区别的。 [图片] 3.最难解的天坑~~提示你:提交作品登记证书或是能证明是你作品的材料 [图片] 首先对于有自行创作的人来说,你提交原创作品+psd源文件,基本上没问题 对于没有创作能力,但是有ps技能的人,你从素材网站下载文件,然后进行“二次创造”,+二次创造后的psd 文件,是可以通过的。 但这招不是百分百OK的。 对于没有自行创作能力和不懂ps的人,就别多想了。 不是别想了,是别想多了!。有个更生猛的方法,比前两种审核通过的更快!更高! 这里需要借助万能的【t ,b】,微信社区不便多说,,应该是懂的哈~ 4,还要很多很多坑,篇幅问题就不一一阐述了,做了份详细的避坑文档,寥解我近一个月被拒的失落,需要的朋友可取~ 交流微信:dashenu [图片] 2月5日更新~~ 自从做了红包封面的,我对人生的感悟又加深了些理解。人生不就是申请红包封面的过程嘛, 充满希望的申请~无情的被驳回~修改完再次充满希望~再次被拒~给自己打完气再次申请。。。 好了,言归正传~ 上次发完帖子,有些朋友加了我微信,了解到大家遇到的种种问题,按照我的方法去改后多数都是可以通过的。 但是,按照老方法年前很难通过了,时间来不及!很多人都是想年前做活动用,过了新年红包封面的热潮势必会下降。 [图片][图片] 本来以为没办法了,但是昨天从我一个朋友那里又得到了个新消息,不用花5天时间办理作品登记证,直接用授权的素材图 就直接通过了!为此,我找了一圈能够授权的使用微信红包封面的素材网站。模式都是单张图片授权,一张图片要680元!还有收费800多的, 这些网站的一年会员 也就1000多点,一张图片就要大几百。这个价格太高了,害,可曾考虑过我们贫苦企业的感受。素材商这波吃的利润也未免太多了。 [图片] 有钱的企业直接上图虫网,680一张,素材多。 我这种没钱,就算了吧。算了吧 ,算了吧,怎么可能算了!害老子搞了一个多月时间,怎么能放弃 终于让我发现了,一家素材可以授权使用微信红包封面,而且价格低。最重要的是节省了时间,有希望年前搞定红包封面 这两天是年前是最后的机会了, [图片] [图片] 不码字了,交流微信:dashenu 有些经验分享可以让你少走弯路 [图片]
2021-02-05 - 微信红包封面定制个人学习总结
一、创建账号目前有两条注册路线,分别是个人和企业。 个人:需先开通微信视频号并获得有效粉丝数100个,然后申请封面定制平台账号,用视频号管理员验证完成注册。 *有效粉丝数,个人猜测应该是系统按特定规则计算,会排除刷粉等异常数据,规则不会对外公开。 [图片] 企业:需注册公众号,并进行微信认证,然后申请封面定制平台账号,用公众号管理员验证完成注册。 [图片] *目前仅面向大陆境内的认证企业公众号,或已完成视频号认证的个人用户开放。 *且暂不对宗教、烟草、医疗、特殊医学用途配方食品、医疗器械、农药、兽药、保健食品及药品相关的主体开放。 二、封面定制个人定制:定制页面如下, [图片] [图片] 1,红包封面简称最多8个字,可以使用视频号名称,或自行命名。注意起名也需要提供相关证明材料。 2,个人LOGO支持PNG、JPG,尺寸是200*200像素,文件小于100KB。 虽然可以直接使用视频号头像,但如果你视频号头像图片是网图,也会管你索要版权证明的。 建议不使用LOGO,直接文字命名。 3,样式(即封面图片)封面图片直接使用一张图片即可,红包各个阶段的页面,都是从这一张图片中截取。 支持PNG、JPG,尺寸是957*1278像素,文件小于500KB。 注意第1张示例图底部的“开”字部分,会遮挡图片下面一部分内容。 第2张示例图,实际效果是可以下拉的,需要考虑下拉后的顶部显示内容,如果不合适还可以单独调整封面图上传。 第3张示例图、第4张示例图,可以直接编辑选择显示位置。 4,封面故事在红包打开后的红包详情页展示,该页下拉时,直接以图片或视频方式展示封面故事。 图片和视频,最多可设置5个,左右滑动观看效果。 图片支持PNG、JPG,尺寸是750*1250像素,文件小于300K。 视频支持MP4格式,编码是H.264/AVC,宽度≥720像素,宽高比是3:5-16:9之间,小于15秒时长,码率不高于1600kbit/s,文件小于10M。 同时支持用视频号上传素材。 故事的文字描述不得超过40个汉字。 个人号,支持跳转到视频号或表情封面; 暂时个人号没有跳转公众号或小程序的链接。 5,证明材料整个设计中,出现的名称、LOGO、图片等美术作品,以及涉及人像、字体等,都需要提供相关权属证明文件,以证明你有资格使用这些内容。 *涉及注册商标的,需提供《商标注册证》的扫描件或商标使用授权书(在授权情况下); *美术作品涉及著作权的,需提供《作品登记证书》或《著作权登记证书》的扫描件;没有证书的,需提供该作品的psd格式文件,或人民法院确认权属的法律文书,或其他能证明作品权利人的发表链接等; *涉及肖像权的,需提供图中人物的身份证明,如身份证正反面或护照等扫描件或照片;或提供肖像权授权书。其中授权人为图中涉及肖像的人,被授权人为微信红包封面开放平台注册者; *涉及版权的,需提供作品版权证明,如著作权登记证、作品登记证;或版权授权书,其中授权人为版权所有者,被授权人是微信红包封面开放平台注册者; 以及版权所有者主体证明,企业请提交合法营业执照电子版扫描件或照片,个人请提交身份证正反面或护照等身份证明扫描件或照片; 没有上述证书,需提供该作品的psd格式文件,或人民法院确认权属的法律文书,或其他能证明作品权利人的发表链接等; 如果涉及资料文件较多,可打包上传。文件需小于25M(实际定制页面目前写的是小于80M); 如果证明材料过大,可以写邮件发往wxcover_support@tencent.com(邮件名为【证明材料补充】+封面名称),并在提交审核时在「证明材料」处上传说明文档,列明发至邮箱的证明材料所包括的内容。 6,手机预览填完资料的封面,可以点击底部的“手机预览”按钮,手机扫描弹出的二维码,在手机上预览红包封面效果。 企业定制:和个人封面定制大体流程一致,只是在封面故事部分增加了小程序或公众号的跳转。 [图片] *可以关联企业主体下的小程序或公众号,其中小程序可以设置指定界面路径跳转。 三、封面审核1,审核周期原审核周期是1个工作日,后改为从1月2日起,至2021年2月26日,审核周期调整为3个工作日。 并且对特定情形的封面定制,会延长审核周期为1个月。 特定情形:(1)封面中存在外文、少数民族语言文字内容的,需要提供完整、准确的中文翻译。 (2)封面中存在任何宗教、民族、政治性质的图腾、人物、神兽、符号、法器等元素的,需要提供该等元素的详细说明。 2,审核标准肯定以官方实际审核为准。 从官方公开的审核标准中,个人归纳如下: 综合标准:(1)不违法;(2)符合未成年人保护标准;(3)不违背社会善良风俗或各民族感情;(4)格调健康,积极向上;(5)不得过度营销;(6)不能直接使用中国地图(除非相关部门授权);(7)除党政和事业机关账号,其他不可使用政治军事以及其他主旋律推广内容;(8)不能使用全网封杀人物肖像 直接标准:(1)必须确保有权使用;(2)在先原则(不可与已发布封面雷同); 3,提审数量最多可同时在审3款红包封面,待审核完成后可继续提交。 四、封面购买TODO 五、封面发放TODO 六、封面违规与侵权处理从官方原始购买后,定制方不得以任何形式向用户售卖微信红包封面。 TODO 七、相关参考资料*微信红包封面开放平台-帮助中心 https://cover.weixin.qq.com/cgi-bin/mmcover-bin/readtemplate?t=page/index.html#/doc?page=introduce&index=-1 *封面审核周期调整公告 https://cover.weixin.qq.com/cgi-bin/mmcover-bin/readtemplate?t=page/index#/notice_detail?id=1609588007_3773_1102306322 ====================================== 附:常见审核驳回原因整理1,所提交的封面素材和他人已发布的作品存在较高相似度,侵权风险较大。请提供早于他人作品发布时间的作品版权证明。 2,红包封面的图案应尽量避开头像、昵称、祝福语的区域。若无法避开,需避免图案过于复杂,影响文字识别。 3,需补充提供【XXXX公司/网站】享有著作权的证明材料。(即使你有其他平台的版权授权书也不行,需要他们著作权证明) 4,所提供的《XX图片授权书》中被授权方为【张三】,无法体现被授权方与【张三视频号】视频号之间的关系。请提供授权范围包含【张三视频号】视频号之红包封面定制场景的授权书后,再上传系统进行审核。(授权书需要有身份证号或其他证明,能让官方确认是授权给你,只有名字不行) 5,所提交的封面素材涉及版权,需提供《作品登记证书》或《著作权登记证书》的扫描件、作品源文件等版权证明材料。 6,PSD文件需要详细分层。 7,红包封面简称仅可以使用主体名称中的字号、公众号名称或注册商标名称。如使用注册商标请上传《商标注册证》的扫描件。可使用【XXX】等命名。 8,所提交的封面素材涉及他人的作品,需提供以下材料:1)《作品登记证书》或《著作权登记证书》的扫描件、作品PSD源文件等版权证明材料; 2)版权授权书(企业需盖章);3)版权所有者是个人的,需提供身份证正反面或护照等扫描件。 9,不可出现除企业字号、商标名称、企业价值观、祝福语以外的文字。 10,红包封面的背景色不可与微信红包的文字色相接近,影响昵称、祝福语的识别。需更换背景色后再提交。 11,所提交的企业logo涉及他人的作品,需提供以下材料:1)《作品登记证书》或《著作权登记证书》的扫描件、作品PSD源文件等版权证明材料; 2)版权授权书(企业需盖章);3)版权所有者是个人的,需提供身份证正反面或护照等扫描件。 12,仅可使用定制主体法人代表的肖像定制封面,需提供企业营业执照、法人代表实名信息(需本人手持身份证拍照),且该等情形的微信红包封面,审核期限将延长至一个月。 13,封面素材不可展示微信红包的固有元素,如祝福语、“开”按钮、用户昵称头像、弧形阴影等,需删除后再提交。 14,所提交的作品创作源文件无法充分证明你享有该作品的著作权,请补充其他证明材料,如作品的《作品登记证书》或《著作权登记证书》的扫描件等。 15,不可出现和他人已发表的作品雷同,或权利归属情况不明的内容(如未获得著作人合法授权的二次创作、同人作品等)。 16,发红包页、红包消息气泡、拆红包页、红包详情页的素材图需属于原始封面样式图的一部分,保持内容、风格、主题一致。 17,品牌logo仅可以使用你的注册商标,且需上传《商标注册证》的扫描件。如使用其他主体的注册商标,需提供有效的授权证明材料。若未注册商标或未取得授权,可删除品牌logo后再提交。 18,证明材料未上传成功,请重新提交。若文件过大无法上传,请将证明材料发邮件至wxcover_support@tencent.com(邮件名为【证明材料补充】+封面名称),可在邮件中留下你的联系方式,我们将与你联系。 19,不可出现真实的人名和地址信息。 20,仅可使用定制主体本人的肖像定制封面,请提供本人实名信息(需本人手持身份证拍照),且该等情形的微信红包封面,审核期限将延长至一个月。 21,建议调整封面中祝福语文案的位置,以免影响在其他机型或者大字体情况下的体验效果。 22,红包封面简称可使用微信视频号账号名称。如果使用其他名称命名,请提供相应的证明材料。 23,请提供有效的版权证明材料。应注意,根据《“微信红包封面”定制功能使用条款》第3.3.3条的约定:定制方不得以任何形式向用户售卖微信红包封面。 24,非党政机关事业单位,不可使用天安门、人民大会堂、华表等国家民族标志物。 25,所提交的《作品登记书》证明材料,需将登记的作品复印件一起上传。 26,所提交的封面故事视频音乐作品和他人已发布的作品存在较高相似度,侵权风险较大。请提供早于他人作品发布时间的作品版权证明。 27,不可包含直接或间接表明产品或服务或其特性的文字。(包括封面故事图片) 28,所提交的封面素材涉及他人的作品,需提供版权授权书,其中被授权人为微信红包封面开放平台注册者。 29,不可出现商品图、店铺图、服务内容截图等广告性质的内容。 30,需提供有拍摄信息的照片源文件。 (不断更新中...欢迎提供!欢迎点赞支持!) ====================================== 重要事项更新日志: *2021.01.20 更新封面故事跳转内容,增加了视频号和表情封面跳转。 *2021.03.23 移除了个人主体必须视频号认证要求。
2021-03-23 - URL Scheme 和 URL Link 优化公告
为了帮助开发者更好地为用户提供服务,降低开发者使用 URL Scheme 和 URL Link 的成本,自 2023 年 12 月 19 日起,微信团队将对 URL Scheme 和 URL Link 进行如下优化: 1、新增明文 URL Scheme,开发者无需调用接口可自行拼接并且生成明文 Scheme; 2、取消 URL Scheme 和 URL Link 打开端一人一链的限制,支持同一条链接被多名用户访问; 3、新增打开端限制:每个小程序每天 URL Scheme 和 URL Link 总打开次数上限为 300 万次。 一、新增明文 URL Scheme开发者无需调用平台接口,可自行根据如下格式拼接 appid 和 path 等参数,作为 URL Scheme 链接。 weixin://dl/business/?appid=*APPID*&path=*PATH*&query=*QUERY*&env_version=*ENV_VERSION* 其中各参数含义如下: [图片] 注意: 1、为保护开发者,通过明文 URL Scheme 拉起的小程序(页面)必须要提前在「小程序管理后台 -> 设置 -> 隐私与安全 -> 明文 scheme 拉起此小程序」中进行声明; 小程序:配置能够通过明文 scheme 进入的小程序页面[图片] 小游戏:打开开关即可通过明文 scheme 拉起小游戏[图片] 2、通过明文 URL Scheme 打开小程序的场景值为 1286; 3、明文 URL Scheme 不受每天 50 万次的生成量限制; 4、明文 URL Scheme 没有有效期的概念,可长期有效; 5、明文 URL Scheme 没有一人一链的打开限制,支持一条链接同时被多名用户访问。 二、原 URL Scheme 升级为加密 URL Scheme,并支持自行拼接参数目前已对外提供的 URL Scheme 能力平滑升级为加密 URL Scheme,取消一人一链的限制,支持开发者自行在链接后拼接参数*CUSTOM PARAMETER*。 注意:之前通过平台接口生成的 URL Scheme 可继续使用,链接自动可支持多人打开。 URL Scheme格式 weixin://dl/business/?t=*TICKET*&cq=*CUSTOM PARAMETER* 其中参数含义如下: [图片] 注意:加密 URL Scheme 打开小程序的场景值保持不变,仍为 1065。 三、原 URL Link 升级为加密 URL Link,并支持自行拼接参数目前已对外提供的 URL Link 能力平滑升级为加密 URL Link,取消一人一链的限制,支持开发者自行在链接后拼接参数*CUSTOM PARAMETER*。 注意:之前通过平台接口生成的 URL Link 可继续使用,链接自动可支持多人打开。 URL Link格式: https://wxaurl.cn/*TICKET*?cq=*CUSTOM PARAMETER* 其中参数含义如下: [图片] 注意:加密 URL Link 打开小程序的场景值保持不变,微信外打开的场景值为 1194;微信内打开会调整为开放标签打开小程序,场景值为 1167。 四、调用规则调整1、加密 URL Scheme 和 URL Link 取消一人一链,支持一条链接同时被多名用户访问,生效后之前生成的链接被多名用户访问时,不会再报错; 2、每个小程序每天能够生成加密 URL Scheme 和 URL Link 共计 50 万条的限制不变,额外增加每个小程序每天在微信外,能够通过链接打开小程序共计 300 万次的打开量限制,其中链接包括加密 URL Scheme、加密 URL Link 和明文 URL Scheme ;若链接打开小程序的次数超过 300 万次/天,则无法通过链接在微信外拉起小程序; 3、URL Scheme (加密和明文)和 URL Link (加密)仅支持非个人主体小程序使用; 4、注意事项:平台有安全策略防止开发者的链接被黑灰产大量打开,可能导致达到访问上限无法正常通过链接打开小程序的问题; 5、查询方式:开发者可复用现有的查询方式对 URL Scheme 和 URL Link 进行打开额度查询和链接状态查询。 [图片]
2023-12-19 - 官方大大,政务民生类小程序想申请长期订阅消息模板
【小程序appid】wx1bc525f7ed419db3 【小程序主体】泉州市生态环境局政务管理 【申请模板类目】 政务民生 >党/团/组织 【申请模板名称】会议提醒、值班提醒、维修提醒 【使用场景】 场景一: 定于5月26日星期五8:40在D720会议室召开局党组理论学习中心组(扩大)学习会,请局处级干部准时参加,邀请驻局纪检监察组参加。 议程如下: 1.学习习近平在学习贯彻习近平新时代中国特色社会主义思想主题教育工作会议上的讲话精神 2.学习中共中央关于在全党深入开展学习贯彻习近平新时代中国特色社会主义思想主题教育的意见 3.学习《人民日报》评论员文章:把理论学习、调查研究、推动发展、检视整改贯通起来 4.学习中央纪委国家监委公开通报青海省6名党员领导干部严重违反中央八项规定精神问题 5.学习党员干部、公职人员酒驾醉驾典型案例的通报(秘密件) 6.学习省委2022年全省泄密案件情况通报(秘密件) 7.学习市委2023年保密工作要点(秘密件) 其中,学习内容1-3由郭建华副局长领学,学习内容4-5由驻局纪检监察组张威副组长领学,学习内容6-7由郭建华副局长领学。 会议开始时间前的前1天晚上6点半(上午的会议或者活动)或上午9点半(下午的会议或者活动),微信小程序推送会议提醒。第一议题开始后,提醒二三…议题参会人员(不重复提醒已在会议室的参会人员),第二议题开始后,提醒三四…议题参会人员 场景二: 值班人员要做好24小时待机和其他值班准备,需要提前一天提醒相关值班人员和带班领导。 值班前一天的晚上6点半,微信小程序向带班领导、值班人员推送值班提醒。值班人员调班申请后,需发送申请通知给被换班人,被换班人同意后,发送审核通知给审核人,审核人通过后发送通知给带班领导,调班人,被调班人,另一值班人员。带班领导调班后,需要提醒局长,由办公室人员吴高焰修改代办领导调班情况 场景三: 办公室或其他科室发现有需要报修的固定资产,可在小程序中上报,小程序通知提醒维修人员处理 【模板字段】: 会议提醒 :主题、时间、地点、参会领导、提示说明 值班提醒:值班类型、值班日期、带班领导、值班人员、提示说明 维修提醒:申请人、申请科室、申请时间、维修固件、维修备注 【消息示例】: 会议提醒: 主题:局党组理论学习中心组(扩大)学习会 时间:2023-05-12 08:00:00 地点:D720会议室 参会领导:郭建华,张威 提示说明:请与会人准时参会 值班提醒: 值班类型:日程值班 值班日期:2023-05-13 带班领导:李国全 值班人员:张果、吴桂枝 提示说明:值班当日,请保持通讯畅通 维修提醒 : 申请人:谢国贤 申请科室:机关党委 申请时间:2023-05-12 08:00:00 维修固件:打印机 维修备注:通电不运行
2023-07-17 - 【社交-笔记、社交-社区/论坛、社交-问答】类目修改指引说明
一、社交类服务,你需要了解: 1、审核流程: [图片] 2、内容安全审核机制: 小程序社交内容发布功能在进行内容安全验证时,若存在信息安全风险,需要尽快完善内容机制:①确保已接入内容安全API并要求所调用API可在小程序内任意发布的场景生效;②小程序内检测结果安全说明仅需提示用户所发布内容含违规信息即可;接口调用可参考:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/sec-check/security.msgSecCheck.html 二、【社交-笔记】、【社交-社区/论坛】和【社交-问答】案例解析: 1、【社交-笔记】:小程序服务内容涉及提供用户自行生成内容(文字、图片、音/视频)的记录、分享 整改建议(2选1): ①补充选择:【社交-笔记】类目 注意事项:该类目补充后首次提审需进入属地主管部门二次审核流程(报备详情),时长为7天,开发者需提前规划好提审时间 ②移除社交笔记相关功能,包括但不限于移除前端、后台代码中所存在的社交功能、社交标签等 【示例】 [图片] 2、【社交-社区/论坛】:小程序服务内容涉及提供用户自行生成内容的发布/分享/交流服务,或含【社区】等tab 整改建议(2选1): ①补充选择:【社交-社区/论坛】类目 注意事项:该类目补充后首次提审需进入属地主管部门二次审核流程(报备详情),时长为7天,开发者需提前规划好提审时间 ②移除社交论坛相关功能,包括但不限于移除前端、后台代码中所存在的社交功能、社区tab等 【示例1】:小程序涉及提供用户自行生成内容的发布/分享/交流服务,需补充选择:社交-社区/论坛类目。 [图片] 【示例2】:小程序涉及建群、拉群,需补充:社交-社区/论坛类目。 [图片] 3、【社交-问答】:涉及提供问答服务 整改建议(2选1): ①补充选择:【社交-问答】类目 注意事项:该类目补充后首次提审需进入属地主管部门二次审核流程(报备详情),时长为7天,开发者需提前规划好提审时间 ②移除社交问答功能,包括但不限于移除前端、后台代码中所存在的问答功能、社交标签等 【示例】 [图片] 附:类目所需资质 [图片] 这是一份动态更新的文档,辅助开发者提前了解社交相关的业务形态所需申请的类目,避免开发者因类目不符审核失败或因不了解涉上述类目需二次审核流程时长导致无法按期发布上线,开发者如有其他疑问,可以通过目前开放的咨询渠道反馈: 1、微信开放社区-交流专区-小程序发帖咨询-提出问题-运营相关问题 2、驳回站内信通知-客服咨询入口(MP代码审核客服入口正处于灰度开放中,若未获得灰度测试入口,开发者可前往社区发帖咨询) 我们会根据新出现的问题、相关法律法规更新或产品运营的需要及时对其内容进行修改并更新,制定新的规则,保证微信用户的体验。建议开发者反复查看以便获得最新信息,定期了解更新情况
2022-03-18 - 小程序中包含招聘信息但是仅作纯信息展示,没有劳务派遣还需要提供人力资源许可证吗?
看到社区中好多说,纯信息展示不需要办理人力资源许可证,我们这个小程序仅作为信息发布和展示使用,没有任何劳务派遣行为
2022-12-25 - 【生活服务-求职/招聘】、【生活服务-求职/招聘(涉外)】类目修改指引
代码审核环节,将会对小程序运营的内容与所选类目是否相符进行核实,当小程序涉及提供求职/招聘、专业人力资源等服务,需要补充【生活服务-求职/招聘】类目合规提审,否则代码审核环节将面临因类目不符被驳回情形。 一、求职/招聘类服务,你需要了解: [图片] 注意:申请类目资质时,若当地存在不需要办理相关资质即可从事相关服务内容,建议可提供包含但不限于当地的政策/法规/主管部门等情况材料说明直接申请类目,类目侧会根据提供的材料进一步评估反馈。 二、应用场景示例与整改指引: 示例1: 【生活服务-求职/招聘】类目:适用于提供求职/招聘、专业人力资源等服务。 [图片] 示例2: 【生活服务-求职/招聘(涉外)】类目:适用于提供对外劳务合作相关求职/招聘等服务。 [图片] 整改建议(2选1): 1、类目选择: (1)若服务涉及【提供求职/招聘、专业人力资源等服务】(如示例1),需补充选择:生活服务-求职/招聘类目; (2)若服务涉及【提供对外劳务合作相关求职/招聘等服务】(如示例2),需补充选择:生活服务-求职/招聘(涉外)类目。 2、或自查代码,确保移除招聘发布、招聘信息展示、简历投递、人力资源服务等内容及相关分类标签。 本文档为【生活服务-求职/招聘】【生活服务-求职/招聘(涉外)】类目的介绍说明,如存在上述问题应及时调整、修整,避免后续存在上诉问题审核失败;若仍有其他疑惑,可以通过以下咨询入口反馈: 1、微信开放社区-交流专区-小程序发帖咨询-提出问题-运营相关问题 2、代码审核驳回站内信通知-客服咨询入口(客服咨询入口目前正在测试开放阶段,若无客服入口,建议前往开放社区发帖咨询) 我们会根据新出现的问题、相关法律法规更新或产品运营的需要及时对其内容进行修改并更新,制定新的规则,保证微信用户的体验。建议开发者反复查看以便获得最新信息,定期了解更新情况。
2022-08-01 - 小程序中包含招聘信息但是仅作纯信息展示,没有劳务派遣,为什么要添加招聘/求职的类目?
你的小程序"酒吧之家",提审时间:2023-04-24 10:49:40 看官方在社区的回复中有回答:小程序提供生活综合类的信息发布,暂未涉及在线求职/招聘服务,暂无需申请生活服务-求职/招聘类目。 [图片]
2023-04-24 - 小程序中包含招聘信息但是仅作纯信息展示,没有劳务派遣也需要提供人力资源许可证吗?
第一次提交审核结果如下: 审核失败原因 存在所选类目与运营内容不符行为,违反《微信小程序平台运营规范常见拒绝情形2.1》 详情描述 你好,你的小程序涉及提供求职招聘、专业人力资源等服务,请补充选择:生活服务-求职/招聘类目。 我们这个小程序仅作为信息发布和展示使用,如果不选择社区论坛这个类目,那我们需要选哪个类目?另外,我们同样没有任何劳务派遣行为,我们也不是劳务公司之类的,这种情况需要怎么处理?
2023-06-11 - 申请发布招聘小程序,人力资源服务许可证,有什么要求么?
[图片] 申请办理人力资源许可证服务的时候,有这个要求,如果不提供这种资料申请下来的人力资源服务许可证是否可以通过审核呢?
2021-03-03 - 现在小程序不能复用公众号认证资质了吗?
刚开通了一个小程序,发现没有了复用"微信认证资质"的选项了,所以现在小程序也要独立认证了吗? 图1是以前的 [图片] 图2是今天的 [图片]
2023-09-25 - 小程序审核:名称规则调整及优化建议
微信小程序的开发者们在发布小程序之前,需要给每个小程序起好一个名称,设置好logo、简介及类目信息,然后才能进行代码提审。 这些帐号的基础信息是用户对一个小程序的初步认知,平台希望这些信息能够给予用户准确预期每个小程序的功能和内容,也希望每个小程序的名称是具有独特性的,减少误导、混淆用户理解的可能性。 因此有以下几点名称规则调整及优化建议,希望开发者可以了解并遵循,后续可能会在名称审核、代码审核或已发布运营时,收到平台的审核通知或建议修改通知。 l 微信小程序的名称建议是品牌、商标或具有辨识度的短词 在微信小程序发布后,用户会通过搜索、传播等场景使用小程序的功能和服务。选择品牌、商标或具有辨识度的短词作为小程序的名称,可以帮助用户快速建立与小程序的记忆与关系。 名称为“印象笔记”会比“笔记”能更好的让用户记忆和理解,并使用“印象”品牌词进行搜索或传播。 [图片] l 不能直接使用功能性描述、广义归纳类的词汇作为名称 功能性描述的词汇虽然可传达出小程序所要提供的相关功能,但直接使用此类词汇,缺乏显著性且不具有识别、区分小程序的作用。 如名称为“牙科”的帐号,用户能直接理解小程序的内容可能与“牙科”相关,但对这个小程序帐号是没有建立认知和关系的。 [图片] l 不能同时使用地域性词汇与广义归纳类词汇进行命名 使用“地域+广义归纳类”词汇进行命名,同样存在指向性过于宽泛的问题。 如以下案例, 名称包含的地域词:“四川”、归纳类词:“系统门窗”,并不会让用户对帐号的功能产生有效的预期。以下示例是不允许的: [图片] 但在政务民生类服务场景,“广州地铁”、“广州公积金”可以被用户理解并接受属于政府或相关机构提供的服务和资讯,因此“地域+广义归纳类”词汇可被政府民生场景使用。 l 不建议使用具有营销属性的词汇进行命名 营销属性词汇如:免费、促销、清仓、打折等,鉴于活动规则普遍附有限制条件,在名称中使用,通常带有过于夸大的表达效果,并非是小程序的核心功能和用户的全部认知,存在误导的可能性。以下示例是不允许的: [图片] l 商品销售类小程序,需要包含品牌名称,不直接使用产品分类进行命名 商品销售类小程序,若仅使用产品分类进行命名,无法建立易于记忆、易于传播的品牌形象。如名称为“女鞋男鞋女包批发生产”,用户并不会因“女鞋”“男鞋”“女包”就会进行选择,反而“品牌+女装”才是用户真正需要的。以下示例是不允许的。 [图片] l 不在名称中堆砌热门搜索关键词 名称中堆砌多个关键词,过于冗长的热门搜索关键词堆砌名称无法建立品牌记忆,目的普遍是在搜索结果上获得更多的曝光。以下示例是不允许的: [图片] 结语 此次名称规则的调整和优化建议,平台希望开发者们能相应地调整自己的小程序名称。如未满足名称规范,平台会在后续的小程序名称设置、名称审核、代码审核流程进行规则提示和修改要求。并会在搜索场景优化需求基础上,对无辨识度的帐号名称进行搜索策略调整。 微信小程序完整的名称规则可具体参照《微信小程序平台运营规范》2. 基本信息规范,除以上规则与示例之外,当然还包括了不得使用违法违规的名称、不得使用侵权他人的品牌词进行命名、在命中敏感类目如医疗词时提交主体资质等规则。 平台希望小程序名称的优化调整,可以使得每个被开发者精心创造出来的小程序都能让用户在使用时、搜索时、传播时逐渐接受并建立对产品品牌的认知。
2019-05-14 - 分享一些小程序名称查询的技巧
为什么需要查词? 我们都知道微信平台对小程序名称审核很严格,所以小程序起名有时候也是个头疼的问题,有时候想了好几个名称,到了注册名称环节,发现没有一个能注册成功的,要么已经被人注册了,要么命名不符合规范,要么需要很多资质证明,所以注册小程序之前需要先查词确认 具体操作步骤如下: 1.注册一个小程序(注册地址:https://mp.weixin.qq.com/cgi-bin/loginpage),完成第一步认证后,不能填写小程序名称。(如图所示) 图上的就是填写“小程序名称”的,这个账号就作为“小程序查词”账号,每次客户要查词时,就登录这个账号,把客户想好的小程序名称输入进去。 [图片] 2. 当你填写的小程序名称检测后提示如图信息“你的名字可以使用”,说明你的名称还没有被注册,你可以注册使用。 [图片] 3. 当你填写的小程序名称检测后提示如图信息,说明你的名称已被注册小程序或被注册了公众号,若这个名称是你的商标,那么你可以点击“侵权投诉”否则你不能注册。 [图片] 4. 当你填写的小程序名称检测后提示如图信息,说明你的名称属于品牌名或商标,需要提供营业执照和其他证明材料,微信审核通过后,这个名称才能注册。 [图片]
2020-04-01 - show-scrollbar设置成false 仍有滚动条出现
show-scrollbar设置成false 仍有滚动条出现
2020-10-28 - 小程序app.onLaunch与page.onLoad异步问题的最佳实践
场景: 在小程序中大家应该都有这样的场景,在onLaunch里用wx.login静默登录拿到code,再用code去发送请求获取token、用户信息等,整个过程都是异步的,然后我们在业务页面里onLoad去用的时候异步请求还没回来,导致没拿到想要的数据,以往要么监听是否拿到,要么自己封装一套回调,总之都挺麻烦,每个页面都要写一堆无关当前页面的逻辑。 直接上终极解决方案,公司内部已接入两年很稳定: 1.可完美解决异步问题 2.不污染原生生命周期,与onLoad等钩子共存 3.使用方便 4.可灵活定制异步钩子 5.采用监听模式实现,接入无需修改以前相关逻辑 6.支持各种小程序和vue架构 。。。 //为了简洁明了的展示使用场景,以下有部分是伪代码,请勿直接粘贴使用,具体使用代码看Github文档 //app.js //globalData提出来声明 let globalData = { // 是否已拿到token token: '', // 用户信息 userInfo: { userId: '', head: '' } } //注册自定义钩子 import CustomHook from 'spa-custom-hooks'; CustomHook.install({ 'Login':{ name:'Login', watchKey: 'token', onUpdate(token){ //有token则触发此钩子 return !!token; } }, 'User':{ name:'User', watchKey: 'userInfo', onUpdate(user){ //获取到userinfo里的userId则触发此钩子 return !!user.userId; } } }, globalData) // 正常走初始化逻辑 App({ globalData, onLaunch() { //发起异步登录拿token login((token)=>{ this.globalData.token = token //使用token拿用户信息 getUser((user)=>{ this.globalData.user = user }) }) } }) //关键点来了 //Page.js,业务页面使用 Page({ onLoadLogin() { //拿到token啦,可以使用token发起请求了 const token = getApp().globalData.token }, onLoadUser() { //拿到用户信息啦 const userInfo = getApp().globalData.userInfo }, onReadyUser() { //页面初次渲染完毕 && 拿到用户信息,可以把头像渲染在canvas上面啦 const userInfo = getApp().globalData.userInfo // 获取canvas上下文 const ctx = getCanvasContext2d() ctx.drawImage(userInfo.head,0,0,100,100) }, onShowUser() { //页面每次显示 && 拿到用户信息,我要在页面每次显示的时候根据userInfo走不同的逻辑 const userInfo = getApp().globalData.userInfo switch(userInfo.sex){ case 0: // 走女生逻辑 break case 1: // 走男生逻辑 break } } }) 具体文档和Demo见↓ Github:https://github.com/1977474741/spa-custom-hooks 祝大家用的愉快,记得star哦
2023-04-23 - wxml-to-canvas没有fontWeight的相关支持?
wxml-to-canvas怎么设置fontWeight?还不支持透明度?作者你粗来 : (
2020-10-26 - 这个报错怎么处理????
真机上出现: Some selectors are not allowed in component wxss, including tag name selectors, ID selectors, and attribute selectors。 这是什么错误????怎么处理????没感觉出啥错误!!!!
2019-04-03 - 微信小程序相机授权,第一次拒绝了,再次进入小程序不会弹出授权窗口了?
微信小程序相机授权,第一次拒绝了,再次进入小程序不会弹出授权窗口了?
2022-09-02 - 如何在云开发中优雅地管控 CDN 流量?
在微信开放社区中,有不少使用云开发的小伙伴反馈遇到了“CDN流量消耗如流水”的情况。 有一觉醒来超额的: [图片] 有被高质量图片的加载“吓”到不敢用的: [图片] 遇到以上情况不要慌,很可能是你的使用姿势不对! 那么问题来了,如何在云开发中优雅地管控 CDN 流量消耗呢?本文就来和你详细聊聊! 按量付费和管道付费 为了便于理解,先来看看云开发的流量计费模式。 简单来说,按量计费就是:你有多少个量跑出去了,就给你算多少量;但是它并不限制你同一时间跑出去的量,也就是流量峰值不设限。 如果你在同一时间需要跑出去100M的量,那么峰值就给你开到100M,在同一时间跑完,最后算费用是100M的钱。 而管道付费则是限制给你开多宽的“道路”,按照这个“道路”的宽窄收费,比如你选择1M的网络道路,那就按照1M的价格来收钱;在使用时,你的量只能达到1M的速度,再也高不了了,这个最大速度就被称做带宽。 但是即使低峰没多少量时,你还必须为这个“道路”付钱。还是上述例子,你同一时间需要跑出去100M,但是速度只能给你开到1M,那么这些量在100秒后才可以走完,最后算费用是1M的道路租金*租用时长。 而在现实项目中,总会有业务的高峰和低峰,流量几乎不可能始终保持在一个恒定的速率,这就会造成管道计费有速度的天花板、但闲置时仍在计费的资源浪费问题。 云开发作为 Serverless 云原生一体化后端服务,提供的流量是按量计费的,不限制同一时刻的流量速度,因此,如果开发者使用不合理就会导致流速过快,进而造成“一眨眼的功夫,流量就超额了”的情况。 了解了按量付费和管道付费的区别后,咱们进入正题,说说 CDN。 什么是CDN流量? 我们在使用云开发时,几乎在各处都会看到CDN这个词。 CDN又称内容分发网络,通俗来讲就是将你主存储(源站)中的文件,复制给各地的存储点(CDN节点),当有用户访问这个资源时,直接从就近的存储点(CDN节点)获取即可。 云开发的云存储和静态网站托管天然支持 CDN 加速,所以你的用户通过客户端下载文件跑的流量都是 CDN 流量。 以上 CDN 流量只适用于各种渠道走加速公网下载文件的情况,比如浏览器加载网站,客户端下载资源,外部系统请求文件,通过临时地址的各种访问打开文件都在消耗 CDN 流量。 但是如果是内网访问文件,则不走 CDN 流量消耗,比如在云函数中通过 fileID 访问文件等。 什么是CDN回源流量? 当我们的存储中有文件更新时,存储在 CDN 节点的旧文件又该如何处理呢?在这里引入一个知识点——缓存时间。 这里的缓存时间其实就是文件副本在各地存储点(CDN节点)的有效时间,比如默认是两小时,那么每次文件副本在各地存储点的有效时间就是两小时,超过这个时间之后再收到请求时,存储点(CDN节点)就会丢弃过期的旧文件,向主存储(源站)请求最新的文件,而这一请求所产生的流量就称为 CDN 回源流量。 缓存时间既不能太长也不可太短,如果 CDN 缓存间隔时间过短,那么 CDN 节点上的数据会经常失效,导致频繁回源,增加了源站的负载,进而影响了整体的传输效率;如果缓存间隔时间过长,会带来数据更新不及时等严重的业务问题。 云开发的云存储就提供了非常细微颗粒度的缓存时间设置,你可以针对一个文件、一个路径甚至是文件后缀来进行分别设置。 [图片] 另外,多个缓存规则设置中还有优先级策略,调配变得更加灵活。 云存储是以从后到前的配置模式来做策略计算的,比如一个云存储的域名做了如下缓存配置: [图片] 现在请求此路径下资源/test/abc.jpg,其从后到前匹配方式如下: 匹配第一条所有文件,命中,此时缓存时间为 2 分钟。 匹配第二条,未命中。 匹配第三条,命中,此时缓存时间为300秒。 匹配第四条,命中,此时缓存时间为400秒。 匹配第五条,命中,此时缓存时间为200秒。 如何合理管控CDN? 我们需要把握一个原则: 缩减大小,善用缓存。 缩减大小的意思就是,我们在开发应用时,所需要的多媒体文件,如果没有特殊要求(比如摄像馆的原图发送),需要尽可能的压缩。只有减轻了业务资源的大小,才能够根本的减少流量资源的消耗。 另外,用户在上传多媒体资源时,仍然可以使用平台或框架能力对资源进行压缩后再上传,保证资源都是经过优化后进入存储,这样在请求下载时就会减轻很多负担。 善用缓存意思就是同一个用户、同一份资源尽可能不要请求一次以上,要合理使用客户端的本地缓存能力,将固定资源全部缓存。当用户再此进入时,直接使用缓存的资源。 例如,微信小程序官方就提供了图片缓存配置,开启后所有图片均进行缓存,下次读取相同资源时,直接从缓存中读取。 文档链接:http://mrw.so/6wT3TR 再送给大家一句网络金句:缓存用的好,PV 的效果用的只是 UV 的量。 而在具体使用时,大家还是需要根据自己的业务情况来合理把握。比如你的资源变更非常频繁,就不太适合缓存优化;而你的资源不能压缩,要保持原大小,则就不适合压缩优化。 结语 以上攻略送给各位 hold 不住 CDN 流量的小伙伴们,如果大家觉得 CDN 消耗如流水,用户活跃却没有多少起色,可能就需要好好检查一下自己哪里浪费了。勤俭节约可是中华民族的传统美德,云开发虽好,也需要节约使用哦~ 小程序·云开发「错误监控」功能有奖调研 诚邀各位云开发者参与小程序·云开发「错误监控」功能有奖调研,参与即送小礼品。 [图片] 期待您的宝贵建议,快扫描下图中的二维码参与吧! 产品介绍 云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为开发者提供高可用、自动弹性扩缩的后端云服务,包含计算、存储、托管等serverless化能力,可用于云端一体化开发多种端应用(小程序,公众号,Web 应用,Flutter 客户端等),帮助开发者统一构建和管理后端服务和云资源,避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。 开通云开发:https://console.cloud.tencent.com/tcb?tdl_anchor=techsite 产品文档:https://cloud.tencent.com/product/tcb?from=12763 技术文档:https://cloudbase.net?from=10004 技术交流加Q群:601134960 最新资讯关注微信公众号【腾讯云云开发】
2021-01-21 - 微信支付多小程序进行一个商户号?
目前有客户想要实现小程序裂变,会有多个小程序,但是想资金流向一个商户号。 问题: 1.除了复制程序源码部署,还有什么方式可以实现,尽量使用一套代码维护。 2.多个小程序资金流向一个商户号,这种税务问题会有什么情况,大体手续费会是多少。 3.目前一个商户号只能用50个小程序,有没有什么方式可以实现多个。 4.这种项目还需要注意什么。 诚心发问~~ 礼貌解答,谢谢。
2023-06-21 - 普通商户号与两个微信小程序关联成功,但是第二个小程序拉起微信支付失败,何解?
拉起微信支付失败报错信息: 日志内容 Request ID: 28dc0cca-f988-11ea-8e5c-5254002665ac 执行时间: 269ms内存使用: 45.32 MB 返回结果 {"returnCode":"FAIL","returnMsg":"sub_mch_id与sub_appid不匹配","errCode":0,"errMsg":"cloudPay.unifiedOrder:ok"} 日志 START RequestId: 28dc0cca-f988-11ea-8e5c-5254002665ac Event RequestId: 28dc0cca-f988-11ea-8e5c-5254002665ac END RequestId: 28dc0cca-f988-11ea-8e5c-5254002665ac Report RequestId: 28dc0cca-f988-11ea-8e5c-5254002665ac Duration:269ms Memory:256MB MemUsage:45.320312MB 已成功关联到同一普通商户号下的两个小程序: [图片] 拉起微信支付报错截图: [图片] sub_mch_id在哪里?这个微信支付分配的子商户号从哪里查找?谢谢!
2020-09-18 - 微信小程序转发朋友圈详解
概述点击右上角分享朋友圈[图片] 分享到朋友圈样式[图片] 朋友圈打开样式[图片] 这个功能目前只支持Android(在IOS高版本微信支持朋友圈打开小程序能力,但不能分享)。 用户打开朋友圈分享的小程序,看到不是真正的小程序,而是原本页面的“单页模式”。 什么是“单页模式”?以下是微信官方对于“单页模式”的描述: “单页模式”下,页面顶部固定有导航栏,标题显示为当前页面 JSON 配置的标题。底部固定有操作栏,点击操作栏的“前往小程序”可打开小程序的当前页面。顶部导航栏与底部操作栏均不支持自定义样式。“单页模式”默认运行的是小程序页面内容,但由于页面固定有顶部导航栏与底部操作栏,很可能会影响小程序页面的布局。因此,请开发者特别注意适配“单页模式”的页面交互,以实现流畅完整的交互体验。限制另外,“单页模式”存在着很多限制。以下是官方给出的禁用能力列表: [图片] 限制主要包括以下几点: 页面无登录态,与登录相关的接口,如 [代码]wx.login[代码] 均不可用不允许跳转到其它页面,包括任何跳小程序页面、跳其它小程序、跳微信原生页面若页面包含 tabBar,tabBar 不会渲染,包括自定义 tabBar本地存储与小程序普通模式不共用这些限制,让“单页模式”只适用于内容展示,不适用于有较多交互。 配置针对“单页模式”,新增了单页模式相关配置。目前这个配置里只有一个navigationBarFit属性: [图片] navigationBarFit属性主要是针对原页面设置了自定义导航栏的情况。也就是原页面的json文件中配置了这个属性: { // ... "navigationStyle":"custom" // ... } 给大家看一下普通导航栏和自定义导航栏的区别,下图是普通导航栏页面: [图片] 下图是自定义导航栏页面,我们在原本的导航栏位置使用了banner: [图片] [代码]"navigationStyle":"custom"[代码]这个设置在“单页模式”下也会生效。前文微信官方对“单页模式”的描述有说到“顶部导航栏与底部操作栏均不支持自定义样式”。如果我们在原页面设置了自定义导航栏。那么“单页模式”样式就会变成这样: [图片] 通过设置navigationBarFit为 [代码]squeezed[代码]就可以解决这个问题: { // ... "singlePage": { "navigationBarFit": "squeezed" } // ... } 设置后的样式: [图片] 开发 接下来介绍如何在小程序中实现这个功能。 第一步在需要转发朋友圈的页面中注册用户点击右上角转发功能,这是实现转发朋友圈功能的必要满足条件。 onShareAppMessage: function () { return { title: '转发标题', path: '/pages/home/index', imageUrl: '自定义图片路径' } } 第二步注册分享朋友圈功能(从基础库 [代码]2.11.3[代码] 开始支持): onShareTimeline: function () { return { title: '转发标题', query: 'from=pyq', imageUrl: '自定义图片路径' } } 注意,这里有个问题,分享朋友圈功能不支持自定义页面路径,意味着只能转发当前页面。如果当前页面存在较多“单页模式”限制功能,就可能让我们的页面不能按预期展示。 当页面存在限制功能时,我们存在两个方案,第一个方案,针对“单页模式”做改动,不调用那些限制的功能。第二个方案,另外写一个针对“单页模式”的页面。 这两种方案都需要能判断当前是否正处在小程序“单页模式”。 我们通过判断场景值(场景值用来描述用户进入小程序的路径)是否等于 1154 来判断当前是否正处在小程序“单页模式”。场景值可以在 [代码]App[代码] 的 [代码]onLaunch[代码] 获取。 // app.js App({ // ... onLaunch(options) { const { scene } = options; this.isSinglePage = scene === 1154; } // ... }) 我们将是否正处在“单页模式”的Boolean值放入App实例,方便全局拿到值。 接下来说说两种方案。 第一种方案,在“单页模式”不调用那些限制功能(这是一种不推荐的方案,代码耦合性太强)。举个例子: const app = getApp(); Page({ // ... onLoad() { if (!app.isSinglePage) { wx.login({ // ... }) } } // ... }) 第二种方案,针对“单页模式”另写一个页面。因为分享朋友圈功能并不支持自定义页面路径,我们只能另外写一个组件来作为“单页模式”的内容承载。 将isSinglePage放入页面的初始数据,方便在wxml中拿到: // pages/home/index.js const app = getApp(); Page({ data: { isSinglePage: app.isSinglePage, } // ... }) home-single-page就是分享到朋友圈的内容承载组件: // pages/home/index.json { // ... "usingComponents": { "home-single-page": "components/home-single-page/index" }, } 当“单页模式”时,我们展示 [代码]home-single-page[代码]组件,否则就展示普通页面内容: // pages/home/index.wxml 样式上虽然搞定了,但是在原本的生命周期中可能会调用一些限制功能,或者跑一些其它“单页模式”用不上的内容。我们得停止原本生命周期函数调用。 建议对传入Page的对象进行统一处理,当“单页模式”时,不调用原本的生命周期: // pages/home/index.js import ExtendPage from 'common/extend-page/index' const app = getApp(); ExtendPage({ data: { isSinglePage: app.isSinglePage, } // ... }) ExtendPage函数针对“单页模式”进行统一处理: // common/extend-page/index.js const app = getApp(); const PAGE_LIFE = [ 'onLoad', 'onReady', 'onShow', 'onHide', 'onError', 'onUnload', 'onResize', 'onPullDownRefresh', 'onReachBottom', 'onPageScroll' ]; export default function(option) { let newOption = {}; if(app.isSinglePage) { newOption = PAGE_LIFE.reduce((res, lifeKey) => { if (option[lifeKey]) { res[lifeKey] = undefined; } return res; }, {}) } return Page({ ...option, ...newOption, }); } 在“单页模式”下,我们将原本的生命周期都停止了调用。这样就能很好的将“单页模式”下的页面和普通页面进行解耦。 如果”单页模式“页面比较复杂,需要使用生命周期。我们也可以添加 [代码]singlePageLife[代码]属性,当处在“单页模式”下,就调用 [代码]singlePageLife[代码]内的生命周期: // pages/home/index.js import ExtendPage from 'common/extend-page/index' const app = getApp(); ExtendPage({ data: { isSinglePage: app.isSinglePage, }, singlePageLife: { onLoad() { // ... }, } // ... }) // common/extend-page/index.js const app = getApp(); const PAGE_LIFE = [ 'onLoad', 'onReady', 'onShow', 'onHide', 'onError', 'onUnload', 'onResize', 'onPullDownRefresh', 'onReachBottom', 'onPageScroll' ]; export default function(option) { let newOption = {}; if(app.isSinglePage) { const { singlePageLife } = option; newOption = PAGE_LIFE.reduce((res, lifeKey) => { if (singlePageLife[lifeKey]) { res[lifeKey] = singlePageLife[lifeKey]; } else if(option[lifeKey]) { res[lifeKey] = undefined; } return res; }, {}) } return Page({ ...option, ...newOption, }); } 文章如有疏漏、错误欢迎批评指正。
2020-10-21 - ✨单页面多个按钮分享方法,onShareAppMessage()进阶用法,详细介绍
现在有这样一个需求: 如下图, [图片][图片][图片] 点击三个点分享: 将整个列表分享给好友. 点击按钮一: 将整个列表分享给好友. 点击按钮二: 将一行数据分享给好友. 点击按钮三: 将搜索出的结果分享给好友. 好,我们先静一静,缕一缕思路. 解决方案开始: 一、点击三个点分享:将整个列表分享给好友: 这个需求相对简单,只需要将这个列表的ID传分享出去,接收页面接受列表ID,把这个列表的所有数据列出来就行了,代码如下: /** * 用户点击右上角分享 */ onShareAppMessage(res) { return { title: '您的好友向您分享了一本通讯录: ' + this.data.setting.name, imageUrl: this.data.setting.share_img, path: 'pages/share/index?user_id=' + getApp().globalData.user_id + '&id=' + id } } 参数解释: title:可以定义分享卡片上显示的字符串,最高28个汉字,超出部分会被...代替 imageUrl: 定义分享卡片上的分享图,不填则截取当前屏幕顶部750rpx*600rpx的区域当分享图。自定义分享图最佳尺寸比例是5:4,超出则会截取 path:定义点击分享卡片跳转的界面,不填则会跳转到首页,并不是当前分享页。可以填任意页面并带参数,path参数最高只支持2048个字符,超出则读取不了。 二、点击按钮一: 将整个列表分享给好友. 同步骤一,这里只需要设定一个button,并设定open-type="sahre"就可以了,效果和点击三个点再点分享效果一致。 <button open-type="share">分享</button> 三、点击按钮二: 将一行数据分享给好友. 因为分享的东西不一样,实现这个功能,就要考虑2个问题。第一:要判断用户是否点三个点menu进行的分享;第二:要判断用户是点的全列表分享按钮还是我们只分享一行数据的按钮; (1)判断用户是否点击menu进行分享: /** * 用户点击右上角分享 */ onShareAppMessage(res) { if(res.from=="menu"){ return { title: '您的好友向您分享了一本通讯录: ' + this.data.setting.name, imageUrl: this.data.setting.share_img, path: 'pages/share/index?user_id=' + getApp().globalData.user_id + '&id=' + id } } if(res.from=="button"){ return { title: '您的好友向您分享了一本通讯录: ' + this.data.setting.name, imageUrl: this.data.setting.share_img, path: 'pages/share/index?user_id=' + getApp().globalData.user_id +'&id=' + id } } }, 这里通过读取res.from判断,menu是点击三个点分享,button判断是通过点击按钮进行分享 (2)判断用户是点击那个按钮进行分享: wxml代码: <button open-type="share">分享</button> <button open-type="share" id="single">分享一个联系人</button> JS代码: /** * 用户点击右上角分享 */ onShareAppMessage(res) { if(res.from=="menu"){ return { title: '您的好友向您分享了一本通讯录: ' + this.data.setting.name, imageUrl: this.data.setting.share_img, path: 'pages/share/index?type=0&user_id=' + getApp().globalData.user_id + '&id=' + id } } if(res.from=="button"){ let type = res.target.id if(type=='single'){ return { title: '您的好友向您分享了一个联系人: ' + this.data.data[this.data.tel_index].name, imageUrl: this.data.setting.share_img, path: 'pages/share/index?type=1&user_id=' + getApp().globalData.user_id + '&id=' + this.data.data[this.data.tel_index].id, } }else{ return { title: '您的好友向您分享了一本通讯录: ' + this.data.setting.name, imageUrl: this.data.setting.share_img, path: 'pages/share/index?type=0&user_id=' + getApp().globalData.user_id +'&id=' + id } } } }, 这里通过读取res.target.id判断,用户是点击了哪个按钮,从而分享不同的参数。path里加了type参数,告诉分享界面我是那种模式分享,从而显示不同显示结果。 四、点击按钮三:将搜索出的结果分享给好友. 刚才说到了,path后面最多填2048个字符,如果搜索出来的结果多了,则没法全部分享。所以我们只告诉分享页我们分享的列表ID和搜索时填的参数。 //本文用的是this.data.value传参,也可以使用 //进行传参,通过读取 let id = res.currentTarget.dataset.id let type = res.currentTarget.dataset.type //读取俩个参数的数据 /** * 用户点击右上角分享 */ onShareAppMessage(res) { if(res.from=="menu"){ return { title: '您的好友向您分享了一本通讯录: ' + this.data.setting.name, imageUrl: this.data.setting.share_img, path: 'pages/share/index?type=0&user_id=' + getApp().globalData.user_id + '&id=' + id } } if(res.from=="button"){ let type = res.target.id if(type=='single'){ return { title: '您的好友向您分享了一个联系人: ' + this.data.data[this.data.tel_index].name, imageUrl: this.data.setting.share_img, path: 'pages/share/index?type=1&user_id=' + getApp().globalData.user_id + '&id=' + this.data.data[this.data.tel_index].id, } }else if(type=='search'){ return { title: '您的好友向您分享了一本通讯录: ' + this.data.setting.name, imageUrl: this.data.setting.share_img, path: 'pages/share/index?type=2&user_id=' + getApp().globalData.user_id + '&id=' + id + '&status=' + this.data.active + '&name=' + this.data.search_name + '&tel=' + this.data.search_tel } }else{ return { title: '您的好友向您分享了一本通讯录: ' + this.data.setting.name, imageUrl: this.data.setting.share_img, path: 'pages/share/index?type=0&user_id=' + getApp().globalData.user_id +'&id=' + id } } } }, 五、聊一下在onShareAppMessage是否可以通过wx.request()来动态读取数据进行分享 //官方示例代码 Page({ onShareAppMessage() { const promise = new Promise(resolve => { setTimeout(() => { resolve({ title: '自定义转发标题' }) }, 2000) }) return { title: '自定义转发标题', path: '/page/user?id=123', promise } } }) 可以使用promise中进行wx.request()进行动态读取数据进行分享,但是不可以超过3000ms,超过了系统会直接跳出进行分享,如果对自己的接口反映速度有自信可以使用,不然分享的时候用户会感觉点了分享按钮卡顿。。。 结尾:样例小程序二维码,自己做的一个免费好用的通讯录小程序 [图片]
2023-05-26 - 实现小程序分享朋友圈功能
一大早在各科技公众号有看到小程序支持直接分享到朋友圈,这么好的功能,忍不住要实践下。 根据官方文档走起,文档地址:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/share-timeline.html 然后根据官方文档的意思,目前之支持Android版本,为什么IOS版本总是慢一些呢,(╯▔皿▔)╯ 接下来先上代码(需要注意的是得是最新版的预发布版本才行,下载链接:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html) [图片] [图片] 在需要分享的页面对应的js文件里面写入"onShareTimeline"即可,需要注意的是需要先编写"onShareAppMessage"方法。 [图片] 点击右上角三个点,出来的效果如下图所示 [图片][图片] 再次点击右下角得"查看小程序分享页"就可以看到类似官方文档上的效果,具体如下图所示: [图片][图片] 在Android手机端下载最新版本的小程序示例,也未发现对应的分享朋友圈功能,静候微信团队的更新
2020-07-08 - 小代码大作用,云函数openapi
以下云函数openapi的代码极简,但是作用很多,包括: (代码直接复制可用) 1、支持所有云调用;是所有哦。 2、支持大图片安全检查 3、支持环境共享的云调用。 云函数代码如下: const cloud = require('wx-server-sdk') cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) const opt = {} exports.main = async event => { const wxc = cloud.getWXContext() opt.appid = wxc.FROM_APPID || wxc.APPID//获取环境或共享环境的访问端小程序appid if (event.action == 'security.imgSecCheck') return await imgSecCheck(event)//大图片安全检查 if (event.action == 'xxx') return await xxx(event)//其他特殊处理 return await cloud.openapi(opt)[event.action](event.body || {}) } async function imgSecCheck(event) { let res = await cloud.downloadFile({ fileID: event.fileID, }) return await cloud.openapi(opt).security.imgSecCheck({ media: { contentType: "image/png", value: res.fileContent } }) } 小程序端的调用代码示例: 1、获取小程序码 app.cloud.callFunction({ //app.cloud是小程序当前环境的cloud,在app.js中初始化,可能是wx.cloud,也可能是共享环境的cloud name: 'openapi', data: { action: 'wxacode.getUnlimited', body: { scene, width: 280 }, } }) 2、发送订阅消息 app.cloud.callFunction({ name: 'openapi', data: { action: 'subscribeMessage.send', body: { "touser": openid, "page": 'pages/index/index?orderId=' + order._id, data, "templateId": tid, "miniprogramState": 'trial' } } }) 3、获取小程序直播房间列表 app.cloud.callFunction({ name: 'openapi', data: { action: 'liveBroadcast.getLiveInfo', body: { start: 0, limit: 100 } } })
2022-06-14 - 共享环境时的支付问题
同一个账号主体下的多个小程序共享一个云环境,云函数中调用 cloud.cloudPay.unifiedOrder() ,小程序端调用 wx.requestPayment() 提示APPID不对,这情况要怎么处理?
2022-09-15 - 共享环境下能调unifiedOrder唤起支付吗?
将小程序A云开发环境共享给小程序B。小程序B有微信支付功能,故调用A的云函数用unifiedOrder方法来计算签名返回前端。但unifiedOrder方法没有appid入参,导致算出来的签名里的appId是小程序A的,不是小程序B的,从而在支付时提示“商户传入的appid参数不正确,请联系商户处理”。 那么在共享环境下能调用unifiedOrder来支付吗?
2022-11-14 - 共享云环境时代来了,解决fileID带来不兼容问题。
云开发收费了,不管你怎么选择,只要你还继续使用云开发,共享云环境的课题就不可避免。 我们知道,共享云环境下,fileID是无法使用的,怎么兼容,一个最简的方法如下: <wxs module="wxs"> module.exports = { getUrl: function (link) { if (link) { } else return '' if (link.substring(0, 5) == 'cloud') { } else return link var arr = link.split('/') arr[0] = 'https:' arr[2] = arr[2].split('.')[1] + '.tcb.qcloud.la' return arr.join('/') } } </wxs> <image src="{{wxs.getUrl(link)}}"></image> 可见:只要将原项目所有的fileID换成wxs.getUrl(link) 其他代码可以一分不动,也不需要用到wx.cloud.getTempFileURL 可以将wxs.getUrl放在lib.wxs里,任何wxml引用即可。
2022-10-28 - image组件的src设置成共享云的图片id为什么不能显示?
<image src="cloud://cloud_id_xxxxx/images/peach.svg" mode="aspectFit" style="height:80px; width:80px;"> </image> 图片放共享的云存储中,不可以正常显示
2022-12-16 - 云函数支付,统一下单,functionName:pay_cb 返回支付成功信息,怎么传回小程序 ?
我统一下单,我的functionName:pay_cb函数中返回 retrun{ errcode:0 ,errmsg:success}怎么传回小程序端呢?我现在只能在日志里面能看到这个返回值。 统一下单云函数: const res = await cloud.cloudPay.unifiedOrder({ "body" : "德海生鲜", "outTradeNo" : event.order_number_send, "spbillCreateIp" : "127.0.0.1", "subMchId" : "1591", "totalFee" : 1, "envId": "dehai-alpha-bq", "functionName": "pay_cb", }) console.log("bpay=",res) return res } "functionName": "pay_cb" 云函数: // pay_cb 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init({ env:'dehai-alpha-bk9zq' }) const db = cloud.database() const _ = db.command exports.main = async (event, context) => { await db.collection('orders').doc(event.outTradeNo).set({ data:event }) return { errcode:0, errmsg:'SUCCESS' } }
2020-06-08 - 小程序欠费,关闭高级日志就OK啦
这个小程序没啥用户使用,每个月就是交个基本费19.9元,今天上来一看,竟然欠费了: [图片] 在没收入的年代,1.74元可是一笔巨款啊,查看一下扣费日志: [图片] 每天扣了0.04元,日积月累巨款就被扣掉啦。还好,刚才看了一下,欠费归欠费,小程序云开发还是能正常跑的,比起双向收费、欠费立马停机的某动要文明的多了。 [图片] 解决措施:在云开发控制台中,关闭云函数的高级日志,就OK啦。 上图,点击右边的“关闭日志”按钮,全部搞定。
2022-12-09 - 无法收到回调全网最全图文指引,看完就能有效的解决你的问题!!!!
前言:相信很多朋友在开发微信支付接口时遇到无法收到回调问题非常的懊恼,不知道从何下手,相信看完本文章基本就能解决你无法收到回调的问题了。阅读本文章前,建议提前看一下文章右侧的目录,帮助你更好的阅读此文章。 -------- 提前需要准备的工具:postman(其他能调试API的工具也可以) -------- 特别说明:这里说的回调都是后端回调,跟前端的回调方法是没有关系,前端的方法需要到社区进行咨询,例如小程序支付的前端方法问题需要到社区小程序模块进行咨询 什么情况下才会有回调通知 1、 支付成功后微信侧才会发送支付结果回调通知 可参考官方文档:支付通知API 2、 申请退款成功后,只有退款状态为退款异常、退款关闭、退款成功才会发送退款回调通知 可参考官方文档:退款结果通知API 注意: 1.上面只是举例了两个接口,还要更多的回调接口,每个回调接口都会有对应的 通知频率 和 回调触发条件 -------- 2.支付结果回调 是异步队列加公网通知的,支付完成后会立即发送回调消息,以支付结果回调为准,不存在回调支付成功,查询接口却一直返回的是未支付 -------- 3.退款回调 是异步的,申请退款接口返回的成功只是代表了申请退款这个操作成功了,退款整个流程可能经过银行等,所以 回调时长可能会长一些 -------- 4.申请退款成功后,用户侧长时间未到账,或商户查询退款状态一直都是退款中,则可能是退款到用户银行卡中,需要经过银行,一般在7个工作内是比较正常的,若7个工作日后还是退款中,请拨打95017协助排查 -------- 5.回调的作用是告诉商户结果是什么,商户应答回调是告诉接口已经成功收到回调,建议商户最好是按照文档要求去应答接口,若商户是自行查询接口来判断情况,而不是根据回调来判断,理论上是可以不去管回调(包括应答),但还是强烈建议按照正常流程正确的应答接口 -------- 下面介绍一下每一种无法接受到回调的情况及对应的检查方法 -------- 情况一:v3接口能支付成功,未设置APIv3密钥则无法收到回调(非常重要!!!非常重要!!!非常重要!!!一定要优先设置,只要是v3接口,不设置APIv3密钥则无法收到回调) 什么是APIv3密钥?如何设置? [图片] [图片] 注意(APIv2密钥以前也叫API密钥): 1.v2接口 使用的是 APIV2密钥,v2接口 下单能成功 说明就设置好了APIv2密钥。 -------- 2.APIv3密钥 与 APIV2密钥 是隔离的,设置APIv3密钥时,不会导致APIV2密钥发生变化,且 对v2接口没有影响。 -------- 情况二:下单时实际填写的回调地址跟自己实际想要的回调地址不一致,可能多了 / 或者 空格 (注意退款接口需要填写退款回调地址, 不然无法收到回调) [图片] -------- 比如想要的是:http://www.qqweixin.top/weixin/pay/callback/test -------- 实际的填写的:http://www.qqweixin.top/weixin/pay//callback/test -------- 可以重新下一笔新的订单,仔细确认下单时传递的地址跟实际需要的地址是否一致 情况三(硬性条件,不要抱着侥幸心理!!!):回调地址不规范,回调地址规则:回调地址不能携带参数及端口号且不能是直接的ip,域名不能携带特殊符号(比如-等),请检查下单时的回调地址是否有携带参数或端口号,必须为 公网域名 且是 https 开头,现使用 http开头 、携带 端口号 或是 ip 能正常接收回调的用户,建议更换为 https 且去除 端口号 使用正常的域名,避免后期出现回调通知无法接收的情况,请求方式为post请求。 notify_url填写注意事项 [图片] -------- 错误示例: 携带端口号:http://www.qqweixin.top:443/weixin/pay/callback/test 携带参数:http://www.qqweixin.top/weixin/pay/callback/test?id=10086 使用ip地址:192.168.x.x 非公网域名:[图片](一定要使用公网ip映射的域名) -------- 如何检查域名是否有问题:核实回调地址是否可被外网访问,是否有DNS解析成功。 (检查ip地址/域名是否可以ping通:如何ping域名,建议是在不同网络下进行操作,这样可以检查是否是内网ip,ping不通可能的原因是ip地址和域名没有映射成功或者是内网ip(同网络能ping通,不同网络不能ping通,一般就是内网ip),需要到注册的域名网站重新进行映射) 成功示例:[图片] 失败示例:[图片] -------- 情况四:开通了防火墙,拦截了回调 (是否开通了防火墙导致回调地址被拦截了,开通防火墙后设置一下白名单,回调IP段白名单) [图片] -------- 情况五:商户侧网络波动导致部分回调丢失 商户侧由于网络波动导致部分部分回调数据没有正常存储或数据丢失等,可以按照网络监测工具检查 1.一般商户侧出现就部分订单的回调丢失就是这种情况,微信侧目前没有出现过支付成功后未给商户发送回调的情况,若极端情况下出现,官方也肯定是会在第一时间通知商户,所以基本都是商户自身网络问题导致 网络排查工具 [图片] 2.商户业务层已经对回调处理完成并成功应答, 但商户侧自身系统问题,导致这条回调数据丢失,需要商户自身排查 -------- 情况六:程序代码问题(若使用的回调地址本身是在正常使用的回调地址,是对代码或者环境修改后出现的问题,则说明是代码层面或者环境的问题) 使用postman等API调试工具模拟微信支付回调的格式测试,检查代码是否能正常接收回调信息,v2接口的回调信息是xml格式,v3接口的回调格式json格式,上述两种格式都是以字符串的形式发送的数据流,特殊情况:只要是在商户平台进行 手动退款的回调通知都是xml格式。 (注意测试时,发送回调和接收回调尽量不要在同一网络当中,避免都是在是同一网络测试结果不准确,注意:接收到回调为空的现象一般都是接收格式的问题,比如xml格式的数据使用json格式接收) v2接口回调格式(固定为xml格式,v2部分接口需要解密,比如:退款接口,详情会在接口特别说明说明中有描述,退款结果通知) [图片] 示例: <xml> <appid><![CDATA[wx2421b1c4370ec43b]]></appid> <attach><![CDATA[支付测试]]></attach> <bank_type><![CDATA[CFT]]></bank_type> <fee_type><![CDATA[CNY]]></fee_type> <is_subscribe><![CDATA[Y]]></is_subscribe> <mch_id><![CDATA[10000100]]></mch_id> <nonce_str><![CDATA[5d2b6c2a8db53831f7eda20af46e531c]]></nonce_str> <openid><![CDATA[oUpF8uMEb4qRXf22hE3X68TekukE]]></openid> <out_trade_no><![CDATA[1409811653]]></out_trade_no> <result_code><![CDATA[SUCCESS]]></result_code> <return_code><![CDATA[SUCCESS]]></return_code> <sign><![CDATA[B552ED6B279343CB493C5DD0D78AB241]]></sign> <time_end><![CDATA[20140903131540]]></time_end> <total_fee>1</total_fee> <coupon_fee><![CDATA[10]]></coupon_fee> <coupon_count><![CDATA[1]]></coupon_count> <coupon_type><![CDATA[CASH]]></coupon_type> <coupon_id><![CDATA[10000]]></coupon_id> <trade_type><![CDATA[JSAPI]]></trade_type> <transaction_id><![CDATA[1004400740201409030005092168]]></transaction_id> </xml> v3接口回调格式(固定为json格式,格式固定,内容不一样,需要解密) [图片] 示例: { “id”: “EV-2018022511223320873”, “create_time”: “2015-05-20T13:29:35+08:00”, “resource_type”: “encrypt-resource”, “event_type”: “TRANSACTION.SUCCESS”, “summary”: “支付成功”, “resource”: { “original_type”: “transaction”, “algorithm”: “AEAD_AES_256_GCM”, “ciphertext”: “3TxpOF8YqF5Zy2cYQWrZNnmC1FWrxwIPvIv4WejUr+8ctmM6L3kxqQ6JS56S7JkVFMiCvfcMGkQFMtUifq09Wrt6+bNwMUNLKQ52zLyMLwS9uML2Y2Qmi1obactel3rwwTs+IXGir505F2eLBG9ruqtJxGd2dlsLQ+0Sl7OUA/mMCnxMXUhfwJC84lv2oZDC3T827Mzy0BQ5YmXfdpgOA0OCTl+OwokWMXJz2DiGafE1n0pqH/R0VgDyUCEAOb6l+dFRR7S0I1yVe7/6czAYp+i7mTgNrmudG7EgDoOVfGga9Wq9epO6PEew1ypK5M8PmIopNSzg34WEouFhOqvPZfi2paqib2gxexcqtniQQbdechavr4SH/3JSpg8Zbnnbeo3ClFDU7eRVO2FCAPQaMlcSmjU4zv2H98dvB9TnIyon/so+QwSo/ZwWMnTKeztviuYd5ICbrtzAPoeeDrPlYlB0pwlFT8Tz3lqC0QZWKvL0+FIj0+9P+2/JvZpr5aVrFosMI1Afb17P7zx69jnLFPFX0ph4AgBK/N8oRNg12uVqvJM3E07/4P7LWLKyrf9FySovQplbhlasAyOf5PWb3aBwEv19hr71uMvAyuCll39zhIZ9M1CZTcSLpuyeWDOUwt3Y7ww0mOMruvK5a5mREuowqfP/OVv73yX/mf/7MEo9wAvz2bNqAuS0c9xc2yn5EHN4rNSTgApcJh2OTNUVEZXu7sL04S/pKpApS4eXxTS1bnLeqVfk5rePQagXFXwMFJVfAPmLyMRLsBLpdc2lO2LIof+nx8HnqjHvKYnolRgJYAlUuHx1mdjsPrZreDjK12b3cBznrfC7gac+3VW4r42f2b533RCAvchchxb7l+sdzQSFImbxZ1IAZFO/ZozZEFFko2FypOh2SdZYigW6Rq6hxw8EFOrvp6GwKpkhGbb4xnQsGHupDAMte5QmiMb9M8KUP5DSIo7gCsO7FMWtXFrdetyQfLXsZ/CidA+JOlSGKL+8s/ISyajpl8YseGNhlq39Zci53GoQCETs/ixLPz4BOTeTLC9FASUoEGPKet+OvYhdo4Xlopbhs95jl6jjgZcT6Bkr5ivG2ocqi2aP5hpnnVDXq/OwXvdofTHxlp2oydlYo9xqXhg+emzSQ8woub6XXO22KOKuEcWMSCiSMWYm9gsP2v0QkCw54ZmJHuDoivV2jVrFQjdH9nO2m68SHj9I9PBj4eSbDG235d/gSxp6VrrH+UaP5b4fjZi4xZ+9Nr1oUAc1Z6RRqqvCVLY1DTMpp2H/aXr9gNUs8fL8kkfuiWEKTkcoW/JKTZjiizzbHEkXSU3+dm4AITiKWrdvSUs80OGg==”, “associated_data”: “certificate”, “nonce”: “4de73afd28b6” } } -------- 情况七:域名(url)转发导致的DNS解析失败 域名转发:所谓域名(url)转发,是通过服务器的特殊设置,将访问您当前域名的用户引导到您指定的另一个网络地址。 地址转向(也可称“URL转发”)即将一个域名指向到另外一个已存在的站点,英文称为“ URL FORWARDING ”。 DNS解析失败:解析失败就是找不到相关域名对应的IP 这种情况一般自己比较难排查吗,所以不要做域名转发,然后再进行测试,出现问题后再按照上述步骤进行检查(建议直接咨询自己的运维人员,他们知道如何处理)
2023-05-10 - 微信支付成功没有回调,按排查步骤排查未果,能否请官方技术帮忙核查下订单?
微信支付成功没有回调。按步骤排查 全都符合要求。请帮忙核查下订单。
2022-08-25 - 借助小程序云开发实现小程序支付功能(含源码)
我们在做小程序支付相关的开发时,总会遇到这些难题。小程序调用微信支付时,必须要有自己的服务器,有自己的备案域名,有自己的后台开发。这就导致我们做小程序支付时的成本很大。本节就来教大家如何使用小程序云开发实现小程序支付功能的开发。不用搭建自己的服务器,不用有自己的备案域名。只需要简简单单的使用小程序云开发。 老规矩先看效果图: [图片] 本节知识点 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 - 10行代码实现小程序支付功能!丨实战
前面给大家讲过一个借助小程序云开发实现微信支付的,但是那个操作稍微有点繁琐,并且还会经常出现问题,今天就给大家讲一个简单的,并且借助官方支付api实现小程序支付功能。 传送门: 借助小程序云开发实现小程序支付功能 老规矩,先看本节效果图 [图片] 我们实现这个支付功能完全是借助小程序云开发实现的,不用搭建自己的服务器,不用买域名,不用备案域名,不用支持https。只需要一个简单的云函数,就可以轻松的实现微信小程序支付功能。 核心代码就下面这些: [图片] 一、创建一个云开发小程序 关于如何创建云开发小程序,这里我就不再做具体讲解。不知道怎么创建云开发小程序的同学,可以去翻看腾讯云云开发公众号内菜单【技术交流-视频教程】中的教学视频。 创建云开发小程序有几点注意的 1.一定不要忘记在app.js里初始化云开发环境。 [图片] 2.创建完云函数后,一定要记得上传 二、创建支付的云函数 1.创建云函数pay [图片] [图片] 三、引入三方依赖tenpay 我们这里引入三方依赖的目的,是创建我们支付时需要的一些参数。我们安装依赖是使用里npm 而npm必须安装node,关于如何安装node,我这里不做讲解,百度一下,网上一大堆。 1.首先右键pay,然后选择在终端中打开 [图片] 2.我们使用npm来安装这个依赖。 在命令行里执行 npm i tenpay [图片] [图片] [图片] 安装完成后,我们的pay云函数会多出一个package.json 文件 [图片] 到这里我们的tenpay依赖就安装好了。 四、编写云函数pay [图片] 完整代码如下 [代码]//云开发实现支付 const cloud = require('wx-server-sdk') cloud.init() //1,引入支付的三方依赖 const tenpay = require('tenpay'); //2,配置支付信息 const config = { appid: '你的小程序appid', mchid: '你的微信商户号', partnerKey: '微信支付安全密钥', notify_url: '支付回调网址,这里可以先随意填一个网址', spbill_create_ip: '127.0.0.1' //这里填这个就可以 }; exports.main = async(event, context) => { const wxContext = cloud.getWXContext() let { orderid, money } = event; //3,初始化支付 const api = tenpay.init(config); let result = await api.getPayParams({ out_trade_no: orderid, body: '商品简单描述', total_fee: money, //订单金额(分), openid: wxContext.OPENID //付款用户的openid }); return result; } [代码] 一定要注意把appid,mchid,partnerKey换成你自己的。 到这里我们获取小程序支付所需参数的云函数代码就编写完成了。 不要忘记上传这个云函数。 [图片] 出现下图就代表上传成功 [图片] 五、写一个简单的页面,用来提交订单,调用pay云函数。 [图片] 这个页面很简单: 1.自己随便编写一个订单号(这个订单号要大于6位) 2.自己随便填写一个订单价(单位是分) 3.点击按钮,调用pay云函数。获取支付所需参数。 下图是官方支付api所需要的一些必须参数。 [图片] 下图是我们调用pay云函数获取的参数,和上图所需要的是不是一样。 [图片] 六、调用wx.requestPayment实现支付 下图是官方的示例代码: [图片] 这里不在做具体讲解了,把完整代码给大家贴出来 [代码]// pages/pay/pay.js Page({ //提交订单 formSubmit: function(e) { let that = this; let formData = e.detail.value console.log('form发生了submit事件,携带数据为:', formData) wx.cloud.callFunction({ name: "pay", data: { orderid: "" + formData.orderid, money: formData.money }, success(res) { console.log("提交成功", res.result) that.pay(res.result) }, fail(res) { console.log("提交失败", res) } }) }, //实现小程序支付 pay(payData) { //官方标准的支付方法 wx.requestPayment({ timeStamp: payData.timeStamp, nonceStr: payData.nonceStr, package: payData.package, //统一下单接口返回的 prepay_id 格式如:prepay_id=*** signType: 'MD5', paySign: payData.paySign, //签名 success(res) { console.log("支付成功", res) }, fail(res) { console.log("支付失败", res) }, complete(res) { console.log("支付完成", res) } }) } }) [代码] 到这里,云开发实现小程序支付的功能就完整实现了。 实现效果 1.调起支付键盘 [图片] 2.支付完成 [图片] 3.log日志,可以看出不同支付状态的回调 [图片] 上图是支付成功的回调,我们可以在支付成功回调时,改变订单支付状态。 下图是支付失败的回调: [图片] 下图是支付完成的状态: [图片] 到这里我们就轻松的实现了微信小程序的支付功能了,是不是很简单啊。 源码地址: https://github.com/TencentCloudBase/Good-practice-tutorial-recommended 如果你有关于使用云开发CloudBase相关的技术故事/技术实战经验想要跟大家分享,欢迎留言联系我们哦~比心! [图片]
2019-08-15 - 使用小程序prepay_id调起支付页但未支付,prepay_id可以继续使用调起支付原订单吗?
使用小程序prepay_id调起支付页但未支付,prepay_id可以继续使用调起支付原订单吗?我们现在做的一个场景是用户需要把未支付的订单支付后才能继续下单,想知道后端怎么处理,是订单表存储prepay_id然后,下单前查表如果有未支付订单,就把该订单的prepay_id返回给用户吗 希望有人解答一下 谢谢
2022-11-08 - 微信支付统一下单后,未完成支付,关闭订单成功,再次调起统一下单接口,报商户订单号重复?
微信支付统一下单后,未完成支付,关闭订单成功,再次调起统一下单接口时(参数除随机字符有变动,其它不变),报商户订单号重复,因项目原因不能变更订单号,怎么处理才能用同一商户订单号继续发起支付?
2020-06-17 - 微信支付结果通知中return_code为FAIL时商户系统这边该如何处理?
当商户系统接收微信系统支付结果通知时,什么场景中return_code会是FAIl?为FAIL时,商户系统如何向微信服务端响应,是SUCCESS?还是FAIL? [图片]
2020-12-25 - 云函数怎样对微信支付回调通知解密?
将云函数开启http访问后收到了微信支付的回调通知,但收到内容(body)是一串字符串,看文档说是加密的信息,第一次做这个功能,请教下如何对这个加密内容进行解密,步骤是怎样的,文档中的这几步没有看懂。例如第二步中【针对resource.algorithm中描述的算法(目前为AEAD_AES_256_GCM),取得对应的参数nonce和associated_data】这是什么意思?resource.algorithm在哪里? 文档内容: [图片]
2022-12-19 - 【手把手喂饭】云开发微信支付教程
绑定商户号等等就不说了…… 基本步骤如下: 1、小程序端 调用云函数 2、云函数调用 cloud.cloudPay.unifiedOrder 获取支付参数,返回给 小程序 3、小程序拿到第二步的参数,调用 wx.requestPayment 调用微信支付 4、支付完成的回调 细节部分: 1、小程序端 调用云函数 这一步没啥好说的,给个我的参考: orderRes = orderInfo // 订单信息,我这里用的预先下订单,也可以支付后创建订单 orderData = {...} // 一些需要传递给云函数的数据,不存在也没有关系,因为我是预先创建订单,所以 后端获取订单,就能补充支付信息(如支付金额)了 http.callFunction('order',orderData) .then((res:any)=>{ const payment = res.result.payment wx.requestPayment({ // 这里是第3步的部分 ...payment, success () { // 支付成功 跳转什么的 }, fail (err:any) { console.error('pay fail', err) } }) }) 2 云函数部分: 这里有个小技巧,就是加个支付流水,这样可以做到订单支付失败后,重新进订单还能重新支付同一个订单,但是如果你上一步做的是支付完成后创建订单,则不需要这个步骤了。 const res = await cloud.cloudPay.unifiedOrder({ "body" : event.goodsName, "outTradeNo" : flowRes._id, "nonceStr":event.nonceStr, "spbillCreateIp" : "127.0.0.1", "subMchId" : "123", "totalFee" : order.totalPrice, "envId": "你自己的环境id", "functionName": "pay_callback", // 回调函数 "tradeType":"JSAPI" }) 3、第三步 就是 第一步 的回调里面的部分 不重复了…… 4、支付完成后回调: 修改一下订单为已支付即可……
2023-02-03 - 使用云函数+云调用,四步实现微信支付
微信支付是云开发原生支持的微信生态能力之一,开发者只需要简单调用相应的函数即可完成整套支付流程,安全又高效。部分优势包括: 无需关心证书、签名,支付流程简化;基于微信私有协议和私有链路,更加安全、高效;免运维,高可用性;按需扩容,弹性伸缩,按量计费,成本缩减;支持通过云函数接受支付回调,无需自建回调服务。流程对比:传统流程 vs 云开发[图片] 代码示例第 1 步:小程序调用云函数C 端用户发起支付流程后,小程序端调用云函数(此处假设云函数名为 [代码]makeOrder[代码]): // 小程序代码 wx.cloud.callFunction({ name: "makeOrder", data: { /* 开发者自定义参数 */ } }); 第 2 步:云函数生成订单,返回订单信息云函数 makeOrder 收到调用之后,使用微信服务端 SDK 提供的 API,无需证书和签名,可直接生成订单。 生成订单之后,利用 CloudPay.unifiedOrder() 统一下单接口,将订单信息返回给小程序。 CloudPay.unifiedOrder() 接口文档: https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/open/pay/CloudPay.unifiedOrder.html // 云函数 makeOrder const cloud = require("wx-server-sdk"); cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }); exports.main = async (event, context) => { const res = await cloud.cloudPay.unifiedOrder({ body: "小秋TIT店-超市", outTradeNo: "1217752501201407033233368018", spbillCreateIp: "127.0.0.1", subMchId: "1900009231", totalFee: 1, envId: "test-f0b102", functionName: "payCallback" // 支付回调的函数名 }); return res; }; 第 3 步:小程序端发起支付小程序端收到云函数返回的订单信息后,发起支付: // 小程序代码 wx.cloud.callFunction({ name: "makeOrder", data: { /* 开发者自定义参数 */ }, success: (res) => { // 取得云函数返回的订单信息 const payment = res.result.payment; // 调起微信客户端支付 wx.requestPayment({ ...payment, success(res) { /* 成功回调 */ }, fail(res) { /* 失败回调 */ } }); } }); 第 4 步:使用云函数接收支付回调,完成支付流程用户完成付款之后,微信后台将会调用指定的云函数(此处假设名为 payCallback),传入的参数中会带有订单信息。 开发者可以在此云函数中,实现自己的发货、完成订单的逻辑。 // 云函数 payCallback exports.main = async (event, context) => { const { return_code, // 状态码 appid, // 小程序 AppID mch_id, // 微信支付的商户号 device_info, // 微信支付分配的终端设备号 openid, // 用户在商户appid下的唯一标识 trade_type, // 交易类型:JSAPI、NATIVE、APP bank_type // 银行类型 // ...... // 更多参数请参考:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7&index=8 } = event; /* 开发者自己的逻辑 */ // 向微信后台返回成功,否则微信后台将会重复调用此函数 return { errcode: 0 }; }; 相关文档:云函数文档: https://docs.cloudbase.net/cloud-function/introduce.html 云调用文档: https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/openapi/openapi.html wx-server-sdk 文档: https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/Cloud.html CloudPay.unifiedOrder() 接口文档: https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/open/pay/CloudPay.unifiedOrder.html
2021-07-08 - 不用开发工具,云开发动态激活关闭触发器。
一、业务场景如图: [图片] 当关闭定时器时,云开发自动删除定时器,云函数停止按时执行; 二、小程序端代码 onTriggerSwitchChanged: function (e) { wx.cloud.callFunction({ name: 'timer', data: { action: e.detail.value ? 'on' : 'off' //打开和关闭定时器 } }) }, 三、云函数timer代码 代码直接复制可用。 const CloudBase = require('@cloudbase/manager-node') const cloud = require('wx-server-sdk') cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) exports.main = async (event, context) => { if (event.action == 'on') return await triggerOn() //打开定时器 if (event.action == 'off') return await triggerOff() await onTrigger() //定时器触发时处理流程 } async function triggerOn() { const tcb = new CloudBase({ envId: cloud.getWXContext().ENV }) return await tcb.functions.createFunctionTriggers("timer", [ { "name": "myTrigger", "type": "timer", "config": "0 */10 * * * * *"//每10分钟触发一次 } ]) } async function triggerOff() { const tcb = new CloudBase({ envId: cloud.getWXContext().ENV }) return await tcb.functions.deleteFunctionTrigger("timer", 'myTrigger') } async function onTrigger() {} 参考文档:https://docs.cloudbase.net/api-reference/manager/node/introduction 四、结束。
2023-03-03 - 小程序中如何加载使用第三方字体
简述:使用开启CORS的woff字体格式(或ttf)的https资源地址,使用[代码]wx.loadFontFace[代码] API(css原生[代码]@font-face[代码]语法)加载使用。 ⚠️ 注意:字体商用需授权许可,目前免费可商用的大部分字体,可见参考索引5。以下示例使用的是开源字体:得意黑和钉钉进步体。 1. wx.loadFontFace使用wx.loadFontFace 加载字体,配合wxss和wxml使用,参见文档 & 官方示例 // -- wxss -- // .DingTalk-JinBuTi { // font-family: 'DingTalk-JinBuTi'; // } wx.loadFontFace({ family: 'DingTalk-JinBuTi', source: 'url("https://xxx/font/DingTalk-JinBuTi.woff")', //此处需替换为真实字体地址 success(res) { console.log(res.status) }, fail: function (res) { console.log(res.status) }, complete: function (res) { console.log(res.status) } }); 注意: 格式支持常见的基本所有类型(ttf、woff、woff2(web主流)、otf、sfnt),建议格式为 TTF 和 WOFF(推荐),WOFF2 在低版本的 iOS 上会不兼容。字体链接仅支持https链接字体链接访问需满足浏览器同源策略,字体文件资源设置CORS的[代码]Access-Control-Allow-Origin[代码]为小程序域名:[代码]servicewechat.com[代码]或者*才可以。经过测试,ios和小米手机对于未设置CORS的字体文件仍然可以正常加载,荣耀和vivo无法正常加载,需要设置正确的CORS即可正常加载在加载成功之后,会自动刷新字体显示不需要设置downloadFile合法域名及业务域名。扩展:一次加载,全局使用如下在app.js中加载添加全局参数(global: true),即可在任意页面中的font-family中使用该字体。 onLaunch() { wx.loadFontFace({ family: 'DingTalk-JinBuTi', global: true, source: 'url("https://xxx/font/DingTalk-JinBuTi.woff")', //此处需替换为真实字体地址 success(res) { console.log(res.status) }, fail: function (res) { console.log(res.status) }, complete: function (res) { console.log(res.status) } }); }, 2. @font-face同css加载字体的规则,见MDN文档, 注意:字体链接访问需满足浏览器同源策略。支持常见格式。 @font-face { font-family: "SmileySans-Oblique"; src: url("https://xxx/font/SmileySans-Oblique.woff"); //此处需替换为真实字体地址 } .SmileySans-Oblique { font-family: 'SmileySans-Oblique'; } 扩展:全局使用在app.wxss中引入字体即可全局使用。 @font-face { font-family: "SmileySans-Oblique"; src: url("https://xxx/font/SmileySans-Oblique.woff"); //此处需替换为真实字体地址 } .SmileySans-Oblique { font-family: 'SmileySans-Oblique'; } 3. face-font base64 因源码过大致小程序增加包体积,暂不考虑。英文字体可以考虑。参见此。 扩展:在canvas中使用小程序canvas渲染时需要字体加载完成,css方式字体加载完成不容易监听,小程序文档提到可使用wx.loadFontFaced的回调中渲染canvas。参考文档及代码示例。 另外wxml-to-canvas中不支持font-family属性,可参考链接4修改源码实现。 参考wx.loadFontFace(Object object) | 微信开放文档微信小程序使用自定义字体的三种方法 - 掘金loadFontFace 支持全局生效 | 微信开放社区wxml-to-canvas没有fontWeight的相关支持? | 微信开放社区光明正大用字体——2023年“不要钱”的字体集合!哔哩哔哩bilibili[图片]
2023-03-21 - 小程序能生成邀请好友的二维码吗?
想让用户 生成带参数的推广二维码,求大神支招
2019-11-24 - 微信小程序图片裁剪工具we-cropper
[图片]扫码查看效果
2018-01-18 - 节流与防抖分享
常用函数 2个 不废话 直接上 代码: /** * 节流原理:在一定时间内,只能触发一次 * * @param {Function} func 要执行的回调函数 * @param {Number} wait 延时的时间 * @param {Boolean} immediate 是否立即执行 * @return null */ let timer, flag; function throttle(func, wait = 500, immediate = true) { if (immediate) { if (!flag) { flag = true; // 如果是立即执行,则在wait毫秒内开始时执行 typeof func === 'function' && func(); timer = setTimeout(() => { flag = false; }, wait); } } else { if (!flag) { flag = true // 如果是非立即执行,则在wait毫秒内的结束处执行 timer = setTimeout(() => { flag = false typeof func === 'function' && func(); }, wait); } } }; /** * 防抖原理:一定时间内,只有最后一次操作,再过wait毫秒后才执行函数 * * @param {Function} func 要执行的回调函数 * @param {Number} wait 延时的时间 * @param {Boolean} immediate 是否立即执行 * @return null */ let timeout = null; function debounce(func, wait = 500, immediate = false) { // 清除定时器 if (timeout !== null) clearTimeout(timeout); // 立即执行,此类情况一般用不到 if (immediate) { var callNow = !timeout; timeout = setTimeout(function() { timeout = null; }, wait); if (callNow) typeof func === 'function' && func(); } else { // 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法 timeout = setTimeout(function() { typeof func === 'function' && func(); }, wait); } } 常用函数 2个 不废话 直接上 代码: /** * 节流原理:在一定时间内,只能触发一次 * * @param {Function} func 要执行的回调函数 * @param {Number} wait 延时的时间 * @param {Boolean} immediate 是否立即执行 * @return null */ let timer, flag; function throttle(func, wait = 500, immediate = true) { if (immediate) { if (!flag) { flag = true; // 如果是立即执行,则在wait毫秒内开始时执行 typeof func === 'function' && func(); timer = setTimeout(() => { flag = false; }, wait); } } else { if (!flag) { flag = true // 如果是非立即执行,则在wait毫秒内的结束处执行 timer = setTimeout(() => { flag = false typeof func === 'function' && func(); }, wait); } } }; /** * 防抖原理:一定时间内,只有最后一次操作,再过wait毫秒后才执行函数 * * @param {Function} func 要执行的回调函数 * @param {Number} wait 延时的时间 * @param {Boolean} immediate 是否立即执行 * @return null */ let timeout = null; function debounce(func, wait = 500, immediate = false) { // 清除定时器 if (timeout !== null) clearTimeout(timeout); // 立即执行,此类情况一般用不到 if (immediate) { var callNow = !timeout; timeout = setTimeout(function() { timeout = null; }, wait); if (callNow) typeof func === 'function' && func(); } else { // 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法 timeout = setTimeout(function() { typeof func === 'function' && func(); }, wait); } }
2022-12-04 - 图片按住一角怎么实现缩放、旋转、拖拽
想实现多个图片操作都可以缩放旋转拖拽 缩放可以按住一角来实现 不知道怎么实现了 利用movable-view、movable-area 可以实现拖拽缩放、不好旋转 得记录所有的图片位置,角度 是不是可以利用canvas绘图计算手指移动的位置角度 但是要是多张图片重叠在一起 想删除一张图 原生的api貌似不能实现, 肯定是删除一个区域的数据 ,而不是删掉某一层的数据 . 不知道有么有啥框架来实现,cocos2d-h5游戏都是canvas绘图都可以 小程序应该也可以的, 或者move-view设置好后, 生成图片的 时候用canvas再绘制一遍 感觉好麻烦,不知道有没有好的方法 不过我这要绘制的图片有点多 , 看到社区QA已知问题里有个 “canvas的drawImage性能变差,频繁调动会出现卡顿” 有大神给个思路么
2018-03-30 - 5行代码获取小程序用户手机号
最近有很多同学有获取小程序用户手机号的需求。其实云开发出现之前我们获取小程序用户的手机号特别繁琐。自从有了云开发,我们获取用户手机号变得非常简单。只需要5行代码即可。 老规矩,我们先来看下效果图 [图片] 再来看下核心的代码,其实只有下面这一些。 [图片] 甚至可以说核心代码只有上图红色框里的两行。是的,你没听错,只靠这2行代码,就可以轻松的获取用户小程序绑定的手机号。 下面我们就来具体讲解吧。 注意:只有企业小程序才可以获取用户手机号,个人小程序没有办法获取的。 一,首先要用到button组件的开发能力 [图片] 编写wxml文件,代码很简单 [图片] 可以看到我们的button按钮,使用了open-type。 再来看下我们对应的js方法。这样我们点击按钮时,就会弹出授权弹窗。如下图 [图片] 不管用户点击拒绝还是允许,我们都能拿到对应的回调。再用户点击了允许以后,就可以获取到以下数据。 [图片] 大家看到我们获取的数据里有一个cloudID,其实这个值很有用的。 二,开发数据检验与解密 1,首先我们看下官方提供的获取手机号的文档。 [图片] 看官方文档,可以知道,我们这里涉及到一个数据的检验与解密问题 2,开发数据检验与解密 [图片] 这里我们要使用的就是方式二,使用云函数来实现解密,然后拿到用户的手机号。 三,云函数的编写 [图片] 通过上图可以看到,我们编写的云函数很简单。这里主要用的就是cloud.getOpenData这个功能。而这个功能需要的参数就是我们上面第一步获取的cloudID [图片] 这样我们调用云函数的时候,只需要把对应的cloudID传进来即可。 [图片] 看下我们的cloudID的作用,再来看下我们通过button的open-type获取的cloudID [图片] 可以看出,我们的cloudID和encryptedData一样,是一串加密数据。我们要通过云函数获取手机号,需要的就是这串加密字段。 四,上传cloudID获取手机号。 上面第三步云函数编写好以后,我们就可以来调用了。调用之前一定要记得部署下云函数,一定要记得部署下云函数。。。。 [图片] 上图就是我们的云函数的调用。如果你对云开发和云函数还不了解,建议你去看下我之前写的云开发相关的文章,获取看下我录的《微信小程序云开发云函数入门》 这时候点击按钮,我们就可以获取到了我们所需要的手机号了 [图片] 到这里我们就可以轻松的通过云开发获取用户的手机号了,比起传统的后台开发来获取,是不是简单了很多。 今天就讲到这里了,后面我还会写更多小程序相关的技术文章出来,请持续关注。
2019-12-16