- 关于标准版交易组件商品销量与浏览量的统计问题?
由于标准版交易组件并未提供商品的销量、浏览量,所以想自己开发做一个相关统计。 1、需要知道交易组件中,商品详情组件中,xxx人看过,xx的相关统计规则,或者提供可以获取该xx的接口。 2、想获取交易中,商品详情组件中, xx人购买, 如果没有相应api获取该参数。想通过获取订单列表做相应商品销量统计,下面关于该接口提出疑问: 获取订单列表api:https://api.weixin.qq.com/product/order/get_list?access_token=xxxxxx 1)该api请求参数中的时间参数,查询结果的时间范围是左闭右开,还是左闭右闭?即查询结果是否包含查询时间的两个时间点。 2)订单状态什么情况下会使销量+1,是需要订单状态100(完成)销量才会+1,还是在订单10(待付款)或者订单20(待发货)时,销量就+1;订单 状态200(全部商品售后之后,订单取消)是指交易完成,用户请求退款吗?这种情况销量会-1吗?订单状态250(用户主动取消或待付款超时取消)会导致销量-1?
2021-07-12 - 自己的小程序使用小商店组件如何在首页展示优惠券?
首页不是小商店的首页,有没有办法把小商店后台创建的优惠券展示在首页上?
2021-03-29 - 小商店标准组件获取商品列表spus数据显示为0个?
通过云函数引入request-promise请求获取商品列表,但是spus显示始终为0,是我写的不对还是什么原因,请大佬支招 云函数如下 [图片] 前端渲染如下 [图片]
2021-06-18 - 云开发的答题活动小程序如何计算答题排名
问题:超过1000人的答题,如何获取答题名次 规则:按得分排名,得分大的排前面,得分相同的按用时排名,用时少的的排前面 已知:答题得分,答题用时 求解:用户排名 逻辑:先取大于该用户的分数的人数,再取等于该用户分数的人里面时间小于该用户人数,两个相加再加1 序号 得分 用时(秒) 01 100 25 02 100 30 03 90 20 04 100 10 db.collection('historys') .where({ num: _.gt(event.num) }) .count() 求得num1 db.collection('historys') .where({ num: _.eq(event.num), time: _.lt(event.time) }) .count() 求得num2 排名 = num1 + num2 + 1 参考 在线答题小程序技术方案征集?? - 微信开放社区 https://developers.weixin.qq.com/community/develop/doc/0006e071ab88a049a56bdc1c251000 探讨答题小程序排名的计算逻辑问题? - 微信开放社区 https://developers.weixin.qq.com/community/develop/article/doc/000462c0848e782eee6ba916f56813
2021-05-14 - wxacode.getUnlimited参数问题
我用wxacode.getUnlimited请求到二维码了然后在scene传参数的时候要传2个参数请问应该怎么传,在前端的话又应该分别获取呢?又不能传对象转化为字符串后的结果,编码的话不知道是不是我操作不对还是什么,获取不了。求大神指教。感激不尽
2019-04-10 - 小程序分享功能是否可以异步?
场景为用户可以自己设置分享码 将订单分享出去 后台生成唯一id来跟踪订单 以便别人打开的时候通过这个唯一id去获取订单状态(判断是否超过了规定分享人数等)但是这个唯一id是后台生成再传给前台的 想实现用户点击分享按钮时 前端传给后台分享码 后台生成唯一id传给前台 前台将唯一id作为参数分享出去 这种如何处理?希望大家帮忙看看,谢谢!
2020-12-25 - 小程序云开发中云数据库where中怎么查询某个数组下符合某个条件的数据?
[代码]{[代码][代码] _id:face13585d4930ed0d0ea60c318aa616[代码] [代码] oils:[[代码] [代码] {[代码] oil_type:'92#', price: 7.92 }, [代码] {[代码] oil_type:'95#', price: 8.26 }, [代码] {[代码] oil_type:'98#', price: 9.04 }, [代码] ],[代码] [代码] station_id: 'W9yHmau9e31Z7KqO'[代码] [代码]},[代码][代码]{[代码][代码] _id:face13585d4930ed0d0ea60c34345[代码] [代码] oils:[[代码] [代码] {[代码] oil_type:'92#', price: 7.82 }, [代码] {[代码] oil_type:'95#', price: 8.26 }, [代码] {[代码] oil_type:'98#', price: 9.04 }, [代码] ],[代码] [代码] station_id: 'H9yHmau9e3342HS12a'[代码] [代码]},[代码][代码][代码] 上面是我某个数据表'oil_prices'中的数据,目前暂且只有2条,这时候我想通过根据station_id和oils数组中的oil_type进行查询到对应数据,然后更新对应的字段数据,能做到吗? 以下写法貌似没效果。 [代码]db.collection([代码][代码]'oil_prices'[代码][代码]).where({[代码][代码] [代码][代码]station_id: event.stationId,[代码][代码] [代码][代码]'oils.$[].oil_type'[代码][代码]: event.oilType[代码][代码] [代码][代码]}).update({[代码][代码] [代码][代码]data: {[代码][代码] [代码][代码]'oils.$[].price'[代码][代码]: event.price[代码][代码] [代码][代码]},[代码][代码] [代码][代码]success: [代码][代码]function[代码] [代码](res) {[代码][代码] [代码][代码]return[代码][代码]{[代码][代码] [代码][代码]code:200,[代码][代码] [代码][代码]msg:[代码][代码]'油价更新成功'[代码][代码] [代码][代码]}[代码][代码] [代码][代码]}[代码][代码] [代码][代码]})[代码]
2019-12-13 - 请问云开发如何在获取数据库的同时格式化时间戳?
感觉可以通过聚合操作实现,但是API中并没有处理时间戳的 [图片]
2019-11-24 - 小程序 vtabs组件滑动跳转混乱?
使用官方提供的vtabs 示例中的代码,开发垂直滑动选项卡。 右侧内容项中的高度是根据内容的大小随机设定的,然后就会出现选项卡切换混乱的问题,当给右侧内容项设定固定高度时,又没有问题。 请问存在什么bug呢?
2020-10-14 - 小程序如何根据视频url展示缩略图?
小程序如何根据视频url展示缩略图?
2020-03-07 - 使用where多条件查询怎么实现?
{ "userNo":"0665", "applyInfo":[{ "applyDate":"2020-02-09 16:45:32", "applyDone":true, "applyUserName":"张三", "applyUserNo":"0026" }, { "applyUserName":"李健", "applyUserNo":"0005", "applyDate":"", "applyDone":false }], } 查询同时满足applyUserName='张三',并且applyDone=true,应该怎么实现? 使用where({ "applyInfo":{ "applyDone":false, "applyUserName":"张三", }}) 查询是或的关系。。
2020-02-09 - .where 如何实现动态添加查询条件(筛选)?
请问不想写这么多if else 怎么办? if (params.username == '' && params.company == '' && params.project == '' && params.bigclassname == '') { wx.cloud.database().collection("demoorder").where({ date: _.gte(new Date(params.startDate)).and(_.lte(new Date(params.endDate))) }) .skip(len) .limit(20) .get({ success(res) { }, fail(res) { } }) } else if (params.username != "" && params.company == "" && params.project == "" && params.bigclassname == "") { wx.cloud.database().collection("demoorder").where({ date: _.gte(new Date(params.startDate)).and(_.lte(new Date(params.endDate))) }) .skip(len) .limit(20) .get({ success(res) { }, fail(res) { } }) } else if (params.username == "" && params.company != "" && params.project == "" && params.bigclassname == "") { wx.cloud.database().collection("demoorder").where({ date: _.gte(new Date(params.startDate)).and(_.lte(new Date(params.endDate))) }) .skip(len) .limit(20) .get({ success(res) { }, fail(res) { } }) }else if{}等等
2021-01-30 - 关于小程序原生开发一个多种条件的筛选demo?
如题,本人刚入坑不久,有么有轮子哇 [图片][图片][图片]
2020-12-07 - 微信下单接口的attach长度能不能增加?
微信下单接口的attach长度能不能增加? 业务系统里是用UUID作为主键,需要在支付成功回调中取出主键进行更新,现有的126长度不能满足使用,只能放两个主键,需要增加传递的长度
2021-01-30 - 云开发如何合并多个订单支付?或者支付回掉函数如何传递参数?
基于云开发的微信支付: 支付成功回调方式: (1)在前端,执行 wx.requestPayment 的 success 成功回调。缺点:如果用户没有点击“完成”,直接退出小程序,则无法正常执行。 (2)在后端,通过微信支付 cloud.cloudPay.unifiedOrder 的支付成功回调函数 functionName。 基于第(2)种方式,当用户合并支付多个订单, 当用户支付成功,执行 functionName ,此时需要更新 id=1、id = 2、id =3 等多个数据的支付状态及其对应的订单号。此时,如何向回调函数传递这些参数???? 已知,attach 可以传递 附加的数据,如果只是一条数据,那可以传递该数据的id,现在是有多条数据需要更新,而 attach 的限制是 String(127),当 id 是16/32位字符串时,则远远不够。 同时,也想请问,一次微信支付的额度是多少?即 cloud.cloudPay.unifiedOrder 的参数 totalFee 有没有额度限制??
2021-01-30 - 微信小程序码能否开放解析或者官方提供解析接口?
我们在已有业务中已经发放了小程序码给客户,此时小程序中开发的业务都正常运行。 后续我们又开发了app,此时希望app也能够正确扫码解析,但是此时发现app不能解析到小程序码的内容,导致需要再发放一套通用的二维码给客户,官方能否提供小程序的解析方式,如果不能/不方便提供,能否提供接口解析把解析结果返回出来 提前感谢回复! 再次编辑说明一下,希望【复用】已经发放的【小程序码】,不重新生成【二维码】,所以要考虑在app解析小程序码的信息,或者官方提供接口在服务器上解析也行。
2021-03-07 - weapp-qrcode-canvas-2d在微信小程序中生成二维码,新版canvas-2d接口
weapp-qrcode-canvas-2d weapp-qrcode-canvas-2d 是使用新版canvas-2d接口在微信小程序中生成二维码(外部二维码)的js包。canvas 2d 接口支持同层渲染且性能更佳,建议切换使用,可大幅提升生成图片的速度。 仓库地址 weapp-qrcode-canvas-2d【码云gitee】 weapp-qrcode-canvas-2d【github】 [图片] 测试环境 微信小程序基础库版本:2.10.4 开发者工具版本:Stable 1.03.2101150 Usage 先在 wxml 文件中,创建绘制的 [代码]canvas[代码],并定义好 [代码]width[代码], [代码]height[代码], [代码]id[代码] , [代码]type[代码] ,其中type的值必须为[代码]2d[代码] [代码]<canvas type="2d" style="width: 260px; height: 260px;" id="myQrcode"></canvas> [代码] 安装方法1:直接引入 js 文件 直接引入 js 文件,使用 [代码]drawQrcode()[代码] 绘制二维码 [代码]// 将 dist 目录下,weapp.qrcode.esm.js 复制到项目中。路径根据实际引用的页面路径自行改变 import drawQrcode from '../../utils/weapp.qrcode.esm.js' [代码] 安装方法2:npm安装 [代码]npm install weapp-qrcode-canvas-2d --save [代码] // 然后需要在小程序开发者工具中:构建npm [代码]import drawQrcode from 'weapp-qrcode-canvas-2d' [代码] 安装完成后调用 例子1:没有使用叠加图片 [代码]const query = wx.createSelectorQuery() query.select('#myQrcode') .fields({ node: true, size: true }) .exec((res) => { var canvas = res[0].node // 调用方法drawQrcode生成二维码 drawQrcode({ canvas: canvas, canvasId: 'myQrcode', width: 260, padding: 30, background: '#ffffff', foreground: '#000000', text: 'abc', }) // 获取临时路径(得到之后,想干嘛就干嘛了) wx.canvasToTempFilePath({ canvasId: 'myQrcode', canvas: canvas, x: 0, y: 0, width: 260, height: 260, destWidth: 260, destHeight: 260, success(res) { console.log('二维码临时路径:', res.tempFilePath) }, fail(res) { console.error(res) } }) }) [代码] 例子2:使用叠加图片(在二维码中加logo) [代码]const query = wx.createSelectorQuery() query.select('#myQrcode') .fields({ node: true, size: true }) .exec((res) => { var canvas = res[0].node var img = canvas.createImage(); img.src = "/image/logo.png" img.onload = function () { // img.onload完成后才能调用 drawQrcode方法 var options = { canvas: canvas, canvasId: 'myQrcode', width: 260, padding: 30, paddingColor: '#fff', background: '#fff', foreground: '#000000', text: '123456789', image: { imageResource: img, width: 80, // 建议不要设置过大,以免影响扫码 height: 80, // 建议不要设置过大,以免影响扫码 round: true // Logo图片是否为圆形 } } drawQrcode(options) // 获取临时路径(得到之后,想干嘛就干嘛了) wx.canvasToTempFilePath({ x: 0, y: 0, width: 260, height: 260, destWidth: 600, destHeight: 600, canvasId: 'myQrcode', canvas: canvas, success(res) { console.log('二维码临时路径为:', res.tempFilePath) }, fail(res) { console.error(res) } }) }; }) [代码] API drawQrcode([options]) options Type: Object 参数 必须 说明 示例 canvas 必须 画布标识,传入 canvas 组件实例 canvasId 非 绘制的[代码]canvasId[代码] [代码]'myQrcode'[代码] text 必须 二维码内容 ‘123456789’ width 非 二维码宽度,与[代码]canvas[代码]的[代码]width[代码]保持一致 260 padding 非 空白内边距 20 paddingColor 非 内边距颜色 默认与background一致 background 非 二维码背景颜色,默认值白色 [代码]'#ffffff'[代码] foreground 非 二维码前景色,默认值黑色 [代码]'#000000'[代码] typeNumber 非 二维码的计算模式,默认值-1 8 correctLevel 非 二维码纠错级别,默认值为高级,取值:[代码]{ L: 1, M: 0, Q: 3, H: 2 }[代码] 1 image 非 在 canvas 上绘制图片,层级高于二维码,v1.1.1+版本支持。具体使用见:例子2 [代码]{imageResource: '', width:80, height: 80, round: true}[代码]
2023-04-02 - 云函数定时任务怎么搞?老板要开除我了
- 需求的场景描述(希望解决的问题) 我们公司需要一个定时任务 可以每天晚上进行数据处理,云函数怎么搞? - 希望提供的能力 提供定时任务函数, 或者提供数据库对外访问的接口,谢谢 2018-09-24 今天中秋节不幸接到了老板的消息 , 已经被开除了,,,,,,,,
2018-09-24 - 云开发如何避免接口被恶意频繁调用?
使用云开发,会不会有用户通过模拟程序恶意频繁调用接口的情况? 如果有,如何避免这种情况? 场景是:用户通过看广告获得积分,广告播放完毕后调用云函数为用户增加积分。我担心云函数被频繁调用,导致积分异常。
2020-10-14 - 云支付,pay_cb/functionName的正确打开姿势
纯代码:第一步就秒过: // pay_cb 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init() const db = cloud.database() const _ = db.command exports.main = async (event, context) => { //回调信息备案 await db.collection('cloudPay').doc(event.outTradeNo).set({ data:event }) //其他业务逻辑 return { errcode:0, errmsg:'SUCCESS' } } 更多内容: [图片]
2020-10-25 - 实战丨如何制作一个完整的外卖小程序(已开源)
最近微信小店开放了,赶着微信全面开放之前,把自己的小程序开源出来给大家使用~ 小程序效果 [图片] [图片] [图片] 开发心得 如何在项目中集成云开发 一开始项目并非基于云开发而开发的,目前考虑用云开发,因此,需要在项目中开启云开发的相关选项。 首先,在小程序文件夹中建立 [代码]cloud[代码] 文件夹,并在package文件中配置,建立用户登录的云函数并上传到微信小程序云中。相关的操作可以参考官方文档。 我在项目目录中添加了 [代码]cloud[代码] 和 [代码]miniprogram[代码] 两个目录,并在 [代码]project.config.json[代码] 文件夹进行配置 [代码]{ "miniprogramRoot": "./miniprogram" "cloudfunctionRoot": "./cloud/" } [代码] 开通云开发 配置完成后,可以点击控制台中的「云开发」来开通云开发。 [图片] 在云开发的界面中配置,并开通云开发。 [图片] 开通数据库集合 云开发不会自动创建数据库集合,因此,你需要手动创建集合。分别创建 店铺表Seller、分类表Category、商品表Food、订单表Order、地址表Address、用户表*_User*。 [图片] 数据操作 有了数据库的表后,就可以在代码中对数据进行操作了。 下方是我进行目录操作的代码。 [代码]const db = wx.cloud.database() const { showModal } = require('../../utils/utils') Page({ onLoad: function(options) { // 管理员认证 getApp().auth() if (options.objectId) { // 缓存数据 this.setData({ isEdit: true, objectId: options.objectId }) // 请求待编辑的分类对象 db.collection('Category') .doc(options.objectId) .get() .then(res => { // 获取分类信息 this.setData({ category: res.data }) }) } }, add: function(e) { var form = e.detail.value if (form.title == '') { wx.showModal({ title: '请填写分类名称', showCancel: false }) return } form.priority = Number.parseInt(form.priority) // 添加或者修改分类 // 修改模式 if (this.data.isEdit) { const category = this.data.category db.collection('Category') .doc(category._id) .update({ data: form }) .then(res => { console.log(res) showModal() }) } else { db.collection('Category') .add({ data: form }) .then(res => { console.log(res) showModal() }) } }, showModal() { // 操作成功提示并返回上一页 wx.showModal({ title: this.data.isEdit ? '修改成功' : '添加成功', showCancel: false, success: () => { wx.navigateBack() } }) }, delete: function() { // 确认删除对话框 wx.showModal({ title: '确认删除', success: res => { if (res.confirm) { const category = this.data.category db.collection('Category') .doc(category._id) .remove() .then(res => { console.log(res) wx.showToast({ title: '删除成功' }) wx.navigateBack() }) } } }) } }) [代码] 联表查询 在使用数据库时,难免要进行联表查询,云开发支持在云函数侧进行联表查询,你可以参考我的代码,来实现联表查询的功能。 [代码]const cloud = require('wx-server-sdk') cloud.init() const db = cloud.database() // 云函数入口函数 exports.main = async (event, context) => { const result = await db.collection('Food') .aggregate() .lookup({ from: 'Category', localField: 'category', foreignField: '_id', as: 'categories' }) .end() // .orderBy('priority', 'asc') // .get() console.log(result) return result.list } [代码] 文件上传 在小程序的操作中,难免会遇到需要进行图片上传的场景。在进行图片上传时,云开发提供了方便的云存储供我们查询数据。 在获取到文件的本地路径后,调用 [代码]wx.cloud.uploadFile[代码] 即可上传文件。 [代码]chooseImage() { wx.chooseImage({ count: 1, // 默认9 sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有 sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 success: res => { const tempFilePaths = res.tempFilePaths const file = tempFilePaths[0] const name = utils.random_filename(file) //上传的图片的别名,建议可以用日期命名 console.log(name) wx.cloud.uploadFile({ cloudPath: name, filePath: file, // 文件路径 }).then(res => { console.log(res) const fileId = res.fileID // 将文件id保存到数据库表中 db.collection('Seller').doc(this.data.seller._id) .update({ data: { logo_url: fileId } }).then(() => { wx.showToast({ title: '上传成功' }) // 渲染本地头像 this.setData({ new_logo: fileId }) }, err => { console.log(err) wx.showToast({ title: '上传失败' }) }) }) } }) } [代码] 微信支付逻辑的实现 作为一个商城,难免会有微信支付相关逻辑的实现。在这种情况下,可以借助云开发提供的微信支付云调用功能实现快速的 API 调用和接口的实现。 绑定商户 在使用云开发提供的微信支付时,需要先执行微信支付的绑定,在云开发控制台添加相应的商户号 [图片] 添加后微信会发来通知 [图片] 根据提示,开通账号即可。 [图片] 如果不绑定,将报“受理关系不存在”的错误 [图片] 函数代码调用 配置完成后,只需要在云函数中调用微信支付的接口,就可以实现相关调用的能力 [代码]const cloud = require('wx-server-sdk') cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) // 云函数入口函数 exports.main = async (event, context) => { console.log('请求中') console.log(cloud.getWXContext().ENV) let { orderId, amount, body } = event const wxContext = cloud.getWXContext() const res = await cloud.cloudPay.unifiedOrder({ body: body, outTradeNo: orderId, spbillCreateIp: '127.0.0.1', subMchId: '1447716902', totalFee: amount, envId: 'dinner-cloud', functionName: 'pay_cb' }) return res.payment } [代码] 这里 [代码]functionName: 'pay_cb'[代码]指的就是支付成功后,微信支付那侧给我的回调信息,后面我们就用它来更新我们的订单状态 小程序端代码调用 调用云函数后,会获得微信支付所需要的各种参数, [图片] 这个时候,就可以在小程序端调用微信支付接口,进行支付,相关代码可以参考 [代码]const { result: payData } = res wx.requestPayment({ timeStamp: payData.timeStamp, nonceStr: payData.nonceStr, package: payData.package, signType: 'MD5', paySign: payData.paySign, success: res => { console.log('支付成功', res) wx.showModal({ title: '支付成功', showCancel: false, success: () => { // 跳转订单详情页 wx.navigateTo({ url: '/order/detail/detail?objectId=' + order._id }) } }) }, ... [代码] 微信支付回调处理 微信统一下单里一个pay_cb回调函数,它是一个云函数,后续微信支付的支付信息将会发送在这个函数中,相应的,我们需要编写处理的方法 [代码]// 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init({ // API 调用都保持和云函数当前所在环境一致 env: cloud.DYNAMIC_CURRENT_ENV }) const db = cloud.database() // 云函数入口函数 exports.main = async (event, context) => { console.log('支付回调') console.log(event) console.log(cloud.getWXContext().ENV) const orderId = event.outTradeNo const resultCode = event.resultCode if (resultCode === 'SUCCESS') { const res = await db .collection('Order') .doc(orderId) .update({ data: { status: 1 } }) console.log(res) return { errcode: 0 } } } [代码] 总结 云开发体验下来,优点自不必多说,微信登录与支付原生支持,调用与调试都很方便,特别是不用启本地服务开发,真的好用; 这个小程序的源码我已经开源了,你可以访问社区官网 获取源码,自行使用~ 作者:黄秀杰,16年开始从事小程序开发与技术布道,同名个人公众号「黄秀杰」。 云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为开发者提供高可用、自动弹性扩缩的后端云服务,包含计算、存储、托管等serverless化能力,可用于云端一体化开发多种端应用(小程序,公众号,Web 应用,Flutter 客户端等),帮助开发者统一构建和管理后端服务和云资源,避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。 产品文档:https://cloud.tencent.com/product/tcb 技术文档:https://cloudbase.net 技术交流加Q群:601134960 最新资讯关注微信公众号【腾讯云云开发】
2020-07-29 - 微信云函数调用支付的时候,支付成功如何防止恶意调用
分析一下自己的做法!! 云函数发起支付,参考文档:developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/open/pay/CloudPay.unifiedOrder.html 如下代码 [图片] 用户支付成功是会调用pay_cb云函数的,也就是进行回调。 也表示,官方建议支付成功的处理逻辑在云函数里面写。 那么这就有一个问题。 恶意用户可以直接调用云函数,来绕过支付。 所以为了安全起见,我们可以加上一个判断:判断pay_cb是回调调用而不是用户直接调用。 这个判断利用了cloud.getWXContext() 代码很简单,如下: [图片] 感觉有帮助麻烦给我来个赞!!需要升级一下谢谢。
2021-03-27 - 借助小程序云开发实现小程序支付功能(含源码)
我们在做小程序支付相关的开发时,总会遇到这些难题。小程序调用微信支付时,必须要有自己的服务器,有自己的备案域名,有自己的后台开发。这就导致我们做小程序支付时的成本很大。本节就来教大家如何使用小程序云开发实现小程序支付功能的开发。不用搭建自己的服务器,不用有自己的备案域名。只需要简简单单的使用小程序云开发。 老规矩先看效果图: [图片] 本节知识点 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 - 微信小程序联表查询、跨时间段查询
需求分析 注意:小程序端不支持 lookup,所以我们退而求其次,交由云开发端实现这一功能。 联表查询 时间段匹配 分页 代码 闲言碎语不要讲咱们直接上干货: [代码]/** 函数前一定要写上 async */ /** * 请求参数 * @param {Date} startTime 查询开始时间 * @param {Date} endTime 查询结束时间 * @param {Number} limit 每页条目 * @param {Number} offset 页码 */ let { startTime, endTime, limit = 20, offset = 1 } = ctx._req.event; // 这个我使用了 tcb-router 包,你可以替换成自己获取请求参数的方法。 let matched = true; // 默认添加项 if (startTime && endTime) { // 这里要将小程序端请求的date类型再new date一下。 startTime = new Date(startTime); endTime = new Date(endTime); /** 时间转码(必需) */ let startTimeJson = $.dateFromString({ dateString: startTime.toJSON() }); /** 时间转码(必须) */ let endTimeJson = $.dateFromString({ dateString: endTime.toJSON() }); matched = $.and([$.gte(['$due', startTimeJson]), $.lte(['$due', endTimeJson])]); } ctx.body = await cloud.database().collection('xxx') .aggregate() .lookup({ from: 'billTag', localField: 'tagId', foreignField: '_id', as: 'tag', }) .addFields({ matched }) .match({ matched: true }) .sort({ due: -1, createTime: -1 }) .skip(offset * limit) .limit(limit) .end() .then(res => { log.log({ state: 'success', ...res }); return res; }) .catch(err => { log.error({ state: 'error', ...err }); return err; }); [代码] 参考链接 [1] 如何使用数据库聚合match过滤$.and? - 微信开放社区 https://developers.weixin.qq.com/community/develop/doc/000860ca140fd87ab5e8bd7075b400 [2] 云开发 聚合阶段 match无法根据时间查询? - 微信开放社区 https://developers.weixin.qq.com/community/develop/doc/000caa1ef70b98d59869e25c454400
2020-07-02 - 关于云开发的反爬、反抓、反刷、反反翻译的一些思考
最近接了个项目,甲方对于反爬、反抓包、反刷流量的要求令人发指,对我有限的代码保安知识真是一个巨大的挑战; 以下是一些经验总结: 一、关于反刷 本项目有大量的图片,放在云存储里,甲方怕有黑方用户不停地刷流量,造成套餐爆掉,所以特别要求,实际情况也确实发生了,仅不到100用户的时候,存储读取次数,一天就有10多万次,免费套餐被爆。采取措施如下: 1、关闭的有官方的页面收藏sitemap { "desc": "", "rules": [{ "action": "disallow", "page": "*" }] } 2、限制用户访问次数,比如限时超过1000次打开详情页就禁止,结果该方案被黑方破解数次,前后经历了多次方案: 将次数限制写在缓存里(删除小程序清缓存被破解); 将限时按手机时间来获取(修改手机时间被破解); 限时按服务器时间,次数写在云表里,才算解决; 二、关于反爬反抓 甲方有一些保密数据,由一些保密参数组成,通过运算得到一个价格再公布出去,一开始以为是云开发,读数据库和云函数都是保密的,结果惨遭泄密。 方案一:通过aggregate聚合,计算参数聚合出最终价格,悲伤的是,集合里的数字保存的字符串,不支持聚合的计算操作,云开发还没有任何办法批量将字符串形式的数字转成number,除非删库重建,一开始就保存成number。惨痛的教训,今后慎重,该是number的就number,别看前端可以随意,数据库里必须区分; 方案二:写一个页面,管理员输入参数,然后生成价格,应用到每一个doc里,结果数据量太大,批量修改集合所有数据的某字段值,目前用云开发完全没法实现。 最终方案:通过云函数来获取doc列表,在云函数里读取参数表,计算后生成价格,应用到每一条列表,然后再返回给小程序端; 结论:云函数是运行在微信服务器上的,还是安全的。 关于图片反爬反抓,结论:无解; 三、关于反翻译 官方的事,我们毫无办法。 设置里,什么混淆、什么代码保护等都勾上了,还是挡不住; 更多内容: [图片]
2020-10-20