个人案例
- 朗月传媒工作室
这是一款商城小程序,主要展示和宣传工作室业务。
朗月传媒工作室扫码体验
- 公众号注册提示“邮箱已被占用”该怎么办?
1、公众号注册提示“该邮箱已被占用,请更换其他邮箱” 请检查核实您所输入的邮箱是否绑定以下其中一种帐号: 1)已绑定开放平台的邮箱; 2)已绑定个人微信的邮箱; 3)已绑定企业号的邮箱; 4)已绑定订阅号、服务号的邮箱; 5)已绑定小程序的邮箱。 注:同一个邮箱只能绑定微信产品的一种帐号,您可以尝试解绑或修改绑定的邮箱后再用于注册。 [图片] 2、公众号注册提示“该邮箱已被占用”,找回密码却提示“您输入的邮箱未注册” 若邮箱绑定的是微信其他产品未绑定公众号,那么无法通过公众号找回密码入口操作,您可以尝试解绑或修改绑定的邮箱后再用于注册。 [图片]
2020-03-18 - 小程序webview访问公众号文章提示非业务域名
排查方式如下 1:小程序和公众号需要进行绑定 2:需要是https请求 3:业务域名设置了不一定参数里就是业务域名的地址,若配置的基本都是公众号文章地址,这里的业务域名是不需要额外设置的 4:参数需要进行encode编码 分享案例 1:若遇到非业务域名问题,请先固定一篇文章进行测试,打印代码 https://mp.weixin.qq.com/s?__biz=xxxxxxxxxx==&mid=xxxxxxxxxx&idx=1&sn=xxxxxxxxxxxx&chksm=c0457762f732fe745f1bf8b1f99fa7a535335772eb6a104c1cf026ea063e16ec157465894b52&token=246279511&lang=zh_CN#rd 2:打开代码片段,放入打印出来的代码,编译查看是否提示参数错误 [图片] 3:把打印出来的代码进行encodeURIComponent转码 https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzkwMDE4MzU5OQ%3D%3D%26mid%3D2247504930%26idx%3D1%26sn%3D8d98cf8616cf11134620508082bdf1eb%26chksm%3Dc0457762f732fe745f1bf8b1f99fa7axxxxxxxxxeb6a104c1cf026ea063e16ec157465894b52%26token%xxxxxxxxxxxxx%26lang%3Dzh_CN%23rd 4:开发者工具-->添加编译模式-->启动参数-->url=encodeURIComponent转码后的请求,然后编译下 [图片] 附上事例中的代码片段:https://developers.weixin.qq.com/s/CdlD8vmP7AxR 欢迎社区开发者留下自己解决非业务域名报错的步骤 !!!
2022-03-04 - 公众帐号无法被搜索到是什么原因?
你好,公众号搜索建议你通过搜一搜—>公众号,搜一搜tab标签页公众号区域进行搜索,若无法搜索到,请你参考以下几种情况: 1、修改公众号名称,简介无法被搜索到 若公众号帐号修改名称和简介,在审核在此期间,建议你将微信公众号帐号的二维码保存在电脑本地后,通过可过微博、空间、网 站等途径进行推广,让更多的粉丝关注你,与粉丝进行更多的互动。 温馨提醒:修改帐号昵称简介等,会动态影响搜索的相关排序,建议稍后重试。 2、是否在公众号后台设置了禁止被搜索? 若微信公众号帐号昵称无法被搜索到,建议你查看是否设置了禁止被搜索,请你通过以下方法查看和设置; 设置方法:登录微信公众微信平台->设置->帐号信息->隐私设置->允许。 温馨提示: 1)设置禁止用户通过昵称搜到该帐号后,粉丝通过ID和二维码可以搜到该帐号。(搜索公众号一栏,默认是搜索原始ID,如果已设置了微信号,原始ID会被微信号取代) 2)设置设置成功,半小时后即可生效。 [图片] 3、帐号信息登记审核中、未审核通过、封号、冻结、注销等 若你的微信公众号信息登记审核中/未审核通过、公众号违规被封/冻结、或公众号被注销时,他人在手机微信->搜一搜->“搜索公众号名称”或“搜索公众号微信号”,是无法搜索到你的公众号帐号。 4、公众号不在搜一搜全部中展示 你好,搜一搜的入口是可以搜到属于正常的,这个不属于搜不到的范围。关于公众号的搜索问题,我们会通盘考虑公众号运营者和微信搜索用户的搜索需求与使用习惯。大致的排序原则:排序结果受公众号的运营时间,运营频率,历史违规行为,搜索用户的使用行为反馈,搜索关键词的匹配程度等因素共同决定的,请运营者坚持运营,我们相信优质的公众号一定会受到用户的喜爱脱颖而出的。 5、在搜一搜公众号模糊搜索不一定搜得到 你好,公众号召回都是以账号名称、内容和简介为主要依据的,我们会通盘考虑公众号运营者和微信搜索用户的搜索需求与使用习惯。因帐号运营质量过低,无法被召回,建议提高公众号的运营质量 6、通过微信搜公众号昵称的逻辑 微信根据用户搜索习惯及公众号质量等信息进行算法排序,暂时无法手动干预。请你以微信页面的实际展示为准,感谢你对微信的支持。 可通过以下两种搜索公众号的方法: 1)通过微信“查找”功能,通过昵称搜索,未认证的公众号和已认证的公众号都可通过昵称搜索到。 2)通过搜一搜,通过昵称搜索和微信号,点击标签页中公众号区域。未认证的公众号和已认证的公众号都可通过昵称搜索到。 温馨提示:注册成功后,手机端最迟48小时内便可搜索到新注册的公众帐号。 [图片] [图片]
2021-06-04 - 微信网页授权能力调整公告
微信网页授权 能力是为了优化用户在微信内登录网站应用的体验而设计的。为进一步规范能力使用,保障用户合法权益,平台将对能力进行调整。 当开发者在网页中在不规范使用发起 snsapi_userinfo 网页授权时,微信将默认打开网页快照页模式进行基础浏览。能力调整将于 2022 年 7 月 12 日 24 时生效。 网页快照页模式介绍快照页将会默认对用户屏蔽网页授权弹窗,用户在快照页中仅可进行滑动浏览操作,其他交互将被限制,并提示用户 “该网页需获取个人信息才可使用完整服务,当前仅可浏览部分内容”。用户如需要使用完整网页服务,可轻触右下角 “使用完整服务” 按钮触发授权弹窗,用户确认后进入原网页。 开发者在快照页内所获取的头像、昵称、openId、unionId 均为虚拟账号数据;快照页与正常页面不共用缓存,快照页的缓存会在用户离开快照页时被清理;快照页内也无法使用微信其它 JS-SDK 的能力。 [图片] 微信网页授权规范授权流程需引导清晰、准确:在申请获取用户信息的弹窗出现前,应该清晰、准确地告知用户获取信息的范围及获取信息的目的;必要场景申请:在必须获取用户信息时才申请,而不是用户尚未了解服务前就强制弹窗。如使用医院挂号时才需要获取用户信息;不强制登录:提供游客模式,供用户了解网页提供的基础服务,不强制用户允许网页获取用户信息后才能使用网页服务。 常见的微信网页授权不规范使用案例强制登录:在用户打开网页时立即要求用户授权,用户拒绝后无法使用网页提供的服务;违规收集个人信息:未在网页提前告知使用个人信息的目的、方式和范围;非必要收集:非必要获取用户信息的网页,如文章、视频等,要求用户在浏览内容前登录;差别对待微信用户:同样的网页在浏览器内可以无需登录直接访问,在微信内却要求用户先登录才可访问。 微信团队 2022年5月9日
2022-05-10 - 找回帐号提示“帐号异常,不支持找回,请联系腾讯客服”
你好,该帐号可支持线下找回,提交问题时需要提供出现问题页面截图 线下找回: 一、企业、个体户,需要通过提交工单申请: 工单所需材料: 1、公众号(邮箱或ID): 2、注册时提供的营业执照: 3、法人资料(法人身份证正反面照片): 4、需要绑定的新邮箱(未绑定个人微信/公众平台的邮箱): 5、申请找回帐号的书面说明(需填写申请原因、及加盖主体公章): 附注:申请找回帐号的书面说明模板(https://file.service.qq.com/user-files/uploads/201804/9ec0f6abc272215445158f439875b52a.jpg ) 准备好材料后打开找回帐号网址QQ扫码提供材料(复制链接到浏览器上打开:https://kf.qq.com/bills/170922selfsam1e2e932.html) [图片]
2022-01-18 - 微信人脸核身接口能力
一、能力背景 近年来,国家在医疗挂号、APP注册、快递收寄、客运、运营商等多领域规定,需要用户实名才可办理业务,预计后续也会有越来越多的此类法规。因此,微信参照公安部“互联网+”可信身份认证服务平台标准,依托腾讯公司及微信的生物识别技术,建立微信“实名实人信息校验能力” ,即通过人脸识别+权威源比对,校验用户实名信息和本人操作(简称微信人脸核身)。 目前接口限定主体及行业类目开放公测,提供给资质符合要求的业务方,在合适的业务场景内使用。目前仅支持持二代身份证的大陆居民。 由于人脸核身功能涉及到用户的敏感、隐私信息,因此调用此接口的小程序,需要满足一定的条件。即:小程序的主体以及类目,需要在限定的类目范围内,且与小程序的业务场景一致。开展的业务也需要是国家相关法规、政策规定的需要“实名办理”的相关业务(其他未在范围内的业务,则暂不支持)。 以下为接口接入及开发的详细内容。如开发中遇到任何疑问,可以点击此处通过社区反馈,将有工作人员跟进回复。 文档第四部分【再次获取核验结果api】,有助于提高业务方安全性,请务必接入! 现阶段微信人脸核验能力,针对小程序,开放的主体类目范围包含: 小程序一级类目 小程序二级类目 小程序三级类目 使用人脸核验接口所需资质 物流服务 收件/派件 / 《快递业务经营许可证》 物流服务 货物运输 / 《道路运输经营许可证》(经营范围需含网络货运) 教育 学历教育(学校) / (2选1):1、公立学校:由教育行政部门出具的审批设立证明 或 《事业单位法人证书》;2、私立学校:《民办学校办学许可证》与《民办非企业单位登记证书》 医疗 公立医疗机构 / 《医疗机构执业许可证》与《事业单位法人证书》 医疗 互联网医院 / 仅支持公立医疗机构互联网医院(2选1):1、卫生健康部门的《设置医疗机构批准书》;2、 《医疗机构执业许可证》(范围均需含“互联网诊疗”或名称含“互联网医院”等相关内容 医疗服务 三级私立医疗机构 / 仅支持三级以上私立医疗机构,提供《医疗机构执业许可证》、《营业执照》及《医院等级证书》 政务民生 所有二级类目 / 仅支持政府/事业单位,提供《组织机构代码证》或《统一社会信用代码证》。 金融业 银行 / (2选1):1、《金融许可证》; 2、《金融机构许可证》。 金融业 信托 / (2选1):1、《金融许可证》; 2、《金融机构许可证》。 金融业 公募基金 / (4选1):1、《经营证券期货业务许可证》且业务范围必须包含“基金”;2、《基金托管业务许可证》; 3、《基金销售业务资格证书》;4、《基金管理资格证书》。 金融业 证券/期货 / 《经营证券期货业务许可证》 金融业 保险 / (8选1):1、《保险公司法人许可证》;2、《经营保险业务许可证》;3、《保险营销服务许可证》;4、《保险中介许可证》;5、《经营保险经纪业务许可证》;6、《经营保险公估业务许可证》或《经营保险公估业务备案》;7、《经营保险资产管理业务许可证》 ;8、《保险兼业代理业务许可证》。 金融业 消费金融 / 银监会核准开业的审批文件与《金融许可证》与《营业执照》 金融业 汽车金融/金融租赁 / 仅支持汽车金融/金融租赁主体,同时提供:1、《营业执照》(公司名称包含“汽车金融” /“金融租赁”;营业范围包含“汽车金融”/“金融租赁”业务);2、《金融许可证》或银保监会及其派出机构颁发的开业核准批复文件。 交通服务 网约车 快车/专车/其他网约车 (自营性网约车)提供《网络预约出租汽车经营许可证》。(网约车平台)提供与网约车公司的合作协议以及合作网约车公司的《网络预约出租汽车经营许可证》。 交通服务 航空 / (航司)提供《公共航空运输企业经营许可证》。(机场)提供《民用机场使用许可证》或《运输机场使用许可证》。 交通服务 公交/地铁 / 提供公交/地铁/交通卡公司《营业执照》 交通服务 水运 / (船企)提供《水路运输许可证》。(港口)提供《港口经营许可证》 交通服务 骑车 / 仅支持共享单车,提供共享单车公司《营业执照》 交通服务 火车/高铁/动车 / 仅支持铁路局/公司官方,提供铁路局/公司《营业执照》 交通服务 长途汽车 / (2选1):1、《道路运输经营许可证》(经营范围需含客运);2、官方指定联网售票平台(授权或协议或公开可查询文件)。 交通服务 租车 / 运营公司提供《备案证明》与对应公司《营业执照》,且营业执照中包含汽车租赁业务 交通服务 高速服务 / 仅支持ETC发行业务,(2选1):1、事业单位主体,需提供《事业单位法人证书》;2、官方指定的发行单位(一发单位),需提供“官方授权或协议,或公开可查询的文件”; 生活服务 生活缴费 / (供电类)提供《电力业务许可证》与《营业执照》,且《营业执照》且经营范围含供电。(燃气类)提供《燃气经营许可证》与《营业执照》,且《营业执照》且经营范围含供气。(供水类)提供《卫生许可证》与《营业执照》。(供热类)提供《供热经营许可证》与《营业执照》,且《营业执照》且经营范围含供热。 IT科技 基础电信运营商 / (2选1):1、基础电信运营商:提供《基础电信业务经营许可证》;2、运营商分/子公司:提供营业执照(含相关业务范围)。 IT科技 转售移动通信 / 仅支持虚拟运营商,提供《增值电信业务许可证》(业务种类需含通过转售方式提供移动通信业务) 旅游服务 住宿服务 / 仅支持酒店,提供《酒店业特种行业经营许可证》 商业服务 公证 / 仅支持公证处,提供《公证处执业许可证》或《事业单位法人证书》 社交 直播 / (2选1):1、《信息网络传播视听节目许可证》;2、《网络文化经营许可证》(经营范围含网络表演)。 如对以上类目或资质有疑问,可点击参考小程序“非个人主体开放的服务类目”,详细了解小程序开放的服务类目及对应资质。 二、准备接入 (请在小程序发布后,再提交人脸核身接口申请) 满足第一节中描述的类目和主体的小程序,可申请微信人脸核验接口。目前微信人脸核身接口已改为线上自助申请方式,需按照如下图例指引,进行接口申请: 第一步:请通过mp.weixin.qq.com登录小程序账号在后台“功能-人脸核身”的路径,点击开通按钮—— [图片] 第二步:仔细查阅《人脸识别身份信息验证服务条款》后,点击“同意并下一步”—— [图片] 第三步:请正确填写服务信息,并上传该小程序类目下所要求的资质—— [图片] 第四步:请按照业务实际需求填写使用人脸接口的场景和用途—— [图片] 第五步:请完善测试信息和联系人—— [图片] 第六步:提交后请耐心等待1-3个工作日的审核期,审核结果将以站内信通知—— 如申请期间遇到问题,可联系腾讯工作邮箱 wx_city@tencent.com,将会有相关工作人员进一步指引。 三、接口文档: (一)接口描述 名称: wx.startFacialRecognitionVerify(OBJECT) 功能:请求进行基于生物识别的人脸核身 验证方式:在线验证 兼容版本: 一闪:android 微信7.0.22以上版本, iOS 微信7.0.18以上版本 建议在微信官网升级至最新版本 (二)参数说明 1、OBJECT参数说明: 参数 类型 必填 说明 name String 是 姓名 idCardNumber String 是 身份证号码 success Function 否 调用成功回调 fail Function 否 调用失败回调 complete Function 是 调用完成回调(成功或失败都会回调) 2、CALLBACK返回参数 参数 类型 说明 errMsg String 错误信息 errCode Number 错误码 verifyResult String 本次认证结果凭据,第三方可以选择根据这个凭据获取相关信息 注 1:传递用户姓名和身份证有两种方式 业务方没有用户实名信息,用户需要在前端填写身份证和姓名,那么前端直接通过jsapi 调用传递 name 和 idCardNumber。 业务方已经有用户实名信息,后台通过微信提供的 api(详情见文档后面“上传姓名身份证后台 api”)上传用户身份证姓名和身份证,api 返回 user_id_key 作为凭证传给前端,前端再调用 jsapi,用户姓名、身份证信息不需要经过前端,参数只需要传递 userIdKey。Tips:使用该功能需要小程序基础库版本号>=1.9.3。 3、回调结果说明 回调结果请参考以下释义: [图片] [图片] [图片] 4、示例代码 [图片] [图片] (三)上传用户姓名身份证的后台api 1、API说明 1.1说明 业务方上传用户姓名和身份证,获取用户凭证,把凭证给到前端通过 jsapi 调用。 Tips :使用该功能需要小程序基础库版本号>=1.9.3。 1.2请求URL https://api.weixin.qq.com/cityservice/face/identify/getuseridkey?access_token={ac cess_token} 1.3请求方式 POST 2、请求数据格式 [代码]Json { "name" : “张三”, "id_card_number" : "452122xxxxxxx43215" } [代码] 请求示例 [代码]#!/bin/bash TOKEN='xxxxxxxxxxxx' URL='https://api.weixin.qq.com/cityservice/face/identify/getuseridkey' JSON='{ "name": "张三", "id_card_number": "452344xxxxxxxxxxxxx234"}' curl "${URL}?access_token=${TOKEN}" -d "${JSON}" [代码] 参数说明 json 字段 中文显示 是否必传 name 姓名 是 id_card_number 身份证号码 是 out_seq_no 业务方唯一流水号 否 3、返回数据 参数 类 型 说明 errcode int 错误码 errmsg string 错误信息 user_id_key string 用于后台交互表示用户姓名、身份证的凭证 expires_in uint32 user_id_key 有效期,过期需重新获取 [代码]{ "errcode" : 0, "errmsg" : "ok", "user_id_key" : "id_key_xxxx", "expires_in": 3600 } [代码] 4、后台消息推送 如果业务方传入out_seq_no,核身完成后会通过消息推送回调给业务方的服务器,如果回调业务方失败,会在5s尽力推送,超过5s不再推送。 参数说明 参数 类 型 说明 ToUserName string 小程序原始ID FromUserName string 事件消息openid CreateTime uint32 消息推送时间 MsgType string 消息类型 Event string 事件类型 openid string 核身用户的openid out_seq_no string 业务方唯一流水号 verify_result string 核身返回的加密key(凭据) 返回示例 [代码]{ "ToUserName": "gh_81fxxxxxxxx", "FromUserName": "oRRn15NUibBxxxxxxxxx", "CreateTime": 1703657835, "MsgType": "event", "Event": "face_identify", "openid": "oRRn15NUibBxxxxxxxxx", "out_seq_no": "test1234", "verify_result": "XXIzTtMqCxwOaawoE91-VNGAC3v1j9MP-5fZJxv0fYT4aGezzvYlUb-n6RWQa7XeJpQo0teKj8mGE4ZcRe1JI3GqzADBYORBu613rKjKAFfEXTXw_bu1bs7MnmPOpguS" } [代码] 四、再次获取核验结果api 此接口是前端完成人脸核身后,基于前端返回的凭据,通过后台api再次进行核验结果和身份信息的校验,有助于提高安全性,请务必接入! 前端获取结果不可信,存在被篡改的风险,为了保障请求结果安全性,请务必对identify_ret、id_card_number_md5、name_utf8_md5字段进行校验! (一)API说明 1、说明 人脸核身之后,开发者可以根据jsapi返回的verify_result向后台拉取当次认证的结果信息。 2、请求URL https://api.weixin.qq.com/cityservice/face/identify/getinfo?access_token={access_token} 3、请求方式 POST 4、请求格式 json (二)请求数据说明 1、请求 参数 类型 是否必填 描述 verify_result String 是 jsapi返回的加密key(凭据) 2、数据返回 HTTP 头如下 Date: Mon, 06 Feb 2017 08:12:58 GMT Content-Type: application/json; encoding=utf-8 Content-Length: 85 Connection: close json示例 [代码]{ "errcode" : 0, [代码] [代码]"errmsg" : "ok", "identify_ret" : 0, "identify_time" : 1486350357 "validate_data": "8593" [代码] [图片] (三)返回参数说明 1、返回参数 注:errcode和identify_ret同时为0,代表本次认证成功。 参数 类型 描述 errcode int 错误码, 0表示本次api调用成功 errmsg string 本次api调用的错误信息 identify_ret int 人脸核身最终认证结果 identify_time uint32 认证时间 validate_data string 用户读的数字(如是读数字) openid string 用户openid user_id_key string 用于后台交互表示用户姓名、身份证的凭证 finish_time uint32 认证结束时间 id_card_number_md5 string 身份证号的md5(最后一位X为大写) name_utf8_md5 string 姓名MD5 2、错误码对应信息 errcode 备注 84001 非法identity_id 84002 用户信息过期 84003 用户信息不存在 五、小程序辅助接口:检查设备是否支持人脸检测 1、接口名称 接 口 :wx.checkIsSupportFacialRecognition(OBJECT) 功能:检查设备是否支持人脸检测 2、接口说明和使用 小程序调用该接口,可以检测当前手机设备是否具备支持人脸检测的能力,可与以上接口分开使用,为了用户体验,建议调用后对手机设备不支持的用户做对应功能处理。 3、接口说明和使用 01 OBJECT 参数说明: 参数 类型 是否必填 描述 success Function 否 调用成功回调 fail Function 否 调用失败回调 complete Function 是 调用完成回调(成功或失败都会回调) checkAliveType Number 否 人脸核验的交互方式,默认读数字(见表 2) 表 2:checkAliveType 的值和对应的解释: 参数 解释 2 先检查是否可以屏幕闪烁,不可以则自动为读数字 02 CALLBACK 返回参数 参数 类型 说明 errMsg Boolean 错误信息 errCode Number 错误码 03 回调结果说明 回调类型 ErrCode 说明 sucess 0 支持人脸采集 fail 10001 不支持人脸采集:设备没有前置摄像头 fail 10002 不支持人脸采集:没有下载到必要模型 fail 10003 不支持人脸采集:后台控制不支持 回调结果说明仅对Android生效,iOS不返回errcode。 04 示例代码 [图片] 六、安全性说明 为保障业务可用性以及安全性,请详细研读微信人脸核身接口相关基础说明及安全说明文档:https://docs.qq.com/doc/DTFB0YWFIdGV6amly 备注:如开发中遇到任何疑问,可以点击此处通过社区反馈,将有工作人员跟进回复。 七、案例展示及补充说明 安徽医科大学第二附属医院,微信人脸核验登录: 安徽医科大学第二附属医院,是三级甲等综合医院。其小程序为用户提供挂号、门诊费用、住院费用、检查报告、体检等医疗服务,同时也提供停车、餐饮等便民服务,是医疗小程序中完整的案例。 小程序使用了微信人脸核验能力作为登录的核验。满足医院管理要求,也满足国家对于实名就医的管理规则。 案例实现的截图效果如下: [图片] [图片] 针对近期少数小程序方面反馈的两类问题,也在本课程进行补充说明。 1、本接口的开放范围,即:可支持的主体类目,是否可以扩大? 说明:基于本接口整体使用范围的评估、相关法规的参考、监管策略的理解执行等,暂时未立刻进行扩大开放范围的工作。 但我们会持续基于不同行业的法规、政策及监管要求等,逐一进行研究考量,以便确认如何扩大开放范围。 2、小程序如果涉及用户本人的生物特征采集,(如本人人脸照片、人脸视频),或涉及采集用户本人生物特征信息并开展人脸核验功能,则存在被驳回的情况? 说明:近两年“人脸识别”技术在社会上掀起了热潮。人脸识别虽然作为摆脱“中间媒介”或“承载载体”的一种直接技术手段,解决了部分政务、交通、医疗、零售等证明“操作者是本人”的问题,但也因此,引入了新的更大的安全风险。 一是,虚假安全风险。 身份认证领域的安全三因素包括“我知道什么”、“我拥有什么”、“我的特征是什么”,通用的安全做法,是要双因素认证(2FA),人脸识别技术如仅凭“我的特征是什么”这一个因素,则容易被攻破或利用。表象给用户以安全的感觉,但实际并不能达到安全效果。 二是,信息泄漏的风险。 越来越多的组织或个人,在并非必需用户敏感信息、生物特征的情况下,采集并存储此类信息。在信息加密、传输、存储过程中,容易暴漏更多的网络节点,使得此类信息有更大的风险被网络黑客拦截、窃听、窃取,或直接被脱库。 三是,消除风险的难度大。 以往基于“中间媒介”或“承载载体”的方式,如出现丢失、被冒用、恶意盗用等风险,可以通过挂失、更换、使用新载体或新媒介等方式,快速排除一定的风险。C端主动,B端主动,都能解决一部分问题。但人脸识别做为更直接的方式,一旦出现冒用、盗用,受害者将面临更大的财产及人生安全风险,且C端用户更多时候无法主动消除风险。 基于以上问题风险,加之国家出台《网络安全法》、《用户隐私保护条例》等法律法规标准,网信办、公安部、工信部及市场监管总局等四部委发起的app获取隐私整治,结合平台安全、用户敏感隐私信息保护要求及监管,针对部分暂无相关法规或要求,需要采集或生物认证方式进行身份核验的,或以“追热点”或“尝鲜”为目的,采集用户生物特征或进行身份核验的,进行严格审核,必要时不予以支持。
11-18 - 微信公众平台用户信息相关接口调整公告
微信公众平台为开发者提供了用户授权登录功能及相关接口,以便开发者为用户提供便捷的使用体验。 根据相关法律法规,为进一步规范开发者调用用户信息相关接口或功能,保障用户合法权益,平台将对用户信息相关功能及接口进行调整,具体如下: 一、相关接口调整: 1、小程序与小游戏获取用户信息相关接口:不再返回用户性别及地区信息; 能力参考:小程序用户信息 、小游戏用户信息; 2、 公众号用户信息获取接口:不再返回用户性别及地区信息; 能力参考:公众号用户信息; 3、 Open平台授权接口:包括App授权登录、公众号H5授权登录、网站扫码授权登录,不再返回用户性别及地区信息; 能力参考:移动应用、网站应用、第三方平台; 本次改造调整生效后,所述涉及字段返回值将按如下规则生效: [图片] *注:字段名均保持不变,小程序与小游戏获取用户信息接口“用户性别”字段名为gender;Open 平台授权接口“用户性别”字段名为 sex 二、相关功能调整: 1、 公众号个性化菜单功能:不再提供基于性别/地区设置个性化菜单的能力; 能力参考:个性化菜单接口; 2、公众号后台粉丝列表:粉丝列表等不再展示用户的性别信息; 涉及功能页面:公众平台帐号管理后台-用户管理/留言管理/赞赏/视频弹幕/消息; 3、服务号粉丝列表筛选:不再提供基于地区筛选粉丝的能力; 涉及功能页面:公众平台帐号管理后台-对话能力-客户管理。 平台预计10月20日完成调整,请开发者及时进行调整适配,避免影响相关服务及用户体验。 微信团队 2021年09月26日
2023-09-26 - 业务域名设置--校验文件检查失败自查指引
目前不少开发者在设置业务域名时,发现检查校验文件失败,可先按照如下步骤进行自查: 如果想保存的业务为https://test.com/,下载下来的校验文件为AbC.txt,则需要确保https://test.com/AbC.txt能够访问。 校验文件内容错误。校验文件内容一般是非HTML数据,如果下载下来的校验文件内容为HTML数据,一般为登录态过期。请重新登录小程序下载校验文件。 使用4G网络尝试访问链接,确认自身服务器没有拦截请求(常见于设置了白名单或者防火墙的服务器,需开发者自行确认下) https证书过期。请确保https证书处于有效期内。 使用curl 测试链接,确保curl能够正常访问链接,且curl出来的内容为校验文件内容。 使用time curl https://test.com/abc.txt查看链接时间,建议耗时在1s之内。 请确保url中的文件名与下载下来的文件名大小写一致。如下载的文件是AbC.txt,确保url是https://test.com/AbC.txt,不能是https://test.com/abc.txt 部分用户的服务器配置较陈旧,安全性差(如配置 768位 的 DH),为了保证通信安全,微信后台不支持,请更新服务器配置。 (1)通过https://cloud.tencent.com/product/tools#userDefined12,检测网址是否支持TLS1.2。 (2)可通过工具 https://www.ssllabs.com/ssltest/analyze.html 检查自己的服务器,对该工具标红的各项漏洞逐项修补,建议更新配置直到该工具打分为 C及以上 。 9. 如上述检查都没有问题,请重新下载校验文件重试,确保上传到服务器的文件内容与新下载的文件内容一致。
2018-06-21 - 小程序主体公司注销了,小程序还能正常使用吗?
小程序主体公司注销了,小程序多久会无法使用?
2022-07-04 - 视频号小店-常见问题汇总
一、视频号小店是什么? 1.1 视频号小店是什么?● 视频号小店是微信视频号团队为商家提供商品信息展示、商品交易等产品能力的技术服务,全方位支持商家在视频号场景内开店经营。 二、如何开通视频号小店?2.1 开通流程包括哪些?● 「视频号小店开店」—「选择企业/个体工商户类型」 —「完成开张任务」—「开店成功」 ● 详情开通流程【视频号小店教程】企业&个体工商户 - 开店指引(对外)点击查看。 2.2 没有营业执照可以开通视频号小店吗?● 目前视频号小店系统仅支持企业&个体户申请资质入驻,故营业执照是必须提交的资质材料。 2.3 开通视频号小店有数量限制吗?● 一个视频号只能申请一个视频号小店。 2.4 视频号小店支持注销吗? ● 开店完成后暂不支持注销,开店完成前可以注销。 三、如何登陆视频号小店?3.1 视频号小店怎么登陆? ● 「电脑浏览器打开https://channels.weixin.qq.com/shop 」> 「打开微信」> 「扫码二维码」 3.2 可以支持手机登陆视频号小店管理后台吗?● 已实现双端互通,支持网页端、移动端登陆及管理。 3.3 谁可以扫码登陆视频号小店?● 注册视频号小店的微信号、超级管理员、添加的其他管理人员。 四、开店任务常见问题4.1 主体信息4.1.1 营业执照信息审核不通过怎么办?● 请根据营业执照驳回原因,仔细核对填写的相关信息是否准确。保证:营业执照证书未过期、清晰可见。 ● 一个营业执照支持开5家店铺,超过该数量会驳回。 4.1.2 商户简称怎么填?● 商户简称会在支付完成页向买家展示,填写商户名称即可。 4.2 超级管理员信息4.2.1 超级管理员要填谁?● 超级管理员信息需要填写注册微信号时的身份信息。 ● 视频号小店超级管理员和视频号管理员也必须是同一个人。 4.2.2 超级管理员可以更换吗?● 视频号小店已上线更换超级管理员的功能,按照路径可以进行更换新的超级管理员,原管理员的帐号会与小店解除绑定关系,谢谢。 路径: 登录视频号小店后台-店铺管理-基础信息-小店超级管理员-右上角修改。 4.2.3 填写超级管理员的时候要注意什么?● 填写超级管理员信息时,务必注意填写真实姓名、身份证号,否则无法完成校验。 4.2.4 视频号小店可以多人管理吗?怎么进行多人管理?● 企业店支持多人管理。在“店铺管理-成员管理”中,添加岗位和关联成员即可,可以添加不同岗位,设置岗位权限。 4.3 验证账户4.3.1 怎么验证账户?● 验证账户有两种方法,任选其一即可。 (1)法人验证:使用法人微信号扫描二维码即可验证成功。 (2)汇款验证:根据页面提示小额打款至指定账户,验证成功后,打款金额会原路退回。 4.3.2 验证账户有有效期吗?● 若30天内一直未完成验证,将自动驳回申请单。若未超过30天,申请单被审核驳回,可再次提交申请单,完成账户验证流程。 4.4 店铺运营4.4.1 视频号小店后台怎么使用?● 视频号小店店铺运营详情可以查看:【视频号小店教程】企业&个体工商户 - 店铺运营(对外) 4.5 商户号 4.5.1 注册视频号小店是否需要新开一个商户号?能否绑定原有的微信小商店的商户号? ● 需要新开一个新的商户号。 五、视频号小店怎么申请类目资质?5.1 类目资质要求及申请指引5.1.1 开放类目范围共开放超过2000个类目,一级类目包括:宠物生活、厨具、家用电器、手机通讯、数码、电脑&办公、服饰内衣、鞋靴、个人护理、母婴、美妆护肤、家纺、家居日用、家具、家庭清洁&纸品、家装建材、工业品、汽车用品、玩具乐器、运动户外、箱包皮具、酒类、食品饮料、钟表、农资园艺、生鲜、二手、生活服务、图书、艺术品、教育培训。 详细类目开放范围请点击链接查看:开放类目公告 5.1.2 类目资质要求详情请查看【视频号橱窗】管理规则合集(可对外) 中 3.1 店铺与类目开放板块的规则。 5.1.3 类目资质申请指引详细类目资质申请指引请查看: 视频号小店-商家指南-「类目资质」开通指引(对外) 六、视频号小店结算规则 6.1 结算费用 ● 交易手续费以商品实际订单成交金额为基数计算,腾讯目前未收取费用,财付通将按照《微信支付服务协议》收取商品订单实际成交金额0.6%的交易手续费。 6.2 货款结算周期及提现方式● 商家接入微信视频号小店后,将通过财付通提供的微信支付功能开通一个新的微信支付商户号。商家可在商户号后台进行资金管理,也可直接在视频号小店商家后台进行账单查询和资金提现。 详情的结算规则请查看:视频号小店结算规则 七、视频号小店商品如何关联上视频号橱窗? ● 详细流程请点击:如何在视频号的直播和短视频上架视频号小店商品?
2023-02-24 - 注册小程序使用的营业执照公司名称变更了,怎么同步小程序主体?
准备相关资料,提单同步主体即可。 1、小程序帐号 2、帐号的营业执照或者组织机构代码证: 3、法人/运营者/提交人的手持身份证照 4、变更后的主体名称: 5、变更后的相关营业执照或者组织机构代码证: 6、工商局变更证明: 手机微信端提单链接:https://kf.qq.com/touch/bill/171208selfqaa5952b5e.html
2019-08-30 - Scope 参数错误或没有 Scope 权限,错误码:10005
登录提示:Scope 参数错误或没有 Scope 权限 [图片] 排查方案: 1:使用的是订阅号,订阅号没有权限使用网页授权,详细可参考接口权限:https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Explanation_of_interface_privileges.html 2:需要已认证的服务号 3:网页授权回调域名填写错误 4:Scope参数顺序不对 5:服务号不支持扫码登录,要网站应用才支持:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html 6:snsapi_userinfo的接口权限被封
2021-07-07 - 公众平台群发消息如何删除?
1、通过微信公众平台群发的图文消息内容(包括群发成功或群发后审核中的内容),可在“已发送”中删除;进入微信公众平台->首页->群发->找到需删除的消息->点击“删除”图标删除即可。 2、将删除图文消息内容,已收到消息的粉丝,手机端图文的封面及标题暂不支持删除。 3、将删除公众号的“查看历史消息”中的相关记录; 4、图文消息删除后,群发权限不会恢复;图文消息删除5分钟后全部生效。 5、支持删除多图文消息的其中一条。 温馨提示:目前在微信公众平台中只能删除已发送成功的消息;正在群发中的消息,暂不支持撤回或删除。 [图片]
2019-11-21 - 公众号可以改名吗?
公众号可以改名,个人类型公众号的名称一年可修改两次。非个人类型的公众号分为未认证和已认证两种,未认证的帐号需进行微信认证才能修改名称,已认证的帐号可通过重新认证来修改名称。 个人类型公众号名称修改说明 1、公众号名称设置规则 公众平台帐号名称可设置4-30个字符(1个汉字=2个字符),只允许含有中文、英文、数字。 温馨提示: 1)微信公众号名称不支持设置空格、符号且不得侵犯商标权利、不能与已注册成功的帐号名称重复。 2)若名称不可使用页面会有相关提示,请留意页面提示。 2、公众号名称怎么修改(个人类型订阅号) 一年可修改两次公众号名称。(例:2019年1月1日至2019年12月31日内可修改两次名称) 公众号名称修改方法:请登录 【 微信公众平台 】->【设置】->【 公众号设置 】->【 帐号详情 】->【 名称 】->【 修改 】->通过使用帐号主体微信扫描二维码后进入修改页面,当修改名称命中保护词的时候,需要进一步审核通过方可修改成功。 温馨提示: 1)若修改名称涉嫌命中保护词的情况,审核时间为7个工作日内; 2)若修改的名称不命中保护词,将会进入24小时名称确认期,24小时后名称才会修改成功,期间可撤销改名; 修改方法如下: 点击公众号设置,在帐号详情里找到名称,点击修改; [图片] 验证身份,使用注册主体的个人微信号扫码验证通过即可; [图片] 同意协议,点击同意并进入下一步; [图片] 修改名称,填写修改后的名称,点击确定; [图片] 确认名称,原名称将有2天的保护期,到期之后立即释放给其他帐号使用。 [图片] 3、名称修改成功之后,旧名称多久释放? 改名成功后,原来的名称会有一个2*24小时(即2天)的保护期,在此期间,符合命名唯一规则情况下,只有同一主体下的其他帐号可以使用该名称,主体不一致的,则需要在保护期满后才能申请使用该名称。 4、修改名称为什么要再提交资料审核? 如果修改的名称受保护,将审核通过才可以使用该名称,您可以提供权利证明、授权文件等材料,证明您有权合法使用该名称,审核通过,则改名成功;如果未通过,则需要重新进行改名。 5、个人类型订阅号一年已经改名两次,能否提前再次修改? 目前个人帐号一年内可修改两次名称(例:2019年1月1日至2019年12月31日内可修改两次名称),暂无法提前修改,还请您等待下次修改时间。 6、用户怎么知道我改名了呢? 公众号完成改名后,在公众号的手机会话框会出现改名提醒,用户【进入公众帐号详细资料页面】->【选择右上角功能键】->【更多资料】->【帐号主体】->【名称记录】即可查看改名记录。 [图片] 您也可登录【微信公众号】->【设置】->【公众号设置】->【 帐号详情 】->【名称】里面查看改名记录。 [图片] 7、公众号名称因侵权名称被清空,是否占用个人订阅号一年两次的改名次数? 目前公众号注册名称为“新注册公众号”的改名和因侵权改名都不占用个人类型公众号一年两次的改名机会内,且无24小时确认期。 8、公众号改名的时候,为什么提示身份不符合? 目前个人类型修改名称需要主体运营者微信扫码验证,微信绑定的信息需与公众号注册所绑定的主体信息一致,您可登录【公众号设置】->【帐号详情】->【主体信息】查看主体姓氏提醒。 [图片] 9、公众号改名的时候,提示未绑定银行卡怎么办? 未绑定银行卡:请登录微信->进入钱包->添加银行卡后重试。 已绑定银行卡:请检查绑定的银行卡是否支持实名认证,若不支持请重新绑定其他可实名认证的银行卡。 10、个人信息忘记了,无法扫码验证怎么办? 个人公众号主体信息就是注册时填写和上传的个人身份证信息,如果无法扫码验证,则不支持改名,还请您联系主体负责人扫码验证后再进行改名。 非个人类型公众号名称修改说明 1、我的公众号未认证,名称如何修改呢? 目前未认证的企业、组织、媒体、政府类型公众号需通过微信认证才能修改名称,在微信认证过程中有一次提交命名的机会; 需通过微信认证流程验证企业/组织的身份和名称,且认证的名称必须符合微信认证命名规则 。 温馨提示: 1)名称不支持设置空格、特殊符号,不得侵犯商标权利且不能与已注册成功的帐号名称重复; 2)若名称不可使用页面会有相关提示,请留意页面提示即可。 [图片] 2、公众号已经认证了,名称可以修改吗? 目前已认证的帐号可通过重新认证来修改名称,重新认证的时间和次数没有限制,每发起一次微信认证,均获得一次改名的机会。 温馨提示: 1)每发起一次微信认证,需缴纳认证审核服务费用300元/次,且必须符合微信认证命名规则; 2)帐号进行重新认证,认证状态将在原认证成功有效期基础上再保留一年,期间不影响公众号使用。 3、我的公众号改名,粉丝会收到通知吗? 帐号完成改名后,在公众号会话框会出现改名提醒,用户【进入公众帐号详细资料页面】->【选择右上角功能键】->【更多资料】->【帐号主体】->【名称记录】即可查看改名记录。 [图片] 4、为什么组织类型的公众号需要通过认证才可以改名? 首先,平台需要确认改名是由帐号主体来发起,避免给公众号带来不必要的损失;其次,对认证的帐号,名称需要由第三方认证审核机构进行,确保帐号名称合法合规。 5、认证改名成功,原名称什么时候可以释放出来给其他帐号使用? 1)改名在2017年5月16号以前 帐号改名成功后,原来的名称会有一个15*24小时(即15天)的保护期,在此期间,符合命名唯一规则情况下,只有同一主体下的其他帐号可以使用该名称,主体不一致的,则需要在保护期满后才能申请使用该名称。 2)改名在2017年5月16号以后 帐号改名成功后,原来的名称会有一个2*24小时(即2天)的保护期,在此期间,符合命名唯一规则情况下,只有同一主体下的其他帐号可以使用该名称,主体不一致的,则需要在保护期满后才能申请使用该名称。 6、改名记录是否可以删除或清空? 目前暂不支持删除或清空改名记录。
2020-06-05 - 如何修改公众号主体?
[图片] 1、主体营业执照公司名称在国家工商局进行修改变更,已获取工商局提供的名称核准通知。(新营业执照注册号需与原申请公众平台时的营业执照注册号一致)举例说明:帐号注册时使用 “深圳市腾讯计算机系统有限公司”,现在工商局变更名称为“腾讯计算机系统有限公司”,营业执照注册号不变,并能提供名称核准通知,可在:公众号设置->主体信息->详情->名称修正,根据页面提供所需资料即可申请修改同步,审核时间为3-7个工作日。 2、主体营业执照按照国家要求更换多证合一,并且能提供工商局出具多证合一证明文件。举例说明:帐号注册时使用:深圳市腾讯计算机系统有限公司,营业执照注册号为:123456,现在工商局进行多证合一的变更,证件号码变更为:XX123456,并可以提供多证合一变更证明,可在:公众号设置->主体信息->详情->名称修正,根据页面提供所需资料即可申请修改同步,审核时间为3-7个工作日。 3.注册信息与证件不一致(仅支持错漏字)举例说明:主体名为:A123有限公司在申请公众帐号时,主体名称误输入为:a123,主体信息填写有错别字或漏字,建议您在:公众号设置->主体信息->详情->名称修正,根据页面提供所需资料即可申请修改同步,审核时间为3-7个工作日。主体资料完成修改同步后,再申请帐号找回操作。 4.原公众帐号主体为个体工商户,现在工商局申请升级为公司,并能提供《个体工商户升级为企业的证明》。举例说明:注册帐号时使用A123的个体户营业执照,现在在工商局将A123的个体工商户升级为A123有限公司,可以通过微信认证流程修正主体信息,需提供工商局出具的《个体户升级企业证明》,审核机构在认证审核过程中会核实主体变更情况,如属实则会更新主体信息。 5.政府类型主体因为行政区划变更导致的主体名称变更 举例说明:深圳市龙华新区税务局变更为深圳市龙华区税务局,可在公众号后台:公众号设置->主体信息->详情->名称修正,根据页面提示提供所需资料即可申请修改同步(变更证明可以提交关于行政区划变更的相关批文或公示、公告等),审核时间为3-7个工作日。 6.非企业类型机构(政府、媒体、其他组织类型等)主体名称发生变更,有相关主管部门出具的关于机构名称变更批复文件或证明文件。 举例说明:注册帐号时机构名称叫A123,后来因为机构改制或其他原因更名为A124,可以通过微信认证流程修正主体信息,需提供相关主管部门出具的关于机构名称变更批复文件或证明文件,审核机构在认证审核过程中会核实主体变更情况,如属实则会更新主体信息。 [图片] 1、A公司注册需转给B公司运营及认证使用举例说明:A公司营业执照进行完成注册审核公众帐号:A123,现在A公司想将A123这个帐号转给B公司进行运营使用,B公司想要用自己的单位资料对A123进行认证年审,这情况下公众帐号主体不能进行修改同步,建议您对帐号之间申请帐号迁移使用。 2、公众帐号主体已在工商局进行注销,并在工商局重新注册新的公司 举例说明:原帐号主体主体A123在工商局申请注销,重新注册了公司:B123,两个公司的营业执照注册号不一致,这情况下公众帐号主体不能进行修改同步,建议您对帐号之间申请帐号迁移使用。 3、公众帐号申请主体为子公司,现需要将帐号转交至母公司统一管理 举例说明:帐号主体为a123,是集团公司分公司名下帐号,现在集团公司A123要求收回帐号统一管理运营,两家公司虽为子母关系,但营业执照注册号不一致并不是同一主体,公众帐号主体不能进行修改同步,建议您对帐号之间申请帐号迁移使用。 4、公众帐号在注册过程中公司主体名称填写有误,与营业执照信息不匹配 举例说明:帐号在注册时选择微信认证验证主体,A123有限公司在申请公众帐号时,主体名称误输入为:a123,若主体信息填写有误,建议您等待30天注销或更换新的邮箱重新注册,这种情况下主体不支持进行修改。
2020-03-18 - 如何找回帐号?
企业/媒体/组织类型(有对公账户) 需结合主体名称、对公银行账户的验证方式找回帐号,具体步骤如下: 第一步【填写资料】:您需按网页指引填写主体信息、重置管理员身份(填写新管理员信息并扫码,找回成功后该信息将更新为管理员)并提供【新的登录邮箱】; 第二步【激活邮箱】:登录新邮箱激活找回邮箱后留意微信号上我司推送帐号找回的重要打款信息; 第三步【打款验证】:使用找回帐号时填写的对公帐号向腾讯指定账户进行指定金额打款(需在10天内完成打款),若打款信息正确则在1个工作日左右推送验证结果至管理员微信号上,且所打款的金额将在3个工作日内原路退还到对公账户上; 第四步【重设密码】:您需使用新邮箱在MP平台进行重设密码再登录公众平台使用即可。 流程图如下: [图片] 步骤详细说明: 1)方法一:找回帐号网址(复制链接到浏览器上打开:http://mp.weixin.qq.com/acct/findacct?action=scan) 方法二:如需找回同主体名下申请的帐号,请您登录上公众平台,点击“公众号设置”->“帐号详情”->“主体信息”->“详情”;在主体绑定帐号这一栏点击“查询”->找回帐号;根据页面提示填写信息; 2)查收新扫码微信号上帐号找回的信息通知,并且在规定时间之前打款指定金额至腾讯收方帐号验证; 3)打款完成后请认真核对打款交易是否成功; 4)验证成功后即可在电脑打开网站(复制链接:http://mp.weixin.qq.com/acct/resetpwd?action=send_email_page),输入之前填写的新邮箱进行重设密码操作; 5)谨记新邮箱+新密码登陆公众平台(复制链接到浏览器上打开http://mp.weixin.qq.com/)。 温馨提示: 1)必须有对公帐户,如没有对公帐户(包括个体户),请尽快去银行办理并确认该对公户能够正常接收款项后再进行帐号找回操作; 2)提供的新登陆邮箱必须为“未绑定过个人微信,且未申请过公众号”的新邮箱; 3)操作成功后,公众号运营者身份证信息 和管理员微信号也同时更换成功。 企业/媒体/组织类型(无对公账户) 请准备好以下信息,联系公众平台人工客服反馈,相关工作人员核实后会在3个工作日内与您联系。 1、公众号(邮箱或ID); 2、提供当时认证运营者名下的个人微信号(需开通微信支付); 3、微信号绑定的银行卡/信用卡(卡后四位数); 4、注册时提供的营业执照; 5、申请找回帐号的书面说明(需填写申请原因、及加盖主体公章); [图片] 6、需要修改邮箱(未绑定过微信/公众号的邮箱); 温馨提示: 1、若无法提交运营者资料可用法人资料代替; 2、如果公众号通过非正常途径申请、或未进行信息登记,则无法再进行核实,建议可以申请新的公众帐号使用。 个体户类型 针对个体工商户类型找回的问题,您可以准备好以下的资料信息后,点击 https://kf.qq.com/bills/170922selfsam1e2e932.html提交申请修改,我司工作人员会尽快核实。 1、公众号(邮箱或ID); 2、提供当时认证运营者名下的个人微信号(需开通微信支付); 3、微信号绑定的银行卡/信用卡(卡后四位数); 4、注册时提供的营业执照; 5、申请找回帐号的书面说明(需填写申请原因、及加盖主体公章); [图片] 6、需要修改邮箱(未绑定过微信/公众号的邮箱); 温馨提示: 1)提供证件及盖章须与申请公众号的原主体保持一致; 2)若无法提交运营者资料可用法人资料代替; 3)找回原因需与表单填写找回原因一致; 4)若只清空管理员微信号,邮箱不作修改,变更邮箱处请填写原有邮箱; 5)变更邮箱需与表单填写邮箱保持一致; 6)公章主体名与组织机构代码主体一致,若个体户无公章,请法人手写、清晰、正楷签字; 政府类型 请您准备好以下资料 [图片] 个人类型 找回操作方法: 方法一:找回帐号网址(复制链接到浏览器上打开:http://mp.weixin.qq.com/acct/findacct?action=scan) 方法二:如需找回同主体名下申请的帐号,请您登录上公众平台,点击“公众号设置”->“帐号详情”->“主体信息”->“详情”;在主体绑定帐号这一栏点击“查询”->找回帐号;根据页面提示填写信息; 根据页面提示操作,提交成功后,24小时审核结果将发送至您扫码时的个人微信号上。 温馨提示:提供的新邮箱需未绑定过个人微信,且未申请过公众号的新邮箱。
2020-06-05 - 如何提单“公众平台”腾讯客服?
第一步:用手机打开微信 在微信首页的顶部“发现搜索按钮”(如图1.1)->搜索“腾讯客服”,打开“腾讯客服”小程序(如图1.2) 图1.1: [图片] 图1.2: [图片] 第二步:进入“腾讯客服”小程序,点击相应的“标签”进行跳转 在顶部tab,点击“其他”(如图2.1)->点击“更多其他问题”(如图2.1)->点击“公众平台”(如图2.2)->点击底部的“提交问题”(如图2.3) 图2.1: [图片] 图2.2 :[图片] 图2.3:[图片] 第三步:点击“提交问题”,跳转到编辑页面。 选择“问题类型”(如图3.1)->对应的选项进行填写(如图3.2) 图3.1:[图片] 图3.2:[图片]
2021-02-25 - 被封禁的公众号,如何释放邮箱、管理员微信号等资源?
被处罚的帐号不支持找回,也不支持释放任何资源,其中包括公众号昵称、邮箱、主体次数、手机号、管理员微信号等。
2020-02-25 - 微信公众平台群发条数说明
1、微信公众平台消息群发条数 1)订阅号(认证用户、非认证用户),1天可群发1条消息(每天0点更新,次数不会累加); 2)服务号(认证用户、非认证用户),1个月(按自然月)内可发送4条群发消息(每月月底0点更新,次数不会累加)。 2、群发条数是否可以增加? 群发条数目前不支持增加。
2019-11-21 - 自定义菜单设置后与手机端显示不同步
1、菜单未发布成功 菜单发布后会24小时内在手机端同步显示。若未显示请重新进入菜单编辑页面,页面如果提示“请设置当前菜单内容”,则代表还有菜单未完善内容,请完善菜单内容或删除空菜单后重新发布。 [图片] 菜单发布成功状态: 确认发布之后页面提示“保存并发布成功”则代表发布成功,自定义菜单左上角会提示具体所需同步时间。发布成功后,菜单状态由“菜单编辑中”变为“菜单已发布”。 [图片] 温馨提示: 1)菜单发布后,粉丝不会收到更新提示,若多次编辑,以最后一次保存为准。 2)编辑中的菜单只要完善了菜单名称即可预览,整体发布则需要每一个菜单都完善内容,否则无法发布同步至手机端。 2、后台设置的自定义菜单和公众号资料页显示不一致 如果自定义菜单内容设置的是“发送消息”,在公众号的资料页不会展示此菜单;若菜单设置的是“跳转网页”、“跳转小程序”,则会在资料页展示。 [图片] 3、使用开发模式设置自定义菜单 开发者可以通过自定义菜单接口进行个性化设置(未认证订阅号暂不支持),开发者可通过用户分组、性别、手机操作系统及地区来设置自定义菜单。设置后,不同条件的用户会看到不同的自定义菜单展示。若使用开发者模式设置菜单后显示不一致,可查看相关开发文档,检查菜单接口数据。 开发文档可点击链接查阅了解:https://mp.weixin.qq.com/wiki
2020-06-05 - 如何修改已群发消息?
1、可以修改哪些内容? 已群发的图文消息可以修改,其他类型消息暂不支持。一篇文章可以修改1次,总计最多能修改20个字符(注:标点、英文、数字、空格都计算在内)。支持增、删和替换。正文其他内容、封面题图、已编辑摘要和图文选项(如原创、留言等)都不支持修改。若该图文无自己编辑的摘要,且运营者修改正文开头文字正好在默认取摘要范围内,提交成功后图文消息的摘要不会更新。 2、怎么操作修改? 登录电脑端公众平台管理后台,在首页已群发消息列表,对已群发单篇图文有修改错别字按钮,点击即可打开修改页面,修改提交后需要管理员微信扫码验证。 [图片] [图片] 3、为什么每篇文章只提供一次修改且只能修改20个字符? 我们希望每条推送都是公众号运营者深思熟虑的结果。秉承对读者负责的原则,更好的保证用户的阅读体验,修改20个以下的错别字也是为了尽量避免出现重复阅读时内容上前后不一致的情况。 4、为什么封面题图、已编辑摘要和图文选项(如原创、留言等)都不支持修改? 推送到用户端的内容无修改权限,不仅仅是为了尊重用户前后一致的感知,技术上也不能对用户端的内容做修改。 5、什么情况下文章无法修改? 以情况下文章无法修改: 1.辟谣:文章被发起辟谣且待审核或文章被发起辟谣且审核通过; 2.已删除的文章;
2020-06-05 - 小程序无法获取手机号,提示“该appid没有权限”
目前获取手机号接口针对非个人开发者,且完成了认证的小程序开放(不包含海外主体)。需谨慎使用,若用户举报较多或被发现在不必要场景下使用,微信有权永久回收该小程序的该接口权限。具体可参考文档说明:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html 若是调用该接口出现提示“该 appid 没有权限”,请确认该小程序是否符合使用条件。
2020-02-25 - 为什么群发成功后粉丝却收不到消息?
在微信公众平台消息群发成功后,而粉丝未收到群发消息,可能是以下原因导致: 1、通过微信公众平台群发消息时,若默认群发给了全部用户,则可以正常接收消息;若对群发对象、性别、群发地区进行了选择,而该粉丝不在所选择的范围内,则无法接收群发消息。(群发消息查看方法:登录微信公众平台->功能->群发功能->已发送) 2、被加入黑名单的粉丝,不会接收到群发信息,建议进入微信公众平台->用户管理->黑名单,查看是否有进行设置。 3、如果该粉丝在您群发消息时,取消了关注,同样不会收到群发消息。 4、若帐号属于服务号,每个粉丝一个月只能收到4条消息,若使用高级群发接口发送了,已经接收超过4条的粉丝无法收到消息。 温馨提示:如果您自己本身没有使用API(开发者接口)群发消息接口进行群发,请联系第三方平台的网站后台或者您帐号的开发者核实确认。
2020-03-18 - “该公众号提供的服务出现故障,请稍后再试”?
“该公众号提供的服务出现故障,请稍后再试”
2020-12-02 - 公众号文章搜索不到时如何处理?
为保障用户体验,公众号文章内容必须是合规内容、且新发布的内容最长可能需要48小时后才能被搜索到。 如已经发布后一周,并且遇到以下公众号文章搜索不到场景: 公众号号内搜索不到文章公众号迁移后搜索不到文章公众号新发的文章搜索不到公众号文章无法通过搜一搜搜索出来可在社区发帖反馈,发帖时,请提供:已群发一周搜索不到的文章标题、搜索结果页面截图、推文链接以及公众号账号信息。 请注意搜索结果页面截图,需要点击文章模块,筛选已关注的公众号。若已关注的公众号下方有展示是符合预期 提交成功后,相关团队将会及时进行核实及处理,请勿重复发帖。 搜一搜优化教程:https://mp.weixin.qq.com/s/FTNvYMAYvvgfg0qtH4QsGQ微信公众平台运营规范:https://mp.weixin.qq.com/mp/opshowpage?action=newoplaw
2023-03-13 - 如何做公众号帐号迁移?
具体参考文档“帐号迁移流程指引”:https://kf.qq.com/faq/170221uQ7Vz2170221ZzIZv6.html1、帐号迁移是什么?(详细请参考文档:https://kf.qq.com/faq/170112Q7vIfi1701122AVZvY.html) 公众号不支持直接变更主体。公众平台推出帐号迁移功能,通过此功能可将A账号的粉丝、文章素材(可选)、微信号(可选)、违规记录迁移至B帐号。 2、帐号迁移条件?(详细请参考文档:https://kf.qq.com/faq/170112nyQ7BZ170112vIN7RZ.html) 1)、原公众号A必须是验证过主体信息的订阅号或服务号:小额打款验证或法定代表人验证或微信认证成功(包括资质审核成功);个人类注册成功。 2)、目标账户B必须是验证过主体信息【小额打款验证或法定代表人验证或微信认证成功(包括资质审核成功)】的组织类订阅号或服务号。 3)、仅支持中国大陆地区主体帐号,海外主体公众号不支持发起迁移或接收迁移。 3、帐号迁移需要提前准备哪些材料?(详细请参考文档:https://kf.qq.com/faq/170301ruE7Jr170301IJbUJz.html) 1)一个满足上述条件的目标帐号; 2)按照迁移流程指引,在第三步下载申请公函并填写; 3)持申请公函到公证机关进行印鉴公证,提供公证书(暂不支持律师见证); 4)因需支付300元审核费用,若需开具增值税发票,请提前和财务申请准备好税号、税务登记证/营业执照、开户许可证。 4、帐号迁移费用?(详细请参考文档:https://kf.qq.com/faq/17011226zUJB170112muuyYF.html) 帐号迁移”需支付审核服务费用人民币300元,该费用为用户基于腾讯公司提供的“帐号迁移”审核服务而产生的包括但不限于委托第三方专业审核机构提供审核服务等费用,一旦确认提交帐号迁移申请,该等成本和费用即已发生,与帐号迁移申请的审核结果无关,不存在退还审核服务费用的情况。 温馨提示:审核中30天内有3次补充或重填机会,我司将通过公众平台通知中心进行通知,请您留意。 5、帐号迁移需要耗费多长时间? 帐号迁移的时间,将根据审核时间和确认迁移等时间确定: 1)提前准备阶段,需针对申请公函在当地公证机关进行公证,或到律师事务所进行见证,1-2个工作日出具公证/见证结果; 2)提交帐号迁移申请后,会由专业第三方审核机构进行审核,审核时间为1-3个工作日; 3)审核通过后,双方管理员确认同意迁移。确认迁移后,系统马上冻结原账号并下发通知给原账号粉丝,粉丝在1天内有选择是否取关的权利; 4)1天后自动触发迁移,包括粉丝、群发素材、违规记录,时间随迁移量大小,将在1-3天内完成; 5)迁移完成后,新帐号名称同步。整个迁移流程结束。 6、帐号迁移步骤: 需要查看完整帐号迁移流程图,点击这里! 温馨提示: 1)例如帐号A迁移至B,那迁移完成,A帐号被回收,B帐号获得A帐号的粉丝等信息继续使用,但主体还是B; 2)若审核失败,费用不予退还。审核中30天内有3次补充或重填机会,我司将通过公众平台通知中心进行通知,请您留意; 3)延续原来名称和使用新名称,都需要重新核实名称是否符合命名规则。
2021-03-04 - 什么是发布,如何进行发布?
1.发布是什么? 发布是公众号内容发表形式的一种。不同于群发,发布的内容不会通过推送消息触达给关注的粉丝,也不会占用群发的次数。每天可以发布多篇内容。 可支持发布的内容与群发一致,包括图文、视频、文字、图片、音频、转载等消息类型,同时支持原创、赞赏、付费,留言(若有)。 2.发布的内容可以运用在什么场景? 发布的内容,可以用于自动回复、自定义菜单、页面模板和话题中,发布成功时会生成一个永久链接。 3.如何发布内容? 在编辑器编辑好内容,可在此选择发布。你也可以将存放在草稿箱中内容,通过发布内容的入口进行发布。 [图片] [图片]
2021-10-15 - 微信客户端 iOS 版本内测安装指南
注意: 1、任何时候都不要卸载微信,否则丢失消息记录,无法找回! 2、参加内测后,如不想继续参与,可在 AppStore 下载正式版微信直接安装。无需卸载原有微信,不会删除聊天记录; 3、通过 TestFlight 包下载的内测版本微信会有黄色圆点(黄色圆点不可清理),用于区分原有版本微信 [图片] 4、TestFlight 包存在有效期。在有效期内,原有微信正常可用;超过有效期,原有微信无法启动且报错。此时前往 AppStore 下载正式包覆盖安装即可,切勿卸载原有微信! TestFlight体验包安装流程 1、手机下载 TestFlight 软件,可在 AppStore 直接搜索安装,或使用下载链接安装(要求 iOS 13.0.0 以上版本) 下载链接:https://itunes.apple.com/cn/app/testflight/id899247664 [图片] 2、手机打开邮箱的收件箱,找到 TestFlight 发送的邮件(如未在收件箱发现邮件,留意是否放入垃圾邮件箱) 3、打开该邮件,点击 View in TestFlight 开始进行安装 4、点击 【接受】 >>【安装】>>【打开】>>【下一步】>>【开始测试】 [图片]
2022-06-08 - 如何重置企业/媒体/组织/个体户类型管理员微信号?
请您通过浏览器打开该网页https://mp.weixin.qq.com/acct/findacct?action=scan重置公众号绑定邮箱和管理员微信号, 在申请找回帐号的页面填写的对公账户信息和运营者信息可以和注册不一致,完成找回后,管理员微信号会同步更新; 第一步:打开网址https://mp.weixin.qq.com/acct/findacct?action=scan,填写资料扫码提交; 第二步:查询银行账单的备注码,并记录好备注码上的6位数字; 第三步:等候24小时,届时会通过“微信团队”下发消息到扫码的微信号提示填写备注码,将备注码填写上去,通过验证; 第四步:到公众平台官网使用新邮箱重新设置密码; 第五步:使用新邮箱+新密码登录公众平台帐号。 温馨提示: 1)必须有对公帐户。如没有对公帐户(包括个体户),请尽快去银行办理并确认该对公户,正常接收款项后再进行帐号找回; 2)在申请找回帐号过程中,扫码的个人微信号会自动默认成为帐号安全中心新的管理员微信号; 3)1分钱打款到帐时间为3个工作日内,若提前收到打款,请耐心等待24小时后“微信团队”下发通知输入验证信息即可。 步骤详细说明: 1)输入公众号名称或原始ID、微信号点击搜索标志; [图片] 2)填写资料验证:包括企业名称、营业执照注册号、对公账户信息、运营者身份证姓名和身份证号码、运营者身份证验证,新的登录邮箱; [图片] [图片] 3)登录新邮箱确认; [图片]
2019-11-21 - 小程序公众号干货运营之注销篇
各位亲,面对帐号注销是不是束手无策呢?帐号如何注销,怎么注销,注销需要提供什么信息内容呢?请仔细往下看看 小程序 关于小程序注销的条件,若未冻结的个人帐号和组织类帐号就不 一 一 细讲,详情请参腾讯客服文档:https://kf.qq.com/product/wx_xcx.html#hid=2826 1:小程序注销之政府无对公账户: 详细流程请参考:https://kf.qq.com/faq/190104YnQbYN190104RzaYba.html 政府的有一致主体是提供一致的主体证件和公章,如果有变更请提供4项材料:因机构改革、单位合并、撤一建一等情况,导致机构主体名称有变更,提供以下材料申请注销: 1、更名相关的红头文件(有鲜章); 2、主体名称变更情况说明书(加盖新主体公章); 3、变更后新主体的主体证件;(原件拍照或加盖公章的复印件) 4、注销申请函(加盖新主体公章); 2:小程序注销之个体工商户 若个体工商户存在对公账户,请使用对公账户小额打款注销 若个体工商户类型无对公账户注销小程序工单指引流程如下 工单所需材料 1、小程序绑定邮箱/原始ID: 2、主体证件材料(营业执照/组织机构代码证等): 3、小程序绑定的法人身份证原件正反面的清晰扫描件或照片: 4、小程序的注销书面申请,申请书必须加盖公章。(若个体户没有公章可支持法人手写签名) 附注:注销申请书模板(https://kf.qq.com/faq/200306R7N3mI200306I3aEBz.html) 材料提交链接:https://kf.qq.com/touch/bill/200306selfqaafe6c551.html(手机端打开) 3:小程序注销之帐号主体已注销 主体已注销小程序工单指引流程如下, 1、小程序绑定邮箱/原始ID: 2、主体注销证明: 3、小程序绑定的法人身份证原件正反面的清晰扫描件或照片: 4、小程序的注销书面申请,企业账号的申请必须有加盖公章的函件(公章被收的请法人手写签字)附注:注销申请书模板(https://kf.qq.com/faq/200306R7N3mI200306I3aEBz.html) 材料提交链接:https://kf.qq.com/touch/bill/200306selfqaafe6c551.html(手机端打开) 4:小程序注销之门店小程序 门店小程序依附于公众号,不支持单独注销,公众号注销门店小程序才支持注销 5:公众号正常运营,门店小程序如何释放昵称 如果需要释放该小店小程序昵称,发送邮件到“miniprogram@tencent.com”,标题格式【关于XXX名称释放请求】,需提供以下材料: 1、小程序帐号(原始ID); 2、绑定的管理员微信号; 3、小程序主体营业执照等主体证件; 4、小程序所有者的书面申请,申请书需加盖小程序主体公章;(个体户无公章:申请书需要加上法人签名); 邮件内容:需包含背景、释放请求原因。 6:复用公众号资质快速注册的小程序如何注销 复用资质申请的小程序是独立存在的,请按照正常流程注销即可 7:注册小程序选择微信认证,若未完成微信认证如何注销呢? 小程序30天未认证或认证失败且7天内未发起认证不会释放邮箱,但该邮箱支持重新注册小程序,会释放主体信息、管理员信息、昵称。 公众号 关于公众号若未冻结的个人帐号和组织类帐号就不一一细讲,详情请参考腾讯客服文档:https://kf.qq.com/product/weixinmp.html#hid=2267 1:公众号注销之政府无对公账户: 详细流程请参考:https://kf.qq.com/faq/190531qyuuiY190531BjyyEv.html 政府的有一致主体是提供一致的主体证件和公章,如果有变更请提供4项材料:因机构改革、单位合并、撤一建一等情况,导致机构主体名称有变更,提供以下材料申请注销: 1、更名相关的红头文件(有鲜章); 2、主体名称变更情况说明书(加盖新主体公章); 3、变更后新主体的主体证件;(原件拍照或加盖公章的复印件) 4、注销申请函(加盖新主体公章); 2:公众号注销之个体工商户 若个体工商户存在对公账户,请使用对公账户小额打款注销 若个体工商户类型无对公账户,请使用法人扫脸注销公众号 详情请参考:https://kf.qq.com/faq/220309bUvmIB220309BbAjMz.html 3:公众号注销之帐号主体已注销 主体已注销公众号工单指引流程如下, 1、公众号绑定邮箱/原始id/微信号: 2、主体注销证明: 3、公众号绑定的法人身份证原件正反面的清晰扫描件或照片: 4、公众号的注销书面申请,企业账号的申请必须有加盖公章的函件(公章被收的请法人手写签字) 附注:注销申请书模板(http://kf.qq.com/faq/171018R3IVBF171018INjUvA.html ) 材料提交链接:https://kf.qq.com/touch/bill/180227selfqa9ab6ac55.html(手机端打开) 4:未注册成功的帐号如何注销 若帐号当时没有走完注册流程且长期没有登录该帐号,到期会被系统注销。没有走完注册流程的帐号不占用个人信息,也不支持找回,建议重新注册 5:注册公众号选择微信认证,若未完成微信认证如何注销呢? 若公众号注册时选择微信认证,自注册日起30天内未进行认证(第30天仍在认证中不算),点击“重新提交材料”,帐号角色变为注册失败,不会释放帐号邮箱,但该邮箱支持重新注册公众号,会释放主体信息、管理员信息、昵称, 6:小程序公众号注销确认期 注销确认期的7天内每天会发送一次确认注销的通知,若管理员一直未点击确认注销则默认取消注销,注销失败。因此管理员请关注公众平台安全助手!!!
2022-04-08 - 微信开发者工具使用和更新需要访问哪些url?
因为公司规定,开发环境不开放访问外网,如必要的需提申请加白名单,所以想请教下,开发者工具有哪些域名是必要的?比如客户端更新、访问云函数、访问云存储之类的
2022-05-07 - 小程序搜索功能,云开发搜索,小程序云开发模糊搜索,同时搜索多个字段
今天来给大家讲讲小程序的搜索功能。我这里后台数据库用的是小程序云开发的云数据库。所以我们搜索的时候就要借助云开发来实现。 一,需求 比如我这里有如下的一些数据 [图片] 我们想实现如下搜索需求 1,搜索标题(title)包含‘小石头’的数据 2,搜索标题(title)或者描述(desc)包含‘小石头’的数据 3,搜索标题(title)描述(desc)都包含‘小石头’的数据 我们知道数据库查询的时候有个where语句,但是where语句是查询某个字段全部包含你输入的内容时才可以,所以单纯用where语句来做搜索的话,结果太单一。所以我们今天就来学习下模糊搜索功能的实现。我们以上面三个需求为例,来一个个讲解。 二,实现原理 我们做模糊搜索的时候,其实就是查询某个字段里是否包含我们的搜索词。而模糊搜索需要借助RegExp,来看看RegExp是什么。 [图片] 官方文档:https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/database/Database.RegExp.html 再来看看官方示例 [图片] 可能看官方示例会有点糊涂,那么我们接下来就结合具体代码来给大家做下讲解。 三,模糊搜索的代码实现 3-1,模糊搜索单个字段 需求:搜索标题(title)包含‘小石头’的数据 代码如下 [图片] 查询结果如下: [图片] 可以看到我们成功的查询到了标题里包含‘小石头的数据’ 3-2,模糊搜索多个字段(满足一个即可) 需求:搜索标题(title)或者描述(desc)包含‘小石头’的数据 由于我们要查询多个字段,所以我们这里用到了command高级操作符里的or [图片] 代码如下: [图片] 查询结果: [图片] 我们来分析下这两条数据 1,标题和描述都包含‘小石头’,符合 2,虽然标题里没有‘小石头’,但是描述里有,所以也符合。 3,title和desc里都没有‘小石头’,所以不符合。 [图片] 3-3,模糊搜索多个字段(要同时满足) 需求:搜索标题(title)描述(desc)都包含‘小石头’的数据 由于我们要查询多个字段,所以我们这里用到了command高级操作符里的and [图片] 代码如下: [图片] 查询结果: [图片] 我们来分析下这两条数据 1,标题和描述都包含‘小石头’,符合 2,虽然desc里没有‘小石头’,但是title里没有,所以也不符合。 3,title和desc里都没有‘小石头’,所以也不符合。 [图片] 四,源码 为例方便大家使用,我把完整的代码贴到这里,后面大家使用时,直接复制这里的代码,略微改造下就可以了。 [代码] //我这里简单起见就把搜索词写死,正常应该用户输入的 let searchKey = '小石头' let db = wx.cloud.database() let _ = db.command db.collection('news') .where(_.or([ {//标题 title: db.RegExp({ //使用正则查询,实现对搜索的模糊查询 regexp: searchKey, options: 'i', //大小写不区分 }), }, {//描述 desc: db.RegExp({ regexp: searchKey, options: 'i', }), } ])).get() .then(res => { console.log('查询成功', res) }) .catch(res => { console.log('查询失败', res) }) [代码] 到这里就讲完了,我后面会专门在云开发入门的课程里作为实战案例录制视频给到大家的: 《小程序云开发入门视频》
2021-02-08 - 小程序 云开发 企业付款到零钱
终于轮到我来装一次b了 之前总是有求于各位神,现在来回馈了。 各位用小程序云开发,要实现退款、企业零钱的可以看过来。 // 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init() const config = { appid: '**************', //小程序Appid,填自己的小程序id envName: '*************', // 小程序云开发环境ID mchid: '***********', //商户号,填自己的商户号 pfx: require('fs').readFileSync('./apiclient_cert.p12'),这里是下载的api证书。证书怎么下在呢?网上有 partnerKey: '123111111111111111111111111111111111111111111111111', //此处填商户密钥 notify_url: ' ', //支付回调网址,这里可以随意填一个网址 spbill_create_ip: '127.0.0.1' //不用改 }; const db = cloud.database(); const TcbRouter = require('tcb-router'); //云函数路由 const rq = require('request'); const tenpay = require('tenpay'); //支付核心模块 这里要是报错,直接搜 nps + 报错内容 // 云函数入口函数 exports.main = async (event, context) => { const wxContext = cloud.getWXContext() console.log("提现走到了函数",event) const api = tenpay.init(config); var tixian = event.tixian // 申请企业付款到用户零钱 const orderNumber= 'dlbmoney' + new Date().getTime() + Math.floor(Math.random() * 1000) const datas = { partner_trade_no: orderNumber, openid: wxContext.OPENID, amount: tixian * 100, desc: "订单说明", check_name: "NO_CHECK", //不检查实名 spbill_create_ip:"123.151.79.109" } const result = await api.transfers(datas) return { event, openid: wxContext.OPENID, appid: wxContext.APPID, unionid: wxContext.UNIONID, } }
2021-07-07 - 官方组件默认样式修改的对应class
swiper面板指示点: .wx-swiper-dots.wx-swiper-dots-horizontal{ margin:20px //调整位置 } .wx-swiper-dot{}//指示点未选中样式 .wx-swiper-dot-active{}//指示点选中样式 button去除边框: button::after { border: none; } checkbox.wx-checkbox-input{}//未选中的框 .wx-checkbox-input.wx-checkbox-input-checked{}//选中的框 .wx-checkbox-input.wx-checkbox-input-checked::before{}//选中的框里的小勾 radio.wx-radio-input{}// 未选中 .wx-radio-input.wx-radio-input-checked{}//选中 .wx-radio-input.wx-radio-input-checked::before{}//选中的小勾 progress.wx-progress-inner-bar{}//已选择的进度条 switch.wx-switch-input{}//
2021-10-29 - 云开发私人实时聊天室
云开发私人实时聊天室说明 在最开始开发小程序时,本人和团队成员实现小程序的聊天室时遇到一些困难,查阅了一些资料,有些讲得太泛,有些讲的太难,在一个阶段克服了这个困难后,收获了很多,对整个流程也熟悉了很多,在这里记录自己的一个思路,希望也能对开发新手有帮助。 项目基本配置 1.项目创建及云开发配置: 官方文档:https://developers.weixin.qq.com/miniprogram/dev/wxcloud/quick-start/miniprogram.html PS:注意云函数目录是否为此样式:[图片] 若是普通目录样式记得在project.config.json中配置加入: [图片] 2.添加包colorui,用于样式使用,并在app.wxss中导入改包 [图片][图片] 3.在pages下新建文件夹index和新建page:index [图片] 聊天室静态页面 最终呈现的效果: 自己: [图片] 对方: [图片] 1. wxml 整体结构: [图片] 整一个页面说白了就是由一个scroll-view和一个回复框组成,scroll-view中由消息数组构成,消息的内容可以自己定义(时间,头像,消息内容等等) 具体源码: <!-- scroll-view来实现页面拖动 --> <scroll-view id='page' scroll-into-view="{{toView}}" upper-threshold="100" scroll-y="true" enable-back-to-top="true" class="message-list"> <!-- 每一条消息 --> <view class="cu-chat" wx:for="{{3}}" wx:key="index" id="row_{{index}}"> <!-- 自己发出的消息 --> <block wx:if="{{false}}"> <block wx:if="{{true}}"> <view class="datetime" style="width:100%">2021-11-16 18:10</view> </block> <view class="cu-item self" style="width: 750rpx; height: 120rpx; display: flex; box-sizing: border-box; left: 0rpx; top: 0rpx"> <view class="main"> <view class="content bg-green shadow" style="position: relative; left: 0rpx; top: 22rpx;border-radius: 10rpx"> <text style="font-size:33rpx">这是一条消息</text> </view> </view> <view class="cu-avatar radius center" style="background-image: url({{useravatar}}); width: 71rpx; height: 71rpx; display: flex; box-sizing: border-box; left: 0rpx; top: 0rpx" bindtap="go_myinfo"></view> </view> </block> <!-- 对方发出的消息 --> <block wx:else> <block wx:if="{{true}}"> <view class="datetime" style="width:100%">2021-11-16 19:10</view> </block> <view class="cu-item" style="width: 750rpx; height: 120rpx; display: flex; box-sizing: border-box; left: 0rpx; top: 0rpx"> <view class="cu-avatar radius center" style="background-image: url({{match_avatar}}); width: 71rpx; height: 71rpx; display: flex; box-sizing: border-box; left: 0rpx; top: 0rpx"> </view> <view class="main"> <view class="content bg-white shadow" style="position: relative; left: 0rpx; top: 22rpx;border-radius: 10rpx"> <text style="font-size:33rpx">这是对面的一条消息</text> </view> </view> </view> </block> </view> </scroll-view> <!-- 回复框 --> <view class="reply cu-bar"> <!-- 输入框 --> <view class="opration-area"> <input type="text" bindinput="getContent" value="{{textInputValue}}" maxlength="300" cursor-spacing="10" style="width: 544rpx; height: 64rpx; display: block; box-sizing: border-box;"></input> </view> <!-- 发送按钮 --> <button class="cu-btn bg-green shadow" bindtap='sendMsg' style="width: 150rpx; height: 64rpx; display: flex; box-sizing: border-box; left: -22rpx; top: 0rpx; position: relative">发送</button> </view> 2. wxss一些样式的配置,具体就不详细叙述了,见源码: /*消息窗口*/ .message-list { margin-bottom: 54px; } /*文本输入或语音录入*/ .reply .opration-area { flex: 1; padding: 8px; } /*回复文本框*/ .reply input { background: rgb(252, 252, 252); height: 36px; border: 1px solid rgb(221, 221, 221); border-radius: 6px; padding-left: 3px; } /*回复框*/ .reply { display: flex; flex-direction: row; justify-content: flex-start; align-items: center; position: fixed; bottom: 0; width: 100%; height: 108rpx; border-top: 1px solid rgb(215, 215, 215); background: rgb(245, 245, 245); } /*日期*/ .datetime { font-size: 10px; padding: 10px 0; color: #999; text-align: center; } 到此,静态的页面就已经做好啦,现在主要的难题也是数据部分,下面将先讲述数据库chatroom的设计及解释,最后进行js的代码编写。 数据库创建及设计1.数据库表创建:在编辑器打开云开发控制台,点击数据库,再点击集合名称右边加号,创建一个集合名称为chatroom的表。 [图片][图片] [图片] [图片] 2.chatroom设计具体页面如图: [图片] 其中, _id为记录创建时自动创建的标识属性,即主键 _openid和match_openid代表了自身和对方 records为一个对象数组,每个对象的属性分别是: msgText:消息属性(此案例中只有text属性,即文本,可自扩展为图片、音频等) openid:发送人的标识 sendTime:消息创建时间 sendTimeTS:消息创建时的时间戳(用于做时间比较,判断时间显示) showTime:消息是否显示时间 textContent:具体文本内容 其中, records:array类型, records中的记录:object类型 records中的sendTimeTS:number类型 records中的showTime:boolean类型 其余全为string类型 PS: 1、openid和match_openid可标识一个聊天室,是唯一不变的; 2、用户本身的openid是有可能在记录中的match_openid位置上的,谁发起了这个聊天室,openid这个位置就是那个发起用户的openid,所以在开发中,想要获取自己和所有其他人的聊天室,要查每条记录中的openid或者match_openid与自身openid是否匹配。 3.权限设置因为该表中的记录,非记录创建者也可以进行读写,这里的权限记得设置,不然会出问题: [图片] [图片] [图片] 具体功能实现(JS写法)1.先配置Page.data:6个属性,如有需要可自行扩展 [图片] chats存储数据库表中的records的所有信息; textInputValue是输入框内容。 2.绑定数据库表onChange函数: [图片] [图片] 这里的onChange输出e是这样的: [图片] type=init,获取了数据库表中该记录的所有内容,在这里将js中的chats进行赋值即可; 另外,当该记录内容变化时,type是update类型 3.wxml修改,wx-for将chats显示,以及一些判断和内容显示的设置: [图片] 到此,显示效果就有啦 [图片] 接下来,就是信息的添加了,下面将显示如何添加新信息到数据库 4.发送信息 先获取输入框内容: [图片] [图片] 发送函数: 增加一条信息,就是在records数组中加一条记录,所以在函数内部要对新纪录的属性进行一些赋值和判断等。 对showTime的处理: [图片] 消息空白处理: [图片] 对消息内的所有属性进行一个打包处理: [图片] 存储记录,并滑动页面: [图片] 最后,清空消息框内容 [图片] 发送一条消息,最终效果如图: [图片][图片] js源码const app = getApp() const db = wx.cloud.database() const _ = db.command const chatroomCollection = db.collection("chatroom") var util = require('../../utils/util.js'); Page({ data: { //这里的openid和match_openid应该是在上一级页面传进来的属性,这里由于只有聊天室所以暂时设置为一些固定值,用于测试 openid:'', match_openid:'', //这里的avatar是头像,具体传参方式自己设定,这里暂时设置为固定值,用于测试 useravatar:'', match_avatar:'', chats:[], textInputValue:'' }, onReady() { var that = this //查询openid和match_openid所标识的唯一聊天室 chatroomCollection.where({ _openid: _.or(_.eq(that.data.openid), _.eq(that.data.match_openid)), match_openid: _.or(_.eq(that.data.openid), _.eq(that.data.match_openid)) }) //绑定onChange,直观而言即表中该记录发生变动时,调用该函数 .watch({ onChange: this.onChange.bind(this), onError(err) { console.log(err) } }) }, //数据库表onchange绑定函数 onChange(e) { let that = this //type="init"的情况:初始化聊天窗口信息 if (e.type == "init") { that.initchats(e.docs[0].records) } //type="update"的情况:records中增加了一条记录 else { //在chats数组中增加该新消息 let i = that.data.chats.length const new_chats = [...that.data.chats] if (e.docs.length) new_chats.push(e.docs[0].records[i]) this.setData({ chats: new_chats }) } }, initchats(records) { this.setData({ chats: records }) //跳转到页面底部 this.goBottom() }, //获取输入文本 getContent(e) { this.data.textInputValue = e.detail.value }, sendMsg(){ let that = this //show代表了数据库表中的showTime属性,是否显示消息时间 var show = false //无记录时,true if (this.data.chats.length == 0) show = true //判断上下两条消息的时间差决定是否显示时间,这里设置了2分钟:120000毫秒,可自行修改 else { if (Date.now() - this.data.chats[this.data.chats.length - 1].sendTimeTS > 120000) show = true } const _ = db.command //消息空白处理 if (!that.data.textInputValue) { wx.showToast({ title: '不能发送空白信息', icon: 'none', }) return } //消息内容赋值 const doc = { openid: that.data.openid, msgText: "text", textContent: that.data.textInputValue, sendTime: util.formatTime(new Date()), sendTimeTS: Date.now(), showTime: show, } //添加数据库表中该记录的records数组,并跳转页面到底部 chatroomCollection.where({ _openid: _.or(_.eq(that.data.openid), _.eq(that.data.match_openid)), match_openid: _.or(_.eq(that.data.openid), _.eq(that.data.match_openid)) }) .update({ data: { records: _.push(doc) } }) .then(res => { that.goBottom() }) //消息设空 that.setData({ textInputValue: "" }) }, goBottom() { wx.createSelectorQuery().select('#page').boundingClientRect(function (rect) { if (rect) { // 使页面滚动到底部 wx.pageScrollTo({ scrollTop: rect.height + 4 }) } }).exec() }, }) 其中,util.js内容如下: const formatTime = date => { const year = date.getFullYear() const month = date.getMonth() + 1 const day = date.getDate() const hour = date.getHours() const minute = date.getMinutes() const second = date.getSeconds() return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}` } const formatNumber = n => { n = n.toString() return n[1] ? n : `0${n}` } module.exports = { formatTime } 一个简单的demo就完成了,大家有什么问题欢迎随时q我。 -----------完结撒花----------
2021-11-18 - 「笔记」字节跳动小程序如何接入腾讯云CloudBase?
前言 最近在把微信小程序迁移至字节跳动小程序,由于服务端使用了腾讯云 CloudBase,网上搜索了一遍,文章千篇一律,都是复制腾讯云官方1年以前的适配器文档,在经过和腾讯云官方技术人员沟通后终于成功解决问题。 安装 npm i @cloudbase/js-sdk -S npm i @maoyan/cloudbase-adapter-tt_mp -S 使用 由于字节跳动小程序没有提供getAccountInfoSync()接口,无法通过接口获取appId 所以需要将appId设置到字节跳动小程序app对象上。 [代码]App({ onLaunch(options) { this.appId = appId } }) [代码] 腾讯云 CloudBase 安全配置 由于字节跳动小程序使用云开发不享受微信生态下的免鉴权,要在终端应用(如APP、小程序等)中使用云开发的身份验证服务,需要将授权的应用加入白名单,并在SDK使用时传入分配的凭证信息。 腾讯云 CloudBase 登陆授权 为了增加安全性,建议开启匿名登陆。启动匿名登录后,用户将不需要登录即可访问应用。如果有更严格的安全要求,可以自行开启其它身份验证方式。 完整代码 [代码]import tcb from '@cloudbase/js-sdk'; import { adapter } from '@maoyan/cloudbase-adapter-tt_mp'; let app; App({ onLaunch(options) { // appId必须设置 this.appId = "字节跳动小程序的appid"; tcb.useAdapters(adapter); // 腾讯云共享环境初始化 app = tcb.init({ env: '云环境id', appSign: '应用标识', // 需要设置成字节跳动小程序的appid appSecret: { appAccessKeyId: '版本', appAccessKey: '凭证' } }) // 匿名登陆 const auth = app.auth() const loginState = auth.anonymousAuthProvider().signIn() let data = await app.callFunction({ name: "云函数名", data: "参数" }); console.log(data) } }) [代码]
2022-03-03 - [已解决]利用云开发解决小程序加载自定义字体无效果问题
终极效果 效果要求:使得最终页面效果在开发者模拟器、安卓、iOS都可正常显示字体效果。 [图片] 问题背景 如何在微信小程序上利用wx.loadFontFace方法加载自己要上传的字体的文件一直是困扰很多开发者的问题,很多人反映使用该方法在开发者工具模拟器上是可以显示的,有的开发者说在模拟器和iOS系统上可以正常显示自定义字体,但是安卓机上无法正常显示。 很多人为了能够实现加载自定义字体想了很多办法,比如 方法1: 字体文件转base64代码(如网站https://www.transfonter.org) ,然后存储在wxss文件中。这也是我曾使用的方法之一,确实很好用,安卓/苹果机上都可以正常实现效果。 缺点:但是面对字体文件包一般都很大的中文字体来说,转换成base64代码是极容易出现仅用来引用字体的wxss代码就超过2M的情况。 根据小程序的开发规矩,即使采用分包形式开发一个小程序,单个分包的代码量也是不能超过2M的,此时就是该方法的鸡肋。 方法2: 也有开发者利用iconfont上的在线引用方法,把自己会用到的字输进入然后点击生成字体,引用一个url即可实现。这种方法也是可行的。 缺点:但是对于部分字多或者可能出现用户输入文字的情况,这种方法就不太方便。 解决方案 今天,和大家讲的就是wx.loadFontFace方法,也是很多人一直在尝试,执着于想要利用这种方法实现。 在小程序开发者文档中,这一段文字是你不陌生的。 wx.loadFontFace(Object object) 基础库 2.1.0 开始支持,低版本需做兼容处理。 本接口从基础库版本 2.15.0 起支持在小程序插件中使用 动态加载网络字体,文件地址需为下载类型。‘2.10.0’起支持全局生效,需在 app.js 中调用。 注意: 字体文件返回的 contet-type 参考 font,格式不正确时会解析失败。 字体链接必须是https(ios不支持http) 字体链接必须是同源下的,或开启了cors支持,小程序的域名是servicewechat.com canvas等原生组件不支持使用接口添加的字体 工具里提示 Faild to load font可以忽略 ’2.10.0’ 以前仅在调用页面生效。 ——来源于《微信小程序开发者文档》 分析: 注意点1是大家一般无需担心的,我们下载到的字体文字很多是ttf文件,都是符合相关要求的。 注意点2也是一般不会犯错的,大家都会避开这个。 注意点3是非常重要的,也是很多开发者不明白的,下面,我会着重讲如何解决这个问题,解决了这个问题,无论调试还是真机都能正常显示。 在开发者文档中,有这样一段代码: [代码]wx.loadFontFace({ family: 'Bitstream Vera Serif Bold', source: 'url("https://sungd.github.io/Pacifico.ttf")', success: console.log }) [代码] 可以看出使用的是https链接,或许你曾经拿这段代码测试过。 或者你也曾经把字体文件上传到一些存储空间然后得到上传后文件的地址,或者说你曾经在开发者社区看到别人上传的字体文件的https链接然后来调用。 在开发者工具模拟器上正常显示,一到真机就显示不了。 当然为了想要使用我自己喜欢的字体,得到该字体的文件链接,我也突然脑洞大开,尝试把字体文件上传到云开发的云存储上,然后得到一个FileID链接和一个下载链接。 随后在页面或者全局的JS中加载该字体文件: 代码: [代码]loadFontFace() { wx.loadFontFace({ family: 'XXX', source: 'url("xxxxxx.ttf")', success(res){ console.log('res', res) }, fail(err){ console.log('err', err) } }) }, [代码] 遗憾的是,也是能在模拟器中显示出自定义字体效果,在安卓的真机上无法正常显示,iOS未知(我没有iOS系统故无法测试)。 到底是怎么回事,问题出在哪呢?于是一遍遍琢磨开发文档中的注意事项“字体链接必须是同源下的,或开启了cors支持,小程序的域名是servicewechat.com”。 后来琢磨后面一句话,我也是不明白啥是cors,于是就搜索了,记得其中一篇文章就讲到腾讯云的cors之类的。 操作步骤 1 进入腾讯云的官网(https://cloud.tencent.com),然后登录账号,选择公众号小程序登录,扫码并选择需要实现自定义字体的小程序进行登录 2 在顶部菜单栏找到“对象存储” [图片] 3 存储桶列表中新建一个存储桶 [图片] 4 给存储桶设置配置,跨域访问中设置好“cors规则”,把https://servicewechat.com域名填写到来源Origin的方框内。 [图片] 现在再来读读“字体链接必须是同源下的,或开启了cors支持,小程序的域名是servicewechat.com”是不是有了新的体会。 5 把需要使用的字体文件上传到该存储桶,然后点击文件右边的“详情”,你就会看到“对象地址”,这个地址就可以粘贴到JS文件的wx.loadFontFace使用。 [图片] 6 不要忘了设置刚刚上传的字体文件“访问权限”为“公有读私有写”,这样每个用户都可以读取这个字体文件了。 源码分享 JS文件 [代码]loadFontFace() { wx.loadFontFace({ family: 'XXX(你给字体拟的名称,最好英文如kaiti)', source: 'url("对象地址")', success(res){ console.log('res', res) }, fail(err){ console.log('err', err) } }) }, [代码] WXSS文件 [代码]page{ font-family: 'XXX'(你给字体拟的名称,最好英文如kaiti); } [代码] 或者 [代码].xxx(class名){ font-family:'xxx(你给字体拟的名称,最好英文如kaiti)' } [代码]
2021-04-13 - 小程序短信验证码登录,1分钟实现小程序发短信功能,借助云开发10行代码实现短信验证码登录小程序
老规矩先看效果图 普通短信 [图片] 验证码短信 [图片] 今天被云开发官方告知,云开发支持发短信功能了,然后就迫不及待的来尝下鲜。 进入官方文档一看,云开发给咱们开发者的福利还真不小。 不仅仅可以很方便的使用短信功能,还送了咱们1000条免费短信。不用白不用嘛。这1000条短信足够咱们把小程序短信功能,和小程序短信验证码功能都学会了。 废话不多说了,咱们直接来撸代码 一,使用云开发短信的条件 这个前置条件很重要,条件不满足,你就没法使用云开发短信功能。 使用条件 1,必须是企业小程序,目前个人小程序无法使用短信发送 2,必须开通静态网站功能(后面应该会逐步放开) 3,必须开通云开发(这个没得说,不开通云开发你还用啥云开发功能啊) 上面条件都满足以后,我们就可以来愉快的撸代码了。 二,开通静态网站功能 如果你不开通静态网站,直接调用短信发送,会报如下错误。 [图片] 其实官方文档里也有给出这个错误。 [图片] 那么我们就来开通静态网站功能。开通静态网站功能之前,必须开通云开发,配置好云开发的环境。这些我在云开发入门里讲过很多遍。还不知道的同学可以翻看下我前面的文章或者视频:https://edu.csdn.net/course/detail/26572 这里开通云开发我们借助小程序开发者工具来实现快速开通。 2-1,注册小程序 这里我就不再多说了,只有注册过小程序的appid才可以开通云开发 [图片] 我们注册好小程序后,就可以拿到appid了,如上图 2-2,创建一个小程序项目 小程序项目的创建,我这里不再多说,我前面小程序基础课里有讲过很多遍。《小程序基础学习》 [图片] 这里强调一点,就是创建小程序项目时一定要用我们自己的appid不要用测试号。 [图片] 如果你一开始是用测试appid创建的,也可以通过上图的方式更换成自己的小程序的appid。 2-3,开通云开发 这里云开发的开通,我就不做过多讲解了,我云开发课程里也讲过很多遍。大家可以去翻看下 [图片] 只需要点击开发者工具里的云开发按钮,跟着提示一步步操作就可以快速开通云开发。 2-4,开通静态网站功能 [图片] 我们上面云开发开通好以后,就可以在这里快速开通静态网站了。 [图片] 点击以后,直接点击开通即可 [图片] 这时候开通有个条件 [图片] 我们必须按照要求改变自己小程序的付费方式,把我们的付费方式改成按量付费即可。 [图片] 这里不用担心,这里的按量付费,每月都有免费额度。这些额度我们开发学习基本上够用了 [图片] [图片] 这个时候我们的静态网站功能就开通成功了。 [图片] 开通成功以后如下图。 [图片] [图片] 三,编写发送短信的云函数 其实上面静态网站功能开通以后,我们不用上传网站资源,就可以直接来使用短信功能了。 下面我们就来使用云开发的云函数功能来做短信发送功能。 老规矩先看效果图 [图片] 代码编写也很简单 [图片] 其实发送短信的代码很简单,就上面这几行。下面就来教大家如何编写这个云函数。 3-1,初始化云开发环境id 新建一个和pages平级的目录cloud,用于存放云函数 [图片] 然后在project.config.json里添加cloudfunctionRoot选项。 [图片] 然后对cloud选择当前环境 [图片] 在app.js里配置环境变量 [图片] 这个env环境id需要你去云开发控制台获取 [图片] 3-2,创建云函数 右键cloud目录,新建Node.js云函数 [图片] 然后新建一个云函数,名字你可以自定随便定。我这里用sendSms [图片] 3-3,编写云函数 [图片] 我这里把代码贴给大家,记得把env和接收短信的手机号换成你自己的。 [代码]const cloud = require('wx-server-sdk') cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) exports.main = async (event, context) => { try { const result = await cloud.openapi.cloudbase.sendSms({ env: 'xiaoshitou-zfl2q', content: '编程小石头发布了新的能力', phoneNumberList: [ "+8615611823564" ] }) return result } catch (err) { return err } } [代码] 3-4,部署云函数 上面云函数编写好了,一定要记得部署下云函数。右键sendSms然后点击下面箭头所示的即可。 [图片] 上传部署成功后,会有下面这样的提示 [图片] 四,调用云函数发送短信 我们上面云函数编写并部署成功以后,就可以来调用这个云函数,发送短信了。 4-1,编写wxml文件 在wxml文件里写一个button按钮,编写一个bindtap点击事件 [图片] 4-2,编写js文件 在js文件里实现上面button的点击事件,然后调用云函数 [图片] 调用云函数时,一定要记得这里的name必须和你的云函数名一模一样。 4-3,点击发送短信 点击发送短信 [图片] 点击发送 短信以后,可以看到日志里打印openapi.cloudbase.sendSms:ok 这就代表发送成功了。 然后再看下手机,收到下面的短信。 [图片] 到这里我们的短信发送功能就完整的实现了。 其实到这里该实现的功能,就已经实现了。但是我们使用短信场景更多的是用短信发送验证码。所以接下来给大家做一个发送短信验证码的例子出来 实战案例~发送验证码短信 老规矩,先看效果图 [图片] 我们只需要获取用户输入的手机号,然后点击获取验证码,最后输入短信里接收到的验证码,进行验证即可。 1,编写wxml 页面比较简单,就两个输入框和两个按钮 [图片] 2,编写js js里主要是获取用户输入的手机号,然后发送验证码,发送验证码调用云函数实现短信验证码发送功能。用户输入验证码以后进行校验即可。 [图片] 3,发送短信验证码 用户输入手机号以后,点击发送,可以看到我们手机上收到了如下短信。 [图片] 然后用户输入获取到的验证码,点击验证。 [图片] 可以看到验证成功,验证成功以后后面的操作就可以自己定了,比如验证成功以后跳转到登录成功页。 到这里我们就实现了验证码发送功能了。 生成随机验证码的方法 我这里把生成随机验证码的方法贴给大家。 [代码] //获取随机验证码,n代表几位 generateMixed(n) { let chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']; let res = ""; for (var i = 0; i < n; i++) { var id = Math.ceil(Math.random() * 35); res += chars[id]; } return res; } [代码] 我后面会专门录制讲解视频 官方文档: https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/cloudbase/cloudbase.sendSms.html 付费视频(含源码和笔记): https://edu.csdn.net/course/detail/26572 完整免费视频(记得三连):https://www.bilibili.com/video/BV1Ca4y1n73j/
2021-01-09 - 微信访问网站被限制的相关问题
一、哪种行为或内容不应在朋友圈出现? 我们鼓励用户自发地分享所见所闻,但反对所有违反《微信外部链接内容管理规范》的内容或行为。 二、如果我的链接违反了《微信外部链接内容管理规范》将会被怎样处理? 对于违反《微信外部链接内容管理规范》的内容,一经发现将立即进行处理,包括但不限于停止链接内容在朋友圈继续传播、停止对相关域名或IP地址进行访问、屏蔽相关链接等。 由微信公众平台或开放平台帐号施行或者发起的,一经查实,前述帐号、主体也将按照微信相关规则进行处罚,包括但不限于限制或禁止使用部分或全部功能、帐号封禁直至注销等,并公告处理结果;微信也有权依照本规范及相关协议、专项规则的规定,拒绝再向前述主体提供服务。 三、我的链接被禁止在微信访问,如何才能恢复正常访问? [图片]注: 1、链接的封禁时间将根据链接的累计违规次数(最近半年)来判定。被禁止访问的链接若不发起解封申请,将不予解封。若出现解封申请的数量过多,审核团队无法较快处理的情况,对于超出封禁时间的链接,审核通过后立即解封。 2、首次违规的链接修改完可申请解封,经平台评估符合规范的链接可申请解除处理,第二次封禁12小时,第三次封禁一天,第四次及以上封禁一周。之后若未修改完成不予解封。对于重复、情节严重或多次违规的行为,平台将视具体情节采取不同程度的阶梯处罚措施。 四、我的链接在朋友圈分享了之后仅自己可见,怎么办? 1、若此域名未在工信部ICP备案,分享频率会受到限制,请先完成备案。点击这里了解详情。 2、请根据《微信外部链接内容管理规范》检查该页面所用的域名、IP地址下是否存在违规内容。若存在,请修改页面内容。 3、确认域名、IP地址不存在违规内容,可以通过电子邮件发送至腾讯指定邮箱:moment@tencent.com进行反馈。 邮件标题请采用如下格式: 【链接解封反馈】“反馈人或企业” + “页面主题” 正文请附上仅自己可见的链接以及情况说明。 Q:公众号发的图文消息是否受影响? A:微信公众号图文消息的域名是已备案域名:qq.com。因此,公众号推送的图文消息不受频率限制的影响。 Q:未备案域名分享频率是否会受到限制? A:未备案的一级域名每天分享至朋友圈的次数将有限制。 Q:不备案会出现什么情况? A:未备案域名,分享达一定次数后,再分享将仅自己可见。 Q:公众号阅读原文或编辑文案中插入了网址需要备案吗? A:阅读原文或文中插入的网址没有强制备案要求。若用户点击此网址后并将其分享到朋友圈,需遵循备案要求。 Q:为何个别域名已经备案了,在朋友圈还是分享仅自己可见? A:可查看该域名是否违反了《微信外部链接内容管理规范》,具体可点击查看:朋友圈管理常见问题 五、如果我的应用被禁止在朋友圈分享,如何才能解封? 1、请根据《微信外部链接内容管理规范》检查应用是否存在违规内容,若存在,请进行修改。 2、修改后,可以通过电子邮件发送至腾讯指定邮箱:moment@tencent.com申请解封。 注:若公众帐号功能被封禁,请按公众平台的相应提示等待解封,目前此邮箱(moment@tencent.com)不接受公众帐号解封申请。 邮件标题请采用如下格式: 【应用解封反馈】“反馈人或企业” + “应用名称” 正文请附上开放平台应用appid和分享链接,以及情况说明。 六、如果我的链接因被他人恶意利用生成违规内容而限制在微信内分享,怎么办? 1.点击“申请恢复访问”按钮,跳转“更多信息页”查看具体被恶意利用的链接; 2.根据违规链接核实被注入情况,修复漏洞,清理违规内容。(腾讯安全应急响应中心博客:xss漏洞解决方案https://security.tencent.com/index.php/blog/msg/53) 3.确认漏洞彻底修复后,提交解封申请。 被注入页面违规内容样式示例: [图片]
2019-11-21 - 小程序云开发训练营
[图片] 微信小程序已经成为一种新的应用形态,为众多开发者带来日趋完善的生态服务和不断丰富的开放能力,特别是小程序开放的云开发能力,可以帮助开发者快速构建微信小程序的后端服务。 本次微信小程序应用开发赛(以下简称“大赛”)的参赛作品应为具有适用场景和对应功能的原创性微信小程序,期望参赛队伍以微信小程序平台以及微信小程序云开发等技术和服务为基础,设计和开发具有实际需求或未来前景的创新应用。对于使用小程序云开发实现的大赛作品(以下简称“云开发小程序”),将独立保证入围赛区决赛名额,并在全国决赛中单独设立云开发奖项。 为了帮助更多在校学生理解小程序云开发相关知识,并更加规范、高效地打造云开发小程序应用,特开设小程序云开发训练营,通过体系化的课程内容,较为完整地介绍小程序云开发的系列知识,完整参与还可获得由腾讯云云开发提供的学习礼品。 *课程内容完全基于官方的开放文档和教程进行设置,无任何新增或特殊内容,不影响大赛的正常报名、参赛和作品提交等全部流程。 *建议收藏本页以便后续学习。 一、课程设置: 1、学习指引:小程序云开发知识分等级梳理(以文档为主,更多教程与视频可前往微信学堂或CloudBase社区官网) (1)小程序云开发基础能力(在微信小程序中可以基础使用) 【文档】 云数据库基本使用 云存储基本使用 云函数基本使用 云调用的认识和基本使用 【视频】 云开发基础等 (2)小程序云开发进阶能力(在小程序之外的延伸场景中使用) 使用CMS内容管理实现数据管理 使用静态网站托管制作微信公众号H5 未登录模式的使用(小程序分享朋友圈) 云函数进阶用法:灰度/版本管理,高级日志,定时触发器 数据库实时数据推送 (3)小程序云开发高阶能力(对云开发更加熟悉) 云托管的认识和使用 数据库安全规则的学习 跨账号环境共享的认识 深度理解云函数运行原理 云开发接入微信支付的学习 云开发HTTP API的学习 了解第三方服务商模式开发 更多学习资源:微信学堂、CloudBase社区官网 2、互动直播 4月7日 晚19:00 小程序云开发基础能力讲解 查看回放 4月14日 晚19:00 小程序云开发进阶能力讲解 查看回放 4月21日 晚19:00 小程序云开发高阶能力&案例讲解 查看回放 直播地址:腾讯云云开发 视频号 [图片] *回放视频将沉淀在微信学堂、腾讯云云开发同名B站账号。 二、参与方式 大赛进行期间,可随时自主学习。完成结课作业,还可获得额外奖励: 结课作业:基于课程内容和自身的学习成果,输出一份云开发学习报告,内容需与云开发相关,主题不限(学习心得/参赛经历感悟/建议反馈/实战案例分享等均可),形式不限(文章/视频等均可),提交至 CloudBase@tencent.com。 具体提交模板: 邮件名称:【云开发训练营】姓名 + 学校名称 + 题目 邮件正文需包含: 主题:学习心得/参赛经历感悟/建议反馈/实战案例分享/ 其他正文内容:如有视频可注明视频地址。参与大赛的小程序 AppID(用于验证是否参赛)队友信息(用于验证是否参赛)联系方式:微信号/QQ号收货信息(用于邮寄礼品)个人简历(建议以 PDF 附件形式发送)作业提交日期:2021年6月1日至2021年7月15日(非规定日期内发送无效) 提交的结课作品,要求不得出现: 违反相关法律、法规、政策规定以及微信相关规则的行为; 涉嫌抄袭或侵犯他人知识产权的行为; 涉及不健康、淫秽、色情或毁谤第三方的内容。 三、奖品设置 在大赛中提交云开发小程序作品,且在规定时间内提交结课作业的同学可获得如下奖品: 参与即送: 小程序云开发技术书《云开发:小程序开发原来如此简单》 优秀参与者可获得: 云开发布道师申请资格 云开发CloudBase实习面试机会(具体岗位视具体情况而定) 优秀参与者还可在如下奖品中任选一个,每种奖品数量有限送完即止(按照结课作业提交顺序进行选择): [图片] *图片仅供参考,实际奖品选择与发放将视官方周边更新与存货情况进行适当调整
2021-06-01 - 如何一键获取云存储中指定文件夹的所有图片url地址
云存储中的图片地址,是需要用cloudId或者路径来换取。像这样: .getTempFileURL({ fileList: ["cloud://a/b/c", "cloud://d/e/f"] }) .then((res) => { // fileList 是一个有如下结构的对象数组 // [{ // fileID: 'cloud://webtestjimmy-5328c3.7765-webtestjimmy-5328c3-1251059088/腾讯云.png', // 文件 ID // tempFileURL: '', // 临时文件网络链接 // maxAge: 120 * 60 * 1000, // 有效期 // }] console.log(res.fileList); }); 但是怎么能批量获取云存储中指定文件夹的图片或者文件的cloudID或着路径,然后来换取临时链接呢? [图片] 很简单 我们首先需要通过node.js管理端SDK(https://docs.cloudbase.net/api-reference/manager/node/storage.html#listdirectoryfiles)的API中 listDirectoryFiles来获取指定文件的所有文件 const result = await storage.listDirectoryFiles("testfiles/img/"); 调用结果如下 [图片] 它的结构是这样 { Key: 'testfiles/img/13f5e8de79ba426feff3987b LastModified: '2021-03-23T06:23:53.000Z', ETag: '"13f5e8de79ba426feff3987be102f012"', Size: '333884', Owner: { ID: '1304607081', DisplayName: '130 StorageClass: 'STANDARD' }, 然后我们需要的便是Key这个数据,因为它对应的是我们文件的路径。但是需要注意的是,返回的数据第一个我们需要去掉,因为它是指定文件夹的根目录,没有意义。 [图片] 所以我们需要这样做 //删除第一个元素 result.splice(0, 1); 接着把Key提取出来 let requestList = []; //把key提取出来 result.map((value) => { requestList.push(value['Key']); }); 因为换取url的接口格式和参数如下 storage.getTemporaryUrl([ { cloudPath: "files/data.txt", maxAge: 86400, }, ]); 传进一个包含cloudPath也就是我们提取出来路径,还有一个url有效的时间 [图片] 所以我们需要构建一个这样的数组 let fileIdList = [] //构建请求文件fileID数组 fileIdList = requestList.map((value) => { return { cloudPath: value, maxAge: 1800 } }) 打印的结果如下 [图片] 已经接近我们想要的了,最后我们只需要调用换取临时连接url的接口就可以了 把fileIdList传进去getTemporaryUrl接口里。获取结果 let responseList = []; //请求临时链接 responseList = await storage.getTemporaryUrl(fileIdList); console.log(responseList); 让我们来看看打印结果 [图片] url就是我们需要的地址了。 完结撒花! [图片]
2021-03-24 - 如何使用微信小程序·云开发的Node.js云函数生成Word文档(2021-10-15更新)
编者按 近期一个云开发项目有生成Word文档的需求,经过搜索,发现并没有小程序·云开发有关生成word文档的案例,因为本人还是本科生且非科班出身,一路摸着石头过河,遇到了不少困难,期间还试图向社区的大佬们求助;花了两天时间才搞定这一百行代码,现在分享给大家。 代码有些糙,希望大佬们不要嫌弃。 一、安装云函数依赖officegen、fs 工欲善其事必先利其器,我们知道云函数代码运行在云端Node.js环境中,因此,理论上来说,Node.js能做的事情,小程序·云开发的云函数基本上也能做到。officegen是Github上一款生成微软Office文档的工具,包括.docx、.xlsx、.pptx三种文件,由于我只用了.docx,本文将以Word文件为例。 https://github.com/Ziv-Barber/officegen [图片] 1. 首先我们在微信开发者工具中 新建一个云函数 => 右键云函数名 => 在终端中打开 [图片] 2. npm安装依赖officegen和fs,为了方便本地调试云函数,我们这里也安装wx-server-sdk。 [图片] 代码如下,请逐个安装,如果安装有问题,可以自行搜索“npm”或“npm taobao 镜像” ;这里不再赘述。 npm i officegen npm i fs npm i wx-server-sdk 3. 在云函数index.js开头写下以下代码,引用我们刚刚安装的包。 const cloud = require('wx-server-sdk') const officegen = require('officegen'); const fs = require('fs'); const docx = officegen('docx'); 二、创建Word文档的内容 文档地址: https://github.com/Ziv-Barber/officegen/blob/master/manual/docx/README.md 1. 首先我们根据文档定义(Ctrl CV)两个函数 //文档生成完成后调用,后来其实发现没啥用 // Officegen calling this function after finishing to generate the docx document: docx.on('finalize', async function (written) { console.log('Finish to create a Microsoft Word document.') }) //生成文档出现问题时调用 // Officegen calling this function to report errors: docx.on('error', function (err) { console.log(err) }) 2. 创建段落API: docx.createP(options) //声明一个创建段落的变量p0bj let pObj = docx.createP(options) //创建一个段落并插入文本 pObj = docx.createP({ align: 'center' //文字对齐方式,center、justify、right;默认为left indentLeft = 1440; // 段落缩进 Indent left 1 inch indentFirstLine = 440; // 首行缩进 }) pObj.addText('你要插入的文字,这里可以时变量', { bold: true, //是否加粗,默认false font_face: 'KaiTi', //字体,这里以“楷体为例”,如果填写了打开文档的电脑没有安装的字体名称,将使用默认字体。能不能用中文,我没试过。 font_size: 19, //字号 color: '595959' //文字颜色 }); 上述例子外,还可以添加下划线、设置斜体、超链接、分页等;还可以编辑页眉和页脚、插入图片等。详见后续代码示例或officegen文档。 3. 插入图片 这里以插入小程序码为例,直接上代码。 要注意的是officegen似乎不支持以buffer形式插入图片,因此要先将图片保存。 //首先定义一个用于保存小程序码图片的函数 //save QR saveFile = function (filePath, fileData) { return new Promise((resolve, reject) => { const wstream = fs.createWriteStream(filePath); wstream.on('open', () => { const blockSize = 128; const nbBlocks = Math.ceil(fileData.length / (blockSize)); for (let i = 0; i < nbBlocks; i += 1) { const currentBlock = fileData.slice( blockSize * i, Math.min(blockSize * (i + 1), fileData.length), ); wstream.write(currentBlock); } wstream.end(); }); wstream.on('error', (err) => { reject(err); }); wstream.on('finish', () => { resolve(true); }); }); } //要获取小程序码,首先要修改云函数config.json文件中的云调用权限 { "permissions": { "openapi": [ "wxacode.getUnlimited" ] } } //在云函数main中获取小程序码 //https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.get.html const result = await cloud.openapi.wxacode.getUnlimited({ page: 'pages/check/check', //小程序页面地址,必须是线上版本中存在的页面的完整地址 scene: '', //小程序码参数 width: 240, //小程序码的宽度(是个正方形) }) const QRcode = result.buffer await saveFile('/tmp/qr.jpg', QRcode); // 这里的fileData是Buffer类型,关于路径会在第三部分生成Word文件中解释。 //将图片插入到文档中 pObj = docx.createP() //创建段落 pObj.options.indentFirstLine = 440; //首行缩进 pObj.addImage('/tmp/qr.jpg', { //图片文件路径 cx: 140, //长度 cy: 140 //宽度 }); 三、生成Word文件 文档内容完成后,就可以生成文档了。officegen似乎只能生成文件,没有文件buffer的接口,而要上传到小程序·云开发的云存储中,只能使用Buffer或fs.ReadStream,怎么办呢?先把文件保存下来再读取呗。 首先提一下云函数运行环境 https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/functions/mechanism.html 云函数运行在云端 Linux 环境中,一个云函数在处理并发请求的时候会创建多个云函数实例,每个云函数实例之间相互隔离,没有公用的内存或硬盘空间。云函数实例的创建、管理、销毁等操作由平台自动完成。每个云函数实例都在 [代码]/tmp[代码] 目录下提供了一块 [代码]512MB[代码] 的临时磁盘空间用于处理单次云函数执行过程中的临时文件读写需求,需特别注意的是,这块临时磁盘空间在函数执行完毕后可能被销毁,不应依赖和假设在磁盘空间存储的临时文件会一直存在。如果需要持久化的存储,请使用云存储功能。因此,我们将文件保存在/tmp路径下,文件名随便起,这里我取为exampl.docx。生成文档的代码如下: // Let's generate the Word document into a file: let out = fs.createWriteStream('/tmp/example.docx') // Async call to generate the output file: docx.generate(out) 理论上来说,我们文档生成完毕后,通过fs.ReadFileStream读取文件调用cloud.uploadFile()即可上传到云存储 const fileStream = fs.createReadStream('/tmp/example.docx') return await cloud.uploadFile({ cloudPath: '/tmp/example.docx', fileContent: fileStream, }) 而在测试过程中我发现,云端测试时,云函数调用超时。而后使用本地调试查看问题出在何处。 云函数本地调试的方法不再赘述,看这里即可。https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/functions/local-debug.html 通过本地调试,发现cloud.uplodaFile()的网络请求始终时挂起(pending)状态,没有传输数据。 [图片] 经过一天的调试,通过监听文件,发现officegen生成文件完成,执行了我们开头复制粘贴的生成文档后执行的docx.on("finalize",)函数,打印文档生成成功的日志后,仍有文件变动,也就是说,文件并没有生成完毕。这就导致了后续步骤的失败。 当时调试的界面我没有保存,就贴一下fs监听文件的代码吧。 let watcherObj = '/tmp/example.docx' //eventType 可以是 'rename' 或 'change'; 当改名或出现或消失的时候触发rename; recursive:是否监听到内层子目录,默认false; try { let myWatcher = fs.watch(watcherObj,{encoding:'utf8',recursive:true},(event,filename) => { if(event == 'change'){ console.log("触发change事件") } console.log(event) //encoding:文件名编码格式,buffer、默认:utf8等;filename有可能为空 if(filename){ console.log('filename: ' + filename) } }) //change 事件会触发多次 myWatcher.on('change',function(err,filename){ console.log(filename + '发生变化'); }); //50秒后 关闭监视 setTimeout(function(){ myWatcher.close() },5000); } catch (error) { console.log('文件不存在!!') } 为解决这一问题,我最先想到了await,结果发现await对officegen生成文档的接口并不起作用;最终我用了最原始的笨办法:用setTimeout等一会儿再读取文件,大佬们有更好的解决方案还请赐教。 return new Promise((resolve, reject) => { setTimeout(async function () { let data = fs.readFileSync('/tmp/example.docx'); let bufferData = new Buffer.from(data, 'base64'); console.log(bufferData); setTimeout(async function () { resolve(await cloud.uploadFile({ cloudPath: varpath, fileContent: bufferData, })); }, 1000); //等文件再读1秒 }, 6300); //等文件再写一会儿。根据自己的需求调试后确定等待时长,要预留出一定时间确保文档完全生成完毕。 }) //最终返回内容为文件云存储中的CloudID。 四、完整核心代码 const cloud = require('wx-server-sdk') const officegen = require('officegen'); const fs = require('fs'); const docx = officegen('docx'); cloud.init({ env: '这里填入你的云环境' }) // Officegen calling this function after finishing to generate the docx document: docx.on('finalize', async function (written) { console.log('Finish to create a Microsoft Word document.') }) // Officegen calling this function to report errors: docx.on('error', function (err) { console.log(err) }) //save QR saveFile = function (filePath, fileData) { return new Promise((resolve, reject) => { const wstream = fs.createWriteStream(filePath); wstream.on('open', () => { const blockSize = 128; const nbBlocks = Math.ceil(fileData.length / (blockSize)); for (let i = 0; i < nbBlocks; i += 1) { const currentBlock = fileData.slice( blockSize * i, Math.min(blockSize * (i + 1), fileData.length), ); wstream.write(currentBlock); } wstream.end(); }); wstream.on('error', (err) => { reject(err); }); wstream.on('finish', () => { resolve(true); }); }); } // 云函数入口函数 exports.main = async (event, context) => { var time = new Date() var filePath = 'exportVoluntaryData' var fileName = "zyzm" + Date.parse(new Date()) + '.docx' var varpath = filePath + '/' + fileName //get QRcode const result = await cloud.openapi.wxacode.getUnlimited({ page: 'pages/check/check', scene: item._id, width: 240, }) const QRcode = result.buffer await saveFile('/tmp/qr.jpg', QRcode); // Add a Footer: var footer = docx.getFooter().createP(); footer.addText('XXXX证明_' + item._id, { font_size: 10 }); footer = docx.getFooter().createP(); footer.addText(time.toString(), { font_size: 10 }); //下方开始文档每一页的循环 for (var i in item.volunteerInfo) { //标题 let pObj = docx.createP({ align: 'center' }) pObj.addText('XXX证明', { bold: true,XXX font_face: 'KaiTi', font_size: 19, color: '595959' }); //此处省略了一些正文内容 pObj = docx.createP() pObj.options.indentFirstLine = 440; pObj.addText('微信扫描下方小程序码,可核验此证明。', { font_face: 'FangSong', font_size: 12, color: '595959', italic: true, }); pObj = docx.createP() pObj.options.indentFirstLine = 440; pObj.addImage('/tmp/qr.jpg', { cx: 140, cy: 140 }); pObj = docx.createP() pObj = docx.createP({ align: 'right' }) pObj.addText('落款', { font_face: 'FangSong', font_size: 15, color: '595959' }); if (i != ((item.volunteerInfo).length - 1)){ docx.putPageBreak() //分页 } } // Let's generate the Word document into a file: let out = fs.createWriteStream('/tmp/example.docx') // Async call to generate the output file: docx.generate(out) return new Promise((resolve, reject) => { setTimeout(async function () { let data = fs.readFileSync('/tmp/example.docx'); let bufferData = new Buffer.from(data, 'base64'); console.log(bufferData); setTimeout(async function () { resolve(await cloud.uploadFile({ cloudPath: varpath, fileContent: bufferData, })); }, 1000); }, 6300); }) } 本人非计算机相关专业本科生,且本文大部分内容为手打,难免会有差错和疏漏,还请各位指教。 希望本文对你有所帮助。 Soochow University. HaoChen. 2020年2月 ======= 2021-10-15更新 ======= 经过一段时间的使用,上述内容主要存在两点问题:(1)难以判断文件何时生成完毕;(2)连续调用生成文档时,若上一个云函数实例未被销毁,会出现文件内容重复和错乱的问题。 前一段时间进行了更新,因为工作学习忙碌,此次暂不做详解,代码如下。 入口文件index.js// 云函数入口文件 delete require.cache[require.resolve('officegen')]; const cloud = require('wx-server-sdk') var office = require('office.js'); //https://github.com/Ziv-Barber/officegen/blob/master/manual/docx/README.md cloud.init({ env: 'sudaxmt1900' }) const db = cloud.database() const _ = db.command // 云函数入口函数 exports.main = async (event, context) => { return await office.genWord(event); } office.jsconst cloud = require('wx-server-sdk') const fs = require('fs'); function delDir(path) { console.log("delete Dir") let files = []; if (fs.existsSync(path)) { files = fs.readdirSync(path); files.forEach((file, index) => { let curPath = path + "/" + file; if (fs.statSync(curPath).isDirectory()) { delDir(curPath); //递归删除文件夹 } else { fs.unlinkSync(curPath); //删除文件 } }); // fs.rmdirSync(path); // 删除文件夹自身 } } readDocx_fs = function (path) { return new Promise((resolve, reject) => { fs.readFile(path,(err,data)=>{ resolve(data); reject(err); }) }) } //save QR saveFile = function (filePath, fileData) { return new Promise((resolve, reject) => { const wstream = fs.createWriteStream(filePath); wstream.on('open', () => { const blockSize = 128; const nbBlocks = Math.ceil(fileData.length / (blockSize)); for (let i = 0; i < nbBlocks; i += 1) { const currentBlock = fileData.slice( blockSize * i, Math.min(blockSize * (i + 1), fileData.length), ); wstream.write(currentBlock); } wstream.end(); }); wstream.on('error', (err) => { reject(err); }); wstream.on('finish', () => { resolve(true); }); }); } exports.genWord = async (event) => { let officegen = require('officegen'); let fs = require('fs'); let docx = officegen('docx'); //ini delDir('/tmp') var item = event.item var filePath = 'exportVoluntaryData' var fileName = "21zyzm" + Date.parse(new Date()) + '.docx' var varpath = filePath + '/' + fileName //=========以下建构文档内容========== //get QRcode const result = await cloud.openapi.wxacode.getUnlimited({ page: 'pages/check/check', scene: item.id, width: 140, }) const QRcode = result.buffer await saveFile('/tmp/qr.jpg', QRcode); // 这里的fileData是Buffer类型 timeBottom = time.getFullYear() + '年' + (time.getMonth() + 1) + '月' + time.getDate() + '日' for (var i in item.volunteerInfo) { let pObj = docx.createP({ align: 'center' }) pObj = docx.createP({ align: 'center' }) pObj.addText('志愿服务时间证明', { bold: true, font_face: 'KaiTi', font_size: 19, color: '595959' }); pObj = docx.createP() pObj = docx.createP({ align: 'justify' }) pObj.options.indentFirstLine = 440; if (item.volunteerInfo[i].academy && item.volunteerInfo[i].major && item.volunteerInfo[i].grade) { var txt = item.volunteerInfo[i].academy + ' ' + item.volunteerInfo[i].major + '专业 ' + item.volunteerInfo[i].grade + ' ' + item.volunteerInfo[i].name + ' 同学(学号 ' + item.volunteerInfo[i].idnum + '),于 ' + date + '参加 ' + item.title + ' 工作,志愿服务时间达到 ' + item.hours + ' 小时。' } else { var txt = item.volunteerInfo[i].name + ' 同学(学号 ' + item.volunteerInfo[i].idnum + '),于 ' + date + '参加 ' + item.title + ' 工作,志愿服务时间达到 ' + item.hours + ' 小时。' } pObj.addText(txt, { font_face: 'FangSong', font_size: 15, color: '595959' }); pObj = docx.createP() pObj.options.indentFirstLine = 440; pObj.addText('特此证明。', { font_face: 'FangSong', font_size: 15, color: '595959' }); pObj = docx.createP() pObj.options.indentFirstLine = 440; pObj.addText('证明人:' + event.tea_info.name + ' ' + event.tea_info.phone, { font_face: 'FangSong', font_size: 15, color: '595959' }); pObj = docx.createP() pObj = docx.createP() pObj.options.indentFirstLine = 440; pObj.addText('微信扫描下方小程序码,可核验此证明。核验信息与此证明一致时,此证明不加盖公章仍然有效;若不一致,则以加盖公章的证明为准。', { font_face: 'FangSong', font_size: 12, color: '595959', italic: true, }); pObj = docx.createP() pObj.options.indentFirstLine = 440; pObj.addImage('/tmp/qr.jpg', { cx: 140, cy: 140 }); pObj = docx.createP() pObj = docx.createP() pObj = docx.createP({ align: 'right' }) pObj.addText('XXXXX', { font_face: 'FangSong', font_size: 15, color: '595959' }); pObj = docx.createP({ align: 'right' }) pObj.addText(timeBottom, { font_face: 'FangSong', font_size: 15, color: '595959' }); // Add a Footer: pObj = docx.createP() pObj = docx.createP() pObj = docx.createP() pObj.addText('XXXXX证明_' + item._id, { font_face: 'FangSong', font_size: 10, color: '808080' }); pObj = docx.createP() pObj.addText(time.toString(), { font_face: 'FangSong', font_size: 10, color: '808080' }); if (i != ((item.volunteerInfo).length - 1)) { docx.putPageBreak() } } //=======================建构文档内容结束========================= // Let's generate the Word document into a file: let out = fs.createWriteStream('/tmp/' + fileName) return new Promise((resolve, reject) => { docx.generate(out); out.on('close', async function(){ console.log("文件已被关闭,总共写入字节", out.bytesWritten) // console.log('写入的文件路径是'+ out.path); var fileBuf = await readDocx_fs(out.path); var upd = await cloud.uploadFile({ cloudPath: varpath, fileContent: fileBuf, }); console.log(docx) resolve({ event, upd, size: Math.floor(100*out.bytesWritten/1024)/100 + "KB" }) }); out.on('error', (err) => { console.error(err); reject({ errMsg: err }) }); }) }
2021-10-15 - 【笔记】云开发通过客服消息实现自动回复进群,同时兼容客服小助手
小程序不具备小程序内扫描二维码的能力,因此如果要实现关注公众号或加用户群功能大家一般都利用微信客服功能的自动回复来实现。此时如果自己去实现微信客服自动回复,客服小助手就不能用了,很令人纠结。经过我的研究,借助云开发找到了一个方案,可以实现当用户想获取微信群走自动回复的接口,真正咨询时,直接到客服小助手进行回复。 效果如下 [图片] 原理解析 云开发在做消息推送配置的时候可以配置消息类型,这个时候如果我们只配置一种类型(小程序卡片),那么就只有卡片才会被云函数接管做自动回复,其他消息类型(图片、文字)则正常走小程序客服的通道。 实现步骤 1.小程序端设置按钮属性open-type="contact",用于用户点击时带上定义的卡片跳到客服消息界面。 申请加入 2.新建云端的函数,设置config.json定义权限,如下config.json { "permissions": { "openapi": [ "customerServiceMessage.send", "customerServiceMessage.uploadTempMedia", "customerServiceMessage.setTyping" ] } } 3.写云函数端代码,如下 if (event.Title == "我要进用户群"||event.Title =="关注公众号"||event) { //设置输入状态 cloud.openapi.customerServiceMessage.setTyping({ touser: OPENID, command: 'Typing' }) //从云储存中拉取图片数据 const qunimg = await cloud.downloadFile({ fileID: "cloud://pm-hsfip.706d-pm-hsfip-1259751853/img/qun.png", }) //上传图片素材到媒体库,并获取到图片id const qunmedia = await cloud.openapi.customerServiceMessage.uploadTempMedia({ type: 'image', media: { contentType: 'image/png', value: qunimg.fileContent } }) //向用户发送群二维码 await cloud.openapi.customerServiceMessage.send({ touser: OPENID, msgtype: 'image', image: { mediaId: qunmedia.mediaId, } }) //取消状态设置 cloud.openapi.customerServiceMessage.setTyping({ touser: OPENID, command: 'CancelTyping' }) } 4.设置消息推送,路径如下 云开发-设置-全局设置-云函数接收消息推送 中添加消息类型为miniprogrampage,绑定云函数为新建的云函数。 [图片] 5.微信公众平台绑定客服[图片] 注意事项 如果按照本教程 客服小助手无法收到消息 或 无法自动回复,可以先将以上消息推送配置删除,然后再微信后台绑定客服后,再重新进行消息推送配置。
2020-07-29 - 关于自定义客服会话contact同时兼容自动和人工客服使用
首先,我们知道,可以通过button中的属性open-type="contact",实现小程序用户和小程序所有者客服对话。
2020-08-12 - 云开发云函数定时触发器讲解
任何可以产生事件,触发云函数执行的均可以被称为触发器,而定时触发器则是可以处理周期性的事情,比如时报、日报、周报等通知提醒,也可以处理倒计时任务,比如节假日、纪念日以及你可以指定一个具体时间的倒计时任务,除此之外,定时触发器还可以用来周期性处理一些定时任务。比如定期清理一些不必要的数据,定期更新集合内的数据。 13.5.1 定时触发器使用说明1、定时触发器的配置与部署配置了定时触发器的云函数,会在相应时间点被自动触发,云函数的返回结果不会返回给调用方。在对某个云函数使用定时触发器前,首先要保证该云函数在小程序端可以调用成功,更准确的说是能够在不传入参数的情况下在云开发控制台的云端测试能调试成功(小程序端调用有登录态)。 云函数目录里的 config.json 文件可以用来配置权限和定时触发器,如果你的云函数目录下面没有这个配置文件,可以自己创建一个,创建的结构目录如下: test //云函数目录 ├── config.json //权限和定时触发器等的配置文件 ├── index.js //云函数 ├── package.json //云函数的依赖管理 然后再来在配置文件 config.json 里进行类似如何格式的配置,config.json 严格遵循配置文件所要求的格式,比如数组最后一项不能有逗号[代码],[代码];配置文件里不能有注释等 triggers 字段是触发器数组,但是目前云函数只支持一个触发器,即数组只能填写一个,不可添加多个;name 是触发器的名字,最大支持 60 个字符,支持 a-z, A-Z, 0-9, - 和 _,必须以字母开头;type 为触发器类型,timer 是定时触发器config 是触发器的定时配置,里面为 cron 表达式(后面有介绍),cron 有七个必需字段,不能多也不能少(以下为每天早上 9 点到 12 点每隔 5 秒触发一次);{ "triggers": [ { "name": "tomylove", "type": "timer", "config": "*/5 * 9-12 * * * *" } ] } 当我们在修改触发器配置文件 config.json 后,首先鼠标右键 config.json 选择“云函数增量上传:更新文件”,然后再右键 config.json 选择“上传触发器”。这里的“云函数增量上传:更新文件”是让云函数端的触发器文件更新;而“上传触发器”则是让触发器开始生效执行。如果在云函数端的触发器没有更新的情况下就“上传触发器”来执行定时触发,文件可能没有更新,执行的还是旧的触发器内容。当我们想暂停或删除触发器时,可以右键选择“删除触发器”。 2、Cron 表达式语法Cron 表达式有七个必填字段,按空格分隔,既不能多写也不能少写,每一个字段都有它的含义对应着不同的时间点,表达式的取值都为整数且为时间制的范围(注意月在星期的前面): 第一位第二位第三位第四位第五位第六位第七位秒(0-59 )分钟(0-59)小时(0-23)日(1-31)月(1-12或三个字母的英文缩写)星期(0-6或三个字母的英文缩写)年(1970~2099 ) 下面是 cron 表达式的案例,以及我们需要了解一下 cron 表达式里的通配符以及直接写数字的含义: [代码],[代码],表示并集,在时间的表述里是“和”的意思,比如在“小时”字段中, [代码]1,2,3[代码]表示 1 点、2 点和 3 点;[代码]-[代码],指定范围的所有值,在时间的表述里是“到”的意思,比如在“日”字段中,[代码]1-15[代码]包含指定月份的 1 号到 15 号;[代码]*[代码],表示所有值,在时间的表述里是“每”的意思,比如在“小时”字段中,[代码]*[代码]表示每小时;[代码]/[代码],指定步长,在时间的表述里是“隔”的意思,比如在“秒”字段中,[代码]*/5[代码]表示每隔 5 秒;直接写数字,在时间的表述里是“第”(时间点)的意思,比如在“月”字段中,[代码]5[代码]表示每月的第 5 日;//表示每隔5秒触发一次, */5 * * * * * * //表示在每月的1日的凌晨2点触发 0 0 2 1 * * * //表示在周一到周五每天上午10:15触发 0 15 10 * * MON-FRI * //表示在每天上午10点,下午2点,4点触发 0 0 10,14,16 * * * * //表示在每天上午9点到下午5点内每半小时触发 0 */30 9-17 * * * * //表示在每个星期三中午12点触发 0 0 12 * * WED * 定时触发器的 Cron 语法没法实现每隔 90 秒钟或 90 分钟发送一次这样的效果,因为 90 秒超过了秒的时间制上限 60,而 cron 在跨位组合(比如 90 秒需要结合秒和分)上无法覆盖所有的时间;除此之外,云开发的触发器暂时不支持多个定时触发器的叠加;在 Cron 表达式中的“日”和“星期”字段同时指定值时,两者为“或”的关系,即两者的条件均生效;值得一提的是,尽管云函数的时区为 UTC+0 时区,但是定时触发器的时间还是北京时间。 13.5.2 用定时触发器调用云函数定时触发器的使用非常简单,使用开发者工具新建一个云函数比如 trigger,然后在 index.js 里输入以下代码: const cloud = require("wx-server-sdk"); cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV, }); exports.main = async (event, context) => { console.log(event); return event; }; 再在 trigger 云函数目录下的 config.json(如果没有这个文件,就创建一个),然后输入以下触发器,为了调试方便,我们可以每隔 5 秒触发一次: { "permissions": { "openapi": [ ] }, "triggers": [ { "name": "tomylove", "type": "timer", "config": "*/5 * * * * * *" } ] } 然后分别右键 index.js 和 config.json,选择“云函数增量上传:更新文件”,然后再来右键 config.json 选择“上传触发器”。云函数就会每隔 5 秒自动触发,相关的日志我们可以在开发者工具的云开发控制台以及腾讯云云开发网页控制台的云函数的日志里查看。 注意小程序端调用 trigger 云函数返回的 event 对象,和使用定时触发器返回的 event 对象的不同,用定时触发器触发云函数是获取不到 openId 的,同时这里有一个 Time 时间是时区为 UTC+0 的时间,比北京时间晚 8 个小时: //在小程序端调用trigger云函数之后返回的event对象 { "userInfo":{ "appId":"wxda99******7046", "openId":"oUL-m5F******buEDsn8" } } //使用定时触发器触发云函数之后返回的event对象 { "Message":"", "Time":"2020-06-11T11:43:35Z", "TriggerName":"tomylove", "Type":"timer", "userInfo":{ "appId":"wxda99********46" } } 13.5.3、定时触发器的应用定时触发器的应用非常广泛,以下仅举一些常用案例,并加以说明: 1、结合消息推送这里的消息推送不仅仅只是指订阅消息,还可以是统一服务消息、公众号的消息(可以用云函数开发微信公众号)、小程序内自己开发的通知(只是用户只有在打开小程序时才能看到)、Email 邮件等等。 比如用户订阅了日报、周报、月报等周期性的通知提醒或者我们需要给用户发送一些汇总信息,就可以固定写一个定时触发器,比如我们需要给指定用户发送工作周报,每周五晚上 17 点 30 分就定时从数据库获取数据发送消息,cron 表达式写法如下: * 30 17 * * FRI * 还可以用来处理一些倒计时(指定时间点)的任务,比如节假日、纪念日以及一些活动时间节点(定时触发器目前只能一个云函数配一个触发器,但是可以提前管理),比如我们希望在六一儿童节的早上 9 点调用云函数给指定用户群体发送消息: 0 0 9 1 6 * * 当然这样的具体时间点显得过于的不灵活,但是如果把时间与云开发数据库结合起来,灵活性就会大很多,比如在运营上每天早上 11 点是你们用户访问最多的时间点,你只需要写一个云函数,把所有的活动都在这个时间点来推送,让定时触发器每天这个时间点都触发,有活动(数据库里有数据)就会发消息,如果没有就不发(云函数调用一次的成本极低)。 如果是实时数据,我们还可以把定时触发器的频率调高,每 5 秒就触发一次,比如我们的数据库只要有最新的数据,就会发消息给指定用户。尽管不是完全的实时,但是 5 秒的频率和实时的差别也就不大了。你也可以根据情况,来调整触发器的频率,毕竟 5 秒和 1 分钟的频率给用户的体验差异并没有太大,但是成本却是 12 倍的关系。 可能你还希望在指定的时间段才触发云函数,比如你只希望在工作日、或者在早上 9 点到晚上 18 点才触发,在指定的时间段才触发既可以让触发更精准不扰民,也可以节约成本,比如下面的触发器就是工作日早上 9 点到 12 点和下午 14 点到 18 点这个时间段,每 5 秒触发一次。 */5 * 9-12,14-18 * MON,TUE,WED,THU,FRI * 从以上案例我们可以了解到,云函数的定时触发可以来自于 cron 表达式的配置,我们可以指定时间点时间段和频率来达到我们想要的效果,同时这个时间“也可以来自于数据库的配置”(伪装),意思是我们可以设置触发器的时间段或频率,如果数据库里有数据就发送,没有数据就不发送,这样就可以达到触发器在时间上的灵活性了。 2、实时获取数据有的时候我们的数据并不是来自于数据库,而是来自于第三方服务,比如前面介绍过的历史上的今天的 API,天气的 API,知乎日报的 API 等等,以及一些 webhook,这些 API 和第三方服务提供的是 json 格式的文件,API 的数据也会随时更新,但是它们更新了却并不会主动通知我们,这时我们可以使用定时触发器向这些 API 发起请求,如果数据出现更新,我们就可以将更新的数据存储到我们的数据库或者进行其他处理,比如企业微信的机器人等机器人通知服务就是如此。 当然定期获取的数据还可以是爬虫,比如我们可以定期抓取指定关键词的新闻或者指定网站的动态,当爬虫获取到了不同的数据的时候,就将最新的动态以机器人消息或者其他方式进行及时的处理。 也就是说,我们无法实时监听到第三方 API 或者网站数据的变动,但是可以用定时触发器来发起请求或者爬虫抓取数据,通过数据的变化来达到“实时”获取数据的目的。 3、自动化处理在数据库的设计里,我们就提到有时候需要对数据库里的数据进行定期的备份与删除等清理维护工作,比如超过一定时间的日志,具有很强时效性的活动数据,以及为了性能考虑而做的虚假删除(数据库性能与优化有介绍)等,毕竟数据库有一定的存储成本而且过多无用数据也会影响数据库的性能,我们可以写一个云函数用定时触发器来执行此类任务。 我们还可以在用户并发比较少的时间段(比如凌晨几点)来处理一些比较耗云函数、数据库性能的任务,比如图片的审核与裁剪、缩略等处理,用户评论是否包含敏感词汇(尽管经过安全处理,但是有时候我们还会设置特别的敏感词),数据的汇总,云存储里废弃文件的删除,用户信息是否完整等等。 也就是说,结合定时触发器,我们可以实现一些任务的自动化处理。 4、密集型任务分流我们知道云函数在处理一些复杂性的任务时是有一些限制的,一是执行时间的限制,建议在设置时执行时间一般不要超过 20s,最长不要超过 60s;二是并发的限制,云函数最大的并发为 1000;三是云函数在查询数据库时一次可以获取最多 1000 条的数据,面对这三个限制,我们应该如何处理密集型的任务呢,比如发送 100 万封邮件,导出几百万条数据到 Excel,发送十万级的订阅消息或消息等等,这个时候就可以使用到定时触发器来处理了。 借助于定时触发器,我们可以将需要耗时较长、对并发要求较高以及数据库请求等的任务进行分批处理,比如我们要给 100 万人发邮件:云函数发起数据库请求,一次只请求 1000 条未发送过邮件的用户(用 where 条件查询某个字段,比如[代码]status:false[代码]),然后将邮件发给 1000 个人(可以参考前面的邮件发送),发完邮件并对这 1000 条数据进行标记(比如使用更新指令将 status 改为 true),这样下次查询未发送过邮件的用户时,就不会重复发送了。通过定时触发器,每 2 秒执行一次发送任务,几十分钟就可以处理完任务。
2021-09-10 - 如何实现快速生成朋友圈海报分享图
由于我们无法将小程序直接分享到朋友圈,但分享到朋友圈的需求又很多,业界目前的做法是利用小程序的 Canvas 功能生成一张带有小程序码的图片,然后引导用户下载图片到本地后再分享到朋友圈。相信大家在绘制分享图中应该踩到 Canvas 的各种(坑)彩dan了吧~ 这里首先推荐一个开源的组件:painter(通过该组件目前我们已经成功在支付宝小程序上也应用上了分享图功能) 咱们不多说,直接上手就是干。 [图片] 首先我们新增一个自定义组件,在该组件的json中引入painter [代码]{ "component": true, "usingComponents": { "painter": "/painter/painter" } } [代码] 然后组件的WXML (代码片段在最后) [代码]// 将该组件定位在屏幕之外,用户查看不到。 <painter style="position: absolute; top: -9999rpx;" palette="{{imgDraw}}" bind:imgOK="onImgOK" /> [代码] 重点来了 JS (代码片段在最后) [代码]Component({ properties: { // 是否开始绘图 isCanDraw: { type: Boolean, value: false, observer(newVal) { newVal && this.handleStartDrawImg() } }, // 用户头像昵称信息 userInfo: { type: Object, value: { avatarUrl: '', nickName: '' } } }, data: { imgDraw: {}, // 绘制图片的大对象 sharePath: '' // 生成的分享图 }, methods: { handleStartDrawImg() { wx.showLoading({ title: '生成中' }) this.setData({ imgDraw: { width: '750rpx', height: '1334rpx', background: 'https://qiniu-image.qtshe.com/20190506share-bg.png', views: [ { type: 'image', url: 'https://qiniu-image.qtshe.com/1560248372315_467.jpg', css: { top: '32rpx', left: '30rpx', right: '32rpx', width: '688rpx', height: '420rpx', borderRadius: '16rpx' }, }, { type: 'image', url: this.data.userInfo.avatarUrl || 'https://qiniu-image.qtshe.com/default-avatar20170707.png', css: { top: '404rpx', left: '328rpx', width: '96rpx', height: '96rpx', borderWidth: '6rpx', borderColor: '#FFF', borderRadius: '96rpx' } }, { type: 'text', text: this.data.userInfo.nickName || '青团子', css: { top: '532rpx', fontSize: '28rpx', left: '375rpx', align: 'center', color: '#3c3c3c' } }, { type: 'text', text: `邀请您参与助力活动`, css: { top: '576rpx', left: '375rpx', align: 'center', fontSize: '28rpx', color: '#3c3c3c' } }, { type: 'text', text: `宇宙最萌蓝牙耳机测评员`, css: { top: '644rpx', left: '375rpx', maxLines: 1, align: 'center', fontWeight: 'bold', fontSize: '44rpx', color: '#3c3c3c' } }, { type: 'image', url: 'https://qiniu-image.qtshe.com/20190605index.jpg', css: { top: '834rpx', left: '470rpx', width: '200rpx', height: '200rpx' } } ] } }) }, onImgErr(e) { wx.hideLoading() wx.showToast({ title: '生成分享图失败,请刷新页面重试' }) //通知外部绘制完成,重置isCanDraw为false this.triggerEvent('initData') }, onImgOK(e) { wx.hideLoading() // 展示分享图 wx.showShareImageMenu({ path: e.detail.path, fail: err => { console.log(err) } }) //通知外部绘制完成,重置isCanDraw为false this.triggerEvent('initData') } } }) [代码] 那么我们该如何引用呢? 首先json里引用我们封装好的组件share-box [代码]{ "usingComponents": { "share-box": "/components/shareBox/index" } } [代码] 以下示例为获取用户头像昵称后再生成图。 [代码]<button class="intro" bindtap="getUserInfo">点我生成分享图</button> <share-box isCanDraw="{{isCanDraw}}" userInfo="{{userInfo}}" bind:initData="handleClose" /> [代码] 调用的地方: [代码]const app = getApp() Page({ data: { isCanDraw: false }, // 组件内部关掉或者绘制完成需重置状态 handleClose() { this.setData({ isCanDraw: !this.data.isCanDraw }) }, getUserInfo(e) { wx.getUserProfile({ desc: "获取您的头像昵称信息", success: res => { const { userInfo = {} } = res this.setData({ userInfo, isCanDraw: true // 开始绘制海报图 }) }, fail: err => { console.log(err) } }) } }) [代码] 最后绘制分享图的自定义组件就完成啦~效果图如下: [图片] tips: 文字居中实现可以看下代码片段 文字换行实现(maxLines)只需要设置宽度,maxLines如果设置为1,那么超出一行将会展示为省略号 代码片段:https://developers.weixin.qq.com/s/J38pKsmK7Qw5 附上painter可视化编辑代码工具:点我直达,因为涉及网络图片,代码片段设置不了downloadFile合法域名,建议真机开启调试模式,开发者工具 详情里开启不校验合法域名进行代码片段的运行查看。 最后看下面大家评论问的较多的问题:downLoadFile合法域名在小程序后台 开发>开发设置里配置,域名为你图片的域名前缀 比如我文章里的图https://qiniu-image.qtshe.com/20190605index.jpg。配置域名时填写https://qiniu-image.qtshe.com即可。如果你图片cdn地址为https://aaa.com/xxx.png, 那你就配置https://aaa.com即可。
2022-01-20 - 云开发实战:小程序导出Ecxcl表格功能
需求 作为信息收集者需要把用户填写的内容,用Ecxcl表格的方式导出。可以支持在线查看或者复制文件下载链接。 [图片] 查看 excle 表格可以直接在手机上查看表格 复制下载地址可以通过链接在电脑上下载 实现 以收集姓名信息为例: 云函数代码 [代码]// 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init() //操作excel用的类库 const xlsx = require('node-xlsx'); // 云函数入口函数 exports.main = async (event, context) => { try { let { dataList, excelName } = event // 1. 定义excel表格名 let dataCVS = 'test.xlsx' // 2. 定义存储数据的 let alldata = []; // 3. 定义表头 let row = ['姓名']; alldata.push(row); // 4. 循环取出姓名数据 for (let key in dataList) { let arr = []; arr.push(applyList[key].name); alldata.push(arr) } //5. 把数据保存到excel里 var buffer = await xlsx.build([{ name: "mySheetName", data: alldata }]); //6. 把excel文件保存到云存储里 return await cloud.uploadFile({ cloudPath: excelName + ".xlsx", fileContent: buffer, }) } catch (e) { console.error(e) return e } } [代码] 注意上传部署云函数的时候需要先安装[代码]node-xlsx[代码] 安装步骤: 打开命令行 [图片] 输入安装命令:[代码]npm install node-xlsx --save[代码] 小程序调用代码 通用调用云函数生成表格代码部分 [代码]createExcel(type) { // 提示加载中 wx.showLoading({ title: '正在加载中...', }) console.log('请求获取') let data = { dataList: 姓名数据集合, excelName: 文件名 } // 生成excel并存储 wx.cloud.callFunction({ name: 'excel', data: data }).then(res => { // 获取存储文件ID this.getFileUrl(res.result.fileID,type) }) } [代码] 根据不同的type来实现不同的功能 2.1 type为0时查看excel 2.2 type为1时复制地址 [代码] getFileUrl(fileID, type) { let that = this; wx.cloud.getTempFileURL({ fileList: [fileID], success: res => { // get temp file URL that.setData({ fileUrl: res.fileList[0].tempFileURL }) // 下载文件并且打开文档 if (type == 0) { wx.downloadFile({ url: res.fileList[0].tempFileURL, success: function (res) { const filePath = res.tempFilePath wx.openDocument({ filePath: filePath }) } }) } else if (type == 1) { // 复制地址 wx.setClipboardData({ data: res.fileList[0].tempFileURL }) } } }) }, [代码] 扩展阅读 以上涉及到的API文档地址: node-xlsx wx.setClipboardData wx.uploadFile wx.downloadFile wx.openDocument
2021-02-25 - 小程序10行代码实现微信头像挂红旗,国庆节个性化头像
最近朋友圈里经常有看到这样的头像 [图片] 既然这么火,大家要图又这么难,作为程序员的自己当然要自己动手实现一个。 老规矩,先看效果图 [图片] 仔细研究了下,发现实现起来并不难,核心代码只有下面10行。 [代码] wx.canvasToTempFilePath({ x: 0, y: 0, width: num, height: num, destWidth: num, destHeight: num, canvasId: 'shareImg', success: function(res) { that.setData({ prurl: res.tempFilePath }) wx.hideLoading() }, fail: function(res) { wx.hideLoading() } }) [代码] 一,首先要创建一个小程序 至于如何创建小程序,我这里就不在细讲了,我也有写过创建小程序的文章,也有路过相关的学习视频,去翻下我历史文章找找就行。 二,创建好小程序后,我们就开始来布局 布局很简单,只有下面几行代码。 [代码]<!-- 画布大小按需定制 这里我按照背景图的尺寸定的 --> <canvas canvas-id="shareImg"></canvas> <!-- 预览区域 --> <view class='preview'> <image src='{{prurl}}' mode='aspectFit'></image> <button size='mini' open-type="getUserInfo" bindgetuserinfo="shengcheng" data-k="1">生成头像1</button> <button size='mini' open-type="getUserInfo" bindgetuserinfo="shengcheng" data-k="2">生成头像2</button> <button size='mini' open-type="getUserInfo" bindgetuserinfo="shengcheng" data-k="3">生成头像3</button> <button size='mini' open-type="getUserInfo" bindgetuserinfo="shengcheng" data-k="4">生成头像4</button> <button type='primary' bindtap='save'>保存分享图</button> </view> [代码] 实现效果图如下 [图片] 三,使用canvas来画图 其实我们实现微信头像挂红旗,原理很简单,就是把头像放在下面,然后把有红旗的相框盖在头像上面 [图片] 下面就直接把核心代码贴给大家 [代码]let promise1 = new Promise(function(resolve, reject) { wx.getImageInfo({ src: "../../images/xiaoshitou.jpg", success: function(res) { console.log("promise1", res) resolve(res); } }) }); let promise2 = new Promise(function(resolve, reject) { wx.getImageInfo({ src: `../../images/head${index}.png`, success: function(res) { console.log(res) resolve(res); } }) }); Promise.all([ promise1, promise2 ]).then(res => { console.log("Promise.all", res) //主要就是计算好各个图文的位置 let num = 1125; ctx.drawImage('../../'+res[0].path, 0, 0, num, num) ctx.drawImage('../../' + res[1].path, 0, 0, num, num) ctx.stroke() ctx.draw(false, () => { wx.canvasToTempFilePath({ x: 0, y: 0, width: num, height: num, destWidth: num, destHeight: num, canvasId: 'shareImg', success: function(res) { that.setData({ prurl: res.tempFilePath }) wx.hideLoading() }, fail: function(res) { wx.hideLoading() } }) }) }) [代码] 来看下画出来的效果图 [图片] 四,头像加红旗画好以后,我们就要想办法把图片保存到本地了 [图片] 保存图片的代码也很简单。 [代码]save: function() { var that = this wx.saveImageToPhotosAlbum({ filePath: that.data.prurl, success(res) { wx.showModal({ content: '图片已保存到相册,赶紧晒一下吧~', showCancel: false, confirmText: '好哒', confirmColor: '#72B9C3', success: function(res) { if (res.confirm) { console.log('用户点击确定'); } } }) } }) } [代码] 来看下保存后的效果图 [图片] 到这里,我的微信头像就成功的加上了小红旗了。 [图片] 源码我也已经给大家准备好了,有需要的同学在文末留言即可。 [图片] 后面我准备录制一门视频课程出来,来详细教大家实现这个功能,敬请关注。
2019-09-26 - 小程序设置多行文本超出隐藏
1、最近开发遇到需要在列表页显示一部分相关信息,但是可能涉及的信息比较长,所以想让它只显示两行,超出即用...显示,ok,实现效果和代码如下。 2、页面 [图片] 3、页面代码(展示部分代码,主要看隐藏) <view class="weui-cell order-info"> <view class="order_content" bindtap="toRepairinfo" data-id="{{maintenance.id}}"> <view class='tag'> {{maintenance.equipmentName}}</view> <view class="total total_time">报修时间 :{{maintenance.applyRepairDate}}</view> <view class="remarks"> <span class="bzm"> 故障描述:</span> <span>{{maintenance.errorDescription}}</span> </view> </view> </view> 4、wxss .order_content .remarks{ padding:1% 5% 1% 5%; /*设置多行超出进行隐藏*/ display: -webkit-box; word-break: break-all; text-overflow: ellipsis; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp:2; /*设置超出两行进行隐藏*/ }
2020-09-24 - 实战分享: 小程序云开发玩转订阅消息(二)
[图片]这是实战分享: 小程序云开发玩转订阅消息的第二部分 第一部分链接 《实战分享: 小程序云开发玩转订阅消息(一)》 将订阅消息存入云开发数据库接下来我们创建一个云函数 [代码]subscribe[代码] ,这个云函数的作用是将用户的订阅信息存入云开发数据库的集合 [代码]messages[代码] 中,等待将来需要通知用户时进行调用。 在微信开发者工具的云开发面板中创建数据库集合 [代码]messages[代码] [图片]微信开发者工具新增数据库集合 创建一个 [代码]subscribe[代码] 云函数,在云函数中我们将小程序端发送过来的课程订阅信息,存储在云开发数据库集合中,开发完成后,在微信开发者工具中右键上传并部署云函数。 cloudfunctions/subscribe/index.js [代码]const cloud = require('wx-server-sdk'); cloud.init(); const db = cloud.database(); exports.main = async (event, context) => { try { const {OPENID} = cloud.getWXContext(); // 在云开发数据库中存储用户订阅的课程 const result = await db.collection('messages').add({ data: { touser: OPENID, // 订阅者的openid page: 'index', // 订阅消息卡片点击后会打开小程序的哪个页面 data: event.data, // 订阅消息的数据 templateId: event.templateId, // 订阅消息模板ID done: false, // 消息发送状态设置为 false }, }); return result; } catch (err) { console.log(err); return err; } }; [代码]利用定时触发器来定期发送订阅消息接下来我们需要实现一个定时执行的云函数[代码]send[代码],来检查数据库中是否有需要发送给用户的订阅消息。如果有需要发送的订阅消息,会通过云调用 [代码]cloud.openapi.subscribeMessage.send[代码] 将订阅消息发送给用户。 创建一个名叫 [代码]send[代码] 的云函数,首先要配置云函数,在 [代码]config.json[代码] 的 [代码]permissions[代码] 中新增 [代码]subscribeMessage.send[代码]的云调用权限,然后新增一个 [代码]sendMessagerTimer[代码] 的定时触发器,定时触发器的语法和 [代码]linux[代码] 的 [代码]crontab[代码] 类似,比如,我们配置的 [代码]"0 * * * * * *"[代码] 代表每分钟执行一次云函数。 cloudfunctions/send/config.json [代码]{ "permissions": { "openapi": ["subscribeMessage.send"] }, "triggers": [ { "name": "sendMessagerTimer", "type": "timer", "config": "0 * * * * * *" } ] } [代码]接下来是实现发送订阅消息的云函数,这个云函数会从云开发数据库集合[代码]messages[代码]中查询等待发送的消息列表,检查数据库中是否有需要发送给用户的订阅消息,发送条件可以根据自己的业务实现,比如开课提醒可以根据课程开课日期来检查是否需要发送订阅消息,在我们下面的代码示例里做了简化,筛选条件只检查了状态为未发送。 查询到待发送的消息列表之后,我们会循环消息列表,依次发送每条订阅消息,发送成功后将数据库中消息的状态改为已发送。 cloudfunctions/send/index.js [代码]const cloud = require('wx-server-sdk'); exports.main = async (event, context) => { cloud.init(); const db = cloud.database(); try { // 从云开发数据库中查询等待发送的消息列表 const messages = await db .collection('messages') // 查询条件这里做了简化,只查找了状态为未发送的消息 // 在真正的生产环境,可以根据开课日期等条件筛选应该发送哪些消息 .where({ done: false, }) .get(); // 循环消息列表 const sendPromises = messages.data.map(async message => { try { // 发送订阅消息 await cloud.openapi.subscribeMessage.send({ touser: message.touser, page: message.page, data: message.data, templateId: message.templateId, }); // 发送成功后将消息的状态改为已发送 return db .collection('messages') .doc(message._id) .update({ data: { done: true, }, }); } catch (e) { return e; } }); return Promise.all(sendPromises); } catch (err) { console.log(err); return err; } }; [代码]最终效果 [图片]开课提醒订阅消息截图 源代码https://github.com/binggg/tcb-subscribe-demo[3] 参考资料 [1]注册小程序帐号: https://tencentcloudbase.github.io/2019-09-03-wx-dev-guide-register/ [2]开通云开发服务: https://tencentcloudbase.github.io/2019-09-03-wx-dev-guide-service/ [3]https://github.com/binggg/tcb-subscribe-demo: https://github.com/binggg/tcb-subscribe-demo
2019-10-23 - 实战分享: 小程序云开发玩转订阅消息(一)
[图片] 微信官方为提升小程序模板消息能力的使用体验,对模板消息的下发条件进行了调整。原有的小程序模板消息接口于 2020 年 1 月 10 日下线,届时将无法使用旧的小程序模板消息接口发送模板消息,取而代之的是新的一次性订阅消息和长期订阅消息。 订阅消息给小程序开发者带来了更好的触达用户的能力,在具体实施过程中,开发者如何把模板消息换成新的订阅消息,是否需要购买服务器来实现服务器鉴权,怎样才能在用户订阅之后一段时间后,给用户发送长期或一次性订阅消息呢? 小程序·云开发最近支持了通过云调用免 access_token 发送订阅消息,还新增支持了在定时触发器中实现云调用,这些能力可以帮助开发者轻松玩转小程序订阅消息。 我们今天会利用小程序·云开发进行一个小程序中实现订阅开课提醒的实战,帮助大家了解如何基于小程序·云开发快速接入小程序订阅消息。 [图片]整体时序图[图片]开课提醒订阅消息时序图环境准备注册小程序帐号[1]开通云开发服务[2]获取订阅消息模板 ID在微信小程序管理后台中,新增一个订阅消息的模板,这里我们新增了一个开课提醒的模板。 [图片]新增模板引导用户订阅微信小程序提供了[代码]wx.requestSubscribeMessage[代码] 接口来发起申请订阅权限界面。 [图片]微信申请订阅权限界面在 "订阅开课提醒" 的按钮上绑定 tap 事件,事件处理器我们这里用的 [代码]onSubscribe[代码] index.wxml [代码]<button class="btn" data-item="{{ item }}" bindtap="onSubscribe" hover-class="btn-hover" > 订阅开课提醒 </button> [代码]在 [代码]onSubscribe[代码] 函数内,我们会调用微信 API [代码]wx.requestSubscribeMessage[代码] 申请发送订阅消息权限,当用户在弹窗同意订阅之后,我们会收到 [代码]success[代码] 回调,将订阅的课程信息调用云函数 [代码]subscribe[代码] 存入云开发数据库,云函数 [代码]subscribe[代码] 的实现在下文会讲。 index.js [代码]onSubscribe: function(e) { // 获取课程信息 const item = e.currentTarget.dataset.item; // 调用微信 API 申请发送订阅消息 wx.requestSubscribeMessage({ // 传入订阅消息的模板id,模板 id 可在小程序管理后台申请 tmplIds: [lessonTmplId], success(res) { // 申请订阅成功 if (res.errMsg === 'requestSubscribeMessage:ok') { // 这里将订阅的课程信息调用云函数存入云开发数据 wx.cloud .callFunction({ name: 'subscribe', data: { data: item, templateId: lessonTmplId, }, }) .then(() => { wx.showToast({ title: '订阅成功', icon: 'success', duration: 2000, }); }) .catch(() => { wx.showToast({ title: '订阅失败', icon: 'success', duration: 2000, }); }); } }, }); [代码][代码] },[代码] 文章字数超出 50000 字,后半部分链接 《实战分享: 小程序云开发玩转订阅消息(二)》
2019-10-23