微信小程序

AI 交友小程序 + 会员订阅

用 CloudBase + 微信支付 + AI 编程,从零做一个带会员系统、推荐机制和线下活动的交友小程序。

背景

做完 AI 心情日记实战后,你已经有了小程序的基础能力。这一篇要上难度了:做一个 交友小程序。它的核心不是一个用户自己用,而是用户与用户之间的连接

这个场景有三个新东西是你在基础案例里没接触过的:

  • 会员订阅:年费玩家,不是单次购买
  • 推荐机制:怎么展示用户、让用户认识
  • 线下活动:活动发布 + 报名 + 人数限制

如果你能把这篇吃透,那市面上大部分小程序的付费模式你都能自己搭了。

完整链路只需要 4 步:

  1. 用户体系 + 资料采集:注册登录、完善个人资料
  2. 推荐系统:浏览其他用户信息、互动
  3. 会员系统(年费玩家):微信支付订阅 + 权益校验
  4. 线下活动:发布活动、报名、人数管理

注意:微信支付需要个体工商户或企业主体才能开通。如果你是个人开发者,这套案例中支付的流程仍然值得看——云调用 + 云函数的架构逻辑,换成其他支付平台(支付宝、聚合支付)思路是相通的。

项目概览

这个交友小程序的核心功能:

  • 会员(年费玩家):年费解锁全部权益——全年免费参加所有线下活动、查看其他用户的详细信息
  • 推荐:展示用户信息,促进用户间的认识与连接
  • 线下活动:发布活动、报名参加、人数限制

技术选型

模块技术
前端微信小程序原生 + TDesign UI
云服务CloudBase(云函数 + SQL 数据库 + 云存储)
登录手机号快速验证组件
支付微信支付(云调用)
AI 工具CloudBase MCP + CloudBase Skill

第一步:用户体系与资料采集

注册登录

沿用基础案例里的手机号登录方案——微信原生 getPhoneNumber 组件 + 云函数存储用户信息。

和心情日记不同之处在于,交友小程序需要更多的用户画像数据:昵称、头像、年龄、城市、职业、兴趣标签等。

云函数 register 在处理登录的同时,创建用户档案:

// 云函数 register(简化)
const cloud = require('wx-server-sdk')
cloud.init()
const db = cloud.database()

exports.main = async (event) => {
  const { OPENID } = cloud.getWXContext()
  const { phoneNumber, nickName, avatarUrl } = event

  // 检查用户是否存在
  const existing = await db.collection('users')
    .where({ openid: OPENID })
    .get()

  if (existing.data.length > 0) {
    return { isNew: false, user: existing.data[0] }
  }

  // 创建新用户
  const user = {
    openid: OPENID,
    phoneNumber,
    nickName,
    avatarUrl,
    isVip: false,
    vipExpireAt: null,
    createdAt: db.serverDate()
  }
  await db.collection('users').add({ data: user })
  return { isNew: true, user }
}

个人资料采集

用户注册后进入资料编辑页,填写兴趣标签(最多 5 个)、自我介绍、职业信息。这些数据是推荐系统的基础。

第二步:推荐系统

推荐系统最简单的第一版:按照距离 + 兴趣标签匹配度排序。

第一版推荐算法不要搞复杂。先按同城 + 共同标签数排序,够用了。等用户量上来再考虑协同过滤或者向量检索。

云函数 getRecommendations

// 云函数 getRecommendations 伪逻辑
const currentUser = getUser(event)
const allUsers = await db.collection('users').get()

// 按城市 + 共同标签数排序
const scored = allUsers
  .filter(u => u.openid !== currentUser.openid)
  .map(u => ({
    ...u,
    score: calcMatchScore(currentUser, u)
  }))
  .sort((a, b) => b.score - a.score)

return { data: scored.slice(0, 20) }

前端展示卡片式布局:头像、昵称、年龄、城市、兴趣标签。点击可查看详情(非会员只能看基本信息)。

第三步:会员系统(年费玩家)

这是整个案例最复杂的部分。核心逻辑:

用户点击"开通年费会员"
  → 云函数发起微信支付统一下单
  → 用户支付成功
  → 微信回调通知
  → 云函数处理回调:更新 users 表 isVip=true, vipExpireAt=一年后
  → 用户解锁会员权益

微信支付的接入方式

这里不是单次购买,而是订阅模式。不过在第一版,微信支付的接入方式是一样的——都是通过云调用(cloud.openapi.pay)。

关键区别在于:

维度心情日记(无支付)单次购买场景交友(会员订阅)
支付类型单次统一下单年费订阅
订单表orders(单次商品)member_orders(会员订单)
权益校验购买即解锁检查 isVip + vipExpireAt
到期处理检查过期自动降级

支付云函数核心逻辑

// 云函数 createMemberOrder(简化)
const cloud = require('wx-server-sdk')
cloud.init()

exports.main = async (event) => {
  const { OPENID } = cloud.getWXContext()

  // 检查是否已是会员且未过期
  const user = await getUser(OPENID)
  if (user.isVip && user.vipExpireAt > Date.now()) {
    return { code: 400, message: '已是会员' }
  }

  // 微信支付统一下单
  const result = await cloud.openapi.pay.unifiedOrder({
    subMchId: '你的商户号',
    totalFee: 19900,    // 199.00 元,以分为单位
    body: '年费会员',
    outTradeNo: generateOrderNo(),
    spbillCreateIp: '127.0.0.1',
    tradeType: 'JSAPI',
    openid: OPENID,
  })

  return { code: 0, payment: result.payment }
}

关于"受理关系不存在"的坑:如果你用直连商户(自己的商户号),不要传 sub_mch_idsub_openid。那是服务商模式用的。直连场景传入这些字段会报错。

会员权益校验

关键点在于:每个需要会员权限的接口,都要做校验

// 获取用户详情(需会员权限)
exports.main = async (event) => {
  const { OPENID } = cloud.getWXContext()
  const user = await getUser(OPENID)

  if (!user.isVip || user.vipExpireAt < Date.now()) {
    return { code: 403, message: '需要会员才能查看' }
  }

  // ... 返回用户详情
}

前端根据 isVip 控制 UI 显示:非会员看到的信息打码或截断,引导开通会员。

第四步:线下活动

活动模块包含:

  • 活动发布:管理员在后台发布(或社区用户发布需审核)
  • 活动浏览:按时间排序,显示报名人数/总名额
  • 活动报名:会员免费,非会员可付费单次参加

数据结构

活动表 events

字段类型说明
titlestring活动标题
descriptionstring活动描述
locationstring地点
startTimeDate开始时间
maxParticipantsnumber最大参与人数
currentCountnumber当前报名人数
pricenumber非会员费用(会员免费)
statusstring报名中/进行中/已结束

报名逻辑

exports.main = async (event) => {
  const { OPENID } = cloud.getWXContext()
  const { eventId } = event

  const user = await getUser(OPENID)
  const eventData = await db.collection('events').doc(eventId).get()

  if (eventData.currentCount >= eventData.maxParticipants) {
    return { code: 400, message: '名额已满' }
  }

  // 会员免费
  if (user.isVip && user.vipExpireAt > Date.now()) {
    await db.collection('event_registrations').add({
      data: { eventId, openid: OPENID, fee: 0, status: 'confirmed' }
    })
    // 更新报名人数
    await db.collection('events').doc(eventId).update({
      data: { currentCount: cloud.database().command.inc(1) }
    })
    return { code: 0, message: '报名成功(会员免费)' }
  }

  // 非会员需要支付
  // ... 发起微信支付
}

MCP 辅助开发要点

这个案例中 CloudBase MCP 能帮你做的事:

场景提示词示例
建表"在 SQL 数据库中创建 users、events、orders 三张表"
部署云函数"部署 register 云函数并开放 invoke 权限"
查日志"查看 createMemberOrder 云函数最近的报错"
配环境"配置云函数的微信支付商户号环境变量"

CloudBase MCP 是 2025-2026 年开发 CloudBase 应用的关键变化。没有 MCP 之前,AI 写 CloudBase 代码质量很差(文档不熟、API 猜错);有了 MCP,AI 可以直接查文档、建表、部署——整个体验接近 Supabase 的开发效率了。

关键教训

  1. 会员系统不只是支付:真正的复杂度在权益校验和过期处理。你需要在每个需要权限的接口都做一次校验,前端也要根据会员状态控制 UI 展示
  2. 推荐系统从笨的开始:第一版不需要向量检索,按城市 + 标签匹配就已经能用了。先把产品 MVP 验证了再优化算法
  3. 微信支付的坑:直连 vs 服务商的区别是 AI 最搞不清楚的部分,需要人工确认
  4. 数据安全:用户手机号、详细资料等敏感信息,云函数层面要做好权限控制,不要让非会员能查到