您现在的位置是:网站首页> 小程序设计

小程序研发关注问题收集

摘要

小程序研发关注问题收集


1.jpg



***使用 Uniapp + UniCloud 云开发微信小程序***

使用 Uniapp + UniCloud 云开发微信小程序

小程序请求不备案不要HTTPS方法

uniapp实现如何使用微信小程序云开发技术实现数据存储和实时通信

实用代码

小程序收款


小程序请求不备案不要HTTPS方法

小程序网络限制

大家都知道,若想在小程序中发起网络请求访问我们的WEB后端,必须要做类似如下的操作:

1.备案你的域名!

2.给你的后端服务上SSL证书!

3.到微信公众平台设置小程序请求域名白名单!

小程序里调用API请求访问我们的后端数据!

这一流程,不难!但对很多人来说,忒麻烦!

所以,这个项目出现了。

得益于小程序的云开发功能,让我们可以突破这个限制,来达到请求任何可访问的http数据!
(如:ip访问、http 80端口访问、自定义端口访问、未备案域名等场景)

不备案,不需HTTPS,不用白名单,直接在小程序里调用我们的API,请求任意网络数据!


1分钟快速部署

首先,我们前往v-request项目的开源地址:

https://github.com/guren-cloud/v-request

里边会有详细的部署和使用方法,我这里也简单介绍一下,真的很简单!新手1分钟搞定!


部署云函数

项目分为两部分,一个是我们的小程序云函数代码,在cloud目录中。

我们首先在开发者工具开通小程序云开发平台,然后初始化好环境之后,创建一个云函数,命名为

命名为 v-request(不要命名错了,重要!)

1.png

然后把index.js和package.json文件的内容替换为项目cloud目录中对应的文件内容,再右键进行上传部署(云端安装依赖)操作:

1.png


部署客户端

另一个文件,就是主目录下的v-request.js文件,这个是运行在我们小程序里的SDK客户端文件。

我们把它放入小程序的目录,如utils/目录中,然后在app.js文件中进行require加载即可:

1.png


开始体验黑科技

通过上边的简单部署,你已经可以在小程序的任意位置,使用 wx.vrequest 方法来进行任意HTTP网络数据请求啦!

(注意:是 vrequest,比官方的 wx.request 方法名前多了个v,也就是 wx.vrequest 哦!)

以下操作均在开启校验域名、HTTPS等设置以及小程序后台未配置request白名单的情况下进行的测试


GET请求测试

wx.vrequest({

  url: 'https://mssnn.cn',

  success: ret => {

    console.log(ret.data);

  }

})

返回数据

1.png


POST请求测试

wx.login({

  success: ret => {

    wx.vrequest({

      url: 'https://wx5bbe79dd056cb238.mssnn.cn/v2/client/init',

      data: 'code=' + ret.code,

      dataType: 'json',

      method: 'POST',

      header: {

        'Content-Type': 'application/x-www-form-urlencoded'

          },

      success: res => {

        console.log('[post.res]', res);

      }

    })

  }

})


返回数据:

1.png

是不是感觉用法很熟悉?

对!和官方的 wx.request API保持一致!不需要耗费过多学习成本!


应用场景

这个方法,已经能够让我们突破了微信官方的request白名单限制,但我们应该在哪个场景里使用比较合适呢?

我这里总结了小部分你应该会遇到的场景:

网站域名没进行备案

网站目前还是http 80端口,未开启https和配置ssl证书

网站没有域名,通过ip地址访问的

隐藏访问流量中的隐私数据,提高小程序后端的安全性

如果你有以上的需求,不妨试试这个黑科技,解决这一痛点难题,提高小程序开发效率!

项目地址:https://github.com/guren-cloud/v-request

觉得不错,欢迎点个star!



uniapp实现如何使用微信小程序云开发技术实现数据存储和实时通信

点击查看原文

首先,我们需要在项目的app.vue文件中引入云开发的初始化函数并进行初始化。在创建云开发环境后,可以将环境ID填入初始化函数的参数中,如下所示:

import { init } from 'wx-server-sdk'


init({

  env: 'your-env-id' // 云开发环境ID

})


接下来,我们需要在需要使用云数据库的页面或组件中使用云开发的api。例如,我们想要从云数据库中读取用户的信息并展示在小程序中,可以在页面的onLoad函数中使用以下代码:

onLoad() {

  wx.cloud.init({

    env: 'your-env-id' // 云开发环境ID

  })

  const db = wx.cloud.database()

  db.collection('users').get({

    success: (res) => {

      console.log(res.data)

    },

    fail: (err) => {

      console.log(err)

    }

  })

}

通过上述代码,我们使用了wx.cloud.database()来获取数据库的引用,然后通过collection函数指定集合名称,并使用get函数获取该集合中的数据。之后,我们可以在success回调函数中处理获取到的数据。



除了数据存储,实时通信也是很多应用中必不可少的功能。微信小程序的云开发提供了实时数据库功能,可以用于实时通信等场景。下面我们将介绍如何在uniapp中使用实时数据库。

首先,我们还需要在项目的app.vue文件中引入云开发的初始化函数并进行初始化。同样地,将环境ID填入初始化函数的参数中。

然后,在需要使用实时数据库的页面或组件中使用以下代码:

onLoad() {

  wx.cloud.init({

    env: 'your-env-id' // 云开发环境ID

  })

  const db = wx.cloud.database()

  const watcher = db.collection('messages').where({

    _roomId: 'roomId' // 指定房间ID

  }).watch({

    onChange(snapshot) {

      console.log('docs changed:', snapshot.docs)

    },

    onError(err) {

      console.error('watch err', err)

    }

  })

}

上述代码中,我们使用了watch()函数来监听指定集合中数据的变化,并通过onChange回调函数获取变化的数据。在实际应用中,我们可以根据业务需求,监听不同的集合和条件,实现实时通信的功能。



使用 Uniapp + UniCloud 云开发微信小程序

点击进入unicloud主页

unicloud文档

查看视频教程

相关研发文章1

uniCloud和阿里云等传统云,的区别和关系

一、uniCloud是DCloud在阿里云和腾讯云的serverless服务上封装而成的

它包含laaS层(由阿里云和腾讯云提供硬件和网络)和PaaS层(由DCloud提供开发环境)。

开发者可以自主选择uniCloud的硬件和网络资源的供应商,在阿里云和腾讯云之间切换。

二、开户和付费虽然通过DCloud渠道,但实际上开发者自动在云厂商处建立了账户和充值了余额。

DCloûd只获取云服务厂商的返佣

、开发时虽使用DCloud的工具,但应用上线时,手机端是直连阿里云或腾讯云的serverless,

不经由DCloud的服务器。


1. 云函数(普通云函数)

服务端代码(云函数)

javascript

// cloudfunctions/getUserInfo/index.js

'use strict';

const db = uniCloud.database();


exports.main = async (event, context) => {

  const { userId } = event;

  if (!userId) {

    return {

      code: 400,

      message: '缺少参数 userId'

    };

  }


  try {

    const collection = db.collection('users');

    const res = await collection.doc(userId).get();

    if (res.data.length === 0) {

      return { code: 404, message: '用户不存在' };

    }

    return {

      code: 0,

      data: res.data[0]

    };

  } catch (err) {

    console.error(err);

    return { code: 500, message: err.message };

  }

};

客户端调用

javascript

// pages/demo/demo.vue

uniCloud.callFunction({

  name: 'getUserInfo',

  data: { userId: 'xxx' }

}).then(res => {

  console.log(res.result);

  if (res.result.code === 0) {

    const userInfo = res.result.data;

    // 处理用户信息

  }

}).catch(err => {

  console.error(err);

});

2. 云对象(更面向对象的方式)

服务端代码(云对象)

javascript

// cloudobjects/user/index.obj.js

module.exports = {

  _before: function() {

    // 前置钩子,可做权限校验

    console.log('调用前', this.getClientInfo());

  },

  async getInfo(userId) {

    if (!userId) {

      return { code: 400, message: '缺少 userId' };

    }

    const db = uniCloud.database();

    const res = await db.collection('users').doc(userId).get();

    if (res.data.length === 0) {

      return { code: 404, message: '用户不存在' };

    }

    return {

      code: 0,

      data: res.data[0]

    };

  },

  async updateName(userId, newName) {

    const db = uniCloud.database();

    await db.collection('users').doc(userId).update({

      name: newName

    });

    return { code: 0, message: '更新成功' };

  }

};

客户端调用

javascript

const userObj = uniCloud.importObject('user');

userObj.getInfo('xxx').then(res => {

  if (res.code === 0) {

    console.log(res.data);

  }

}).catch(err => {

  console.error(err);

});


// 调用多个参数

userObj.updateName('xxx', '新名字').then(res => {

  console.log(res.message);

});

3. 云数据库(clientDB / 云函数中操作)

3.1 客户端直接操作数据库(clientDB)

需要先在 uniCloud/database/db_init.json 中定义表结构和权限(permission)。


javascript

// 客户端直接查询

const db = uniCloud.database();

db.collection('goods')

  .where({

    price: db.command.gt(100)

  })

  .get()

  .then(res => {

    console.log(res.data);

  })

  .catch(err => {

    console.error(err);

  });


// 添加数据(需表权限允许)

db.collection('comments').add({

  content: '非常好',

  articleId: '123'

});

3.2 云函数中使用数据库

javascript

// cloudfunctions/addArticle/index.js

const db = uniCloud.database();

exports.main = async (event) => {

  const { title, content } = event;

  const res = await db.collection('articles').add({

    title,

    content,

    createTime: Date.now()

  });

  return { code: 0, id: res.id };

};

3.3 使用 DB Schema 和 JQL

在云函数或云对象中使用 uniCloud.databaseForJQL() 获得 JQL 实例。


javascript

const dbJQL = uniCloud.databaseForJQL();

const res = await dbJQL.collection('users')

  .where('name == $name')

  .field('name,age')

  .get({

    name: '张三'

  });

4. 云存储(上传、下载、删除文件)

客户端上传文件

javascript

// 选择图片后上传

uni.chooseImage({

  count: 1,

  success(chooseRes) {

    const tempFilePaths = chooseRes.tempFilePaths;

    uniCloud.uploadFile({

      filePath: tempFilePaths[0],

      cloudPath: 'avatar/' + Date.now() + '.png',

      success(res) {

        console.log('文件ID:', res.fileID);

        // 可直接用于 image 组件 src

        this.avatar = res.fileID;

      },

      fail(err) {

        console.error(err);

      }

    });

  }

});

云函数中操作云存储(例如删除文件)

javascript

// cloudfunctions/deleteFile/index.js

exports.main = async (event) => {

  const { fileID } = event;

  try {

    await uniCloud.deleteFile({

      fileList: [fileID]

    });

    return { code: 0, message: '删除成功' };

  } catch (err) {

    return { code: 500, message: err.message };

  }

};

获取临时链接(用于非uni-app环境展示图片)

javascript

uniCloud.getTempFileURL({

  fileList: ['cloud://xxx.png']

}).then(res => {

  const tempUrl = res.fileList[0].tempFileURL;

  // 可以使用该临时链接

});

5. WebSocket 在 uniCloud 中的实现方式

注意:uniCloud 云函数本身不支持 WebSocket 长连接。但你可以:

在客户端直接使用 uni-app 提供的 uni.connectSocket。

配合 uni-push2 实现服务端主动推送消息到客户端(类似 WebSocket 的推送能力)。


5.1 客户端 WebSocket 连接(与第三方 WebSocket 服务通信)

javascript

// 客户端建立 WebSocket 连接

const socketTask = uni.connectSocket({

  url: 'wss://your-websocket-server.com/path',

  success() {

    console.log('连接成功');

  }

});


// 监听打开事件

socketTask.onOpen(() => {

  console.log('WebSocket 已打开');

  socketTask.send({

    data: JSON.stringify({ type: 'join', roomId: '123' })

  });

});


// 接收消息

socketTask.onMessage(res => {

  console.log('收到消息:', res.data);

});


// 发送消息

function sendMsg(msg) {

  socketTask.send({ data: JSON.stringify(msg) });

}

5.2 使用 uni-push2 实现服务端主动推送(替代 WebSocket)

服务端云函数/云对象中调用推送


javascript

// cloudfunctions/sendPush/index.js

exports.main = async (event) => {

  const { userId, title, content } = event;

  const res = await uniCloud.sendPushMessage({

    user_id: [userId],          // 接收者的用户ID(需登录)

    title: title,

    content: content,

    payload: {

      type: 'notification',

      data: 'some data'

    }

  });

  return res;

};

客户端接收推送


在 App.vue 的 onLaunch 中监听推送消息:


javascript

// 监听推送消息

uni.onPushMessage((res) => {

  console.log('收到推送:', res.data);

  if (res.type === 'receive') {

    // 应用在前台时收到

    uni.showToast({ title: res.data.title });

  } else if (res.type === 'click') {

    // 用户点击通知栏打开应用

    uni.navigateTo({ url: '/pages/detail/detail' });

  }

});

使用 uni-push2 需要先在 uniCloud 控制台开通并配置厂商推送通道(个推、华为、小米等)。


新版云函数 WebSocket,的服务端与客户端调用例子

 服务端代码 (云对象)

这个云对象负责处理所有连接,并管理消息的广播。

新建云对象:在 HBuilderX 中,右键点击 uniCloud/cloudfunctions 目录,选择“新建云对象”,并将其命名为 ws-manager。

编写代码:以下是 ws-manager.obj.js 的完整代码,通过 ws.onConnect 等钩子来处理连接的生命周期。

javascript

// uniCloud/cloudfunctions/ws-manager/index.obj.js

module.exports = {

    // WebSocket 连接建立时触发

    'ws.onConnect': async function (event) {

        const { connectionId, query } = event;

        console.log(`[${connectionId}] 客户端连接成功,房间号: ${query.roomId}`);


        // 可以将 connectionId 存储到数据库,用于后续定向推送

        // 主动欢迎消息

        await uniCloud.ws.send({

            connectionId,

            data: `欢迎加入房间 ${query.roomId}!您的连接ID是 ${connectionId}`

        });

        return { success: true };

    },


    // 接收到客户端消息时触发

    'ws.onMessage': async function (event) {

        const { connectionId, data: message } = event;

        const parsedMessage = JSON.parse(message);

        console.log(`[${connectionId}] 收到消息:`, parsedMessage);


        // 处理业务逻辑,例如将收到的消息广播给房间内所有客户端

        // 此处示例:向所有已连接客户端广播消息

        const allConnections = await uniCloud.ws.getConnections();

        for (let conn of allConnections) {

            if (conn.id !== connectionId) {

                await uniCloud.ws.send({

                    connectionId: conn.id,

                    data: JSON.stringify({

                        type: 'broadcast',

                        from: connectionId,

                        content: parsedMessage.content

                    })

                });

            }

        }

    },


    // WebSocket 连接关闭时触发

    'ws.onClose': async function (event) {

        const { connectionId } = event;

        console.log(`[${connectionId}] 连接已关闭`);

        // 可以在此执行清理工作,如从数据库中移除 connectionId

    },


    // (可选) 连接出错时触发

    'ws.onError': async function (event) {

        console.error(`[${event.connectionId}] 连接出错:`, event.error);

    }

};

注意:云对象提供了 ws.onConnect、ws.onMessage、ws.onClose、ws.onError 这4个固定的钩子函数来分别处理WebSocket连接的每个生命周期事件。


💻 客户端代码 (uni-app 端)

客户端主要负责建立连接、收发消息,并处理网络波动等问题。

获取连接地址:WebSocket 云对象需要通过一个特殊的 wss 协议地址来连接。你需要先在 uniCloud Web 控制台,为 ws-manager 云对象开启 URL 化,并获取其 WebSocket 地址。获取到的地址格式通常类似 wss://xxxxxxxxxxxxx。

编写连接代码:在需要通信的页面,编写以下 JavaScript 代码来使用 WebSocket。


javascript

export default {

    data() {

        return {

            ws: null,

            messageList: []

        };

    },

    onLoad() {

        // 从第一步获取的完整 WebSocket 地址,例如 wss://xxxxx/websocket/ws-manager

        const wsUrl = 'wss://xxxxx/websocket/ws-manager';

        this.connectWebSocket(wsUrl);

    },

    methods: {

        // 1. 建立连接

        connectWebSocket(url) {

            this.ws = uni.connectSocket({

                url: url,

                success() {

                    console.log('WebSocket 连接创建成功');

                }

            });


            this.ws.onOpen(() => {

                console.log('WebSocket 连接已打开');

                uni.showToast({ title: '已连接', icon: 'success' });

            });


            // 2. 处理接收到的消息

            this.ws.onMessage((res) => {

                const message = JSON.parse(res.data);

                console.log('收到消息:', message);

                this.messageList.push(message);

            });


            // 3. 监听连接关闭事件

            this.ws.onClose(() => {

                console.log('WebSocket 连接已关闭');

                // 可以在此实现重连逻辑

            });


            this.ws.onError((err) => {

                console.error('WebSocket 连接发生错误', err);

            });

        },

        

        // 发送消息

        sendMessage(content) {

            if (this.ws && this.ws.readyState === WebSocket.OPEN) {

                const message = {

                    type: 'chat',

                    content: content,

                    timestamp: Date.now()

                };

                this.ws.send({ data: JSON.stringify(message) });

            } else {

                uni.showToast({ title: '连接尚未建立', icon: 'none' });

            }

        },


        // 主动关闭连接

        closeWebSocket() {

            if (this.ws) {

                this.ws.close();

                this.ws = null;

            }

        }

    },

    beforeDestroy() {

        // 页面销毁时记得关闭 WebSocket 连接

        this.closeWebSocket();

    }

};

🔐 鉴权与安全保障

为了保护你的 WebSocket 服务,可以在连接 URL 上传递 token 进行身份校验。你需要在服务端的 ws.onConnect 和客户端的 uni.connectSocket 中分别进行配置。

服务端 (ws-manager.obj.js):在 ws.onConnect 中,我们可以从 query 参数里拿到客户端传来的 token。


javascript

// 在 ws.onConnect 函数内部添加鉴权逻辑

'ws.onConnect': async function (event) {

    const { connectionId, query } = event;

    const clientToken = query.token;

    // 假设你的 secretToken 是 "my-secret-key-2026"

    if (clientToken !== 'my-secret-key-2026') {

        console.log(`[${connectionId}] token 验证失败,拒绝连接。`);

        return { success: false }; // 返回 false 以拒绝连接

    }

    // ... 验证通过后的逻辑

}

客户端:在连接时,将 token 作为查询参数附加到 WebSocket URL 后面。

javascript

const token = 'my-secret-key-2026';

const wsUrl = `wss://xxxxx/websocket/ws-manager?token=${token}&roomId=123456`;

this.connectWebSocket(wsUrl);




实用代码

支付老微信代码

// 云函数部分的代码

const cloud = require('wx-server-sdk')

cloud.init({

  env: cloud.DYNAMIC_CURRENT_ENV

})


exports.main = async (event, context) => {

  const res = await cloud.cloudPay.unifiedOrder({

    "body" : "商品描述",

    "outTradeNo" : "商户订单号",

    "spbillCreateIp" : "127.0.0.1",

    "totalFee" : 1,

// 用于接收支付异步通知的云函数所在的服务空间ID和云函数名

    "envId": "test-f0b102",

    "functionName": "pay_cb"

  })

  return res

}


// 小程序部分的代码

wx.cloud.callFunction({

  name: '函数名',

  data: {

    // ...

  },

  success: res => {

    const payment = res.result.payment

    wx.requestPayment({

      ...payment,

      success (res) {

        console.log('pay success', res)

      },

      fail (res) {

        console.error('pay fail', err)

      }

    })

  },

  fail: console.error,

})


...payment

... 是 ES6 的扩展运算符,作用是把 payment 对象里的所有属性和值 “展开” 到当前配置对象中;

payment 是一个提前准备好的支付参数对象,里面必须包含微信支付要求的核心参数,比如:

javascript

运行

// payment 对象的典型结构

const payment = {

  timeStamp: '1735689600', // 时间戳(字符串类型)

  nonceStr: 'abc123def456', // 随机字符串

  package: 'prepay_id=wx20260101123456789', // 预支付会话ID(核心)

  signType: 'MD5', // 签名类型

  paySign: 'xxxxxx' // 支付签名(后端生成)

}


在 ES6 及以上版本的 JavaScript 中,当一个对象的属性值是函数时,可以使用简写语法

省略属性名后的 :(冒号);

省略 function 关键字;

直接写 函数名(参数) { 函数体 },此时函数名就等价于对象的 key。

举个更简单的例子帮你理解:

javascript

运行

// 传统写法(ES5)

const obj = {

  sayHi: function (name) {

    console.log('Hi', name)

  }

}


// 简写写法(ES6+)—— 和上面完全等价

const obj = {

  sayHi (name) {

    console.log('Hi', name)

  }

}


迁移到uniCloud + uni-app体系,代码改成这样:

// 云函数部分的代码

const unipayIns = unipay.initWeixin({

  appId: 'your appId',

  mchId: 'your mchId',

  key: 'you parterner key',

  // pfx: fs.readFileSync('/path/to/your/pfxfile'), // p12文件路径,使用微信退款时需要,需要注意的是务必使用绝对路径

})



exports.main = async (event, context) => {

const res = await unipayIns.getOrderInfo({

openid: 'user openid',

body: '商品描述',

outTradeNo: '商户订单号',

totalFee: 1, // 金额,单位分

notifyUrl: 'https://xxx.xx' // 支付结果通知地址

})

  return res

}


// 客户端部分的代码

uniCloud.callFunction({

name: '云函数名',

data: {

// ...

},

success(res) {

uni.requestPayment({

provider: 'wxpay',

...res.result.orderInfo

success (res) {

  console.log('pay success', res)

},

fail (res) {

  console.error('pay fail', err)

}

})

}

})


小程序收款

注册个体户(定额报税一年一次),收费小程序前加个体名字
















Top