81 - 微信小程序开发与上架全流程指南

适用人群:想开发并发布微信小程序的开发者
难度:中等
预计阅读时间:30分钟

一、小程序概述

1.1 什么是微信小程序

微信小程序是运行在微信内部的轻量级应用,无需下载安装,扫码或搜索即可使用。截至2025年,微信小程序日活超过6亿,覆盖电商、工具、社交、服务等几乎所有领域。

对比小程序原生APPH5网页
安装不需要需要下载不需要
入口微信内桌面图标浏览器
性能中高最高
开发成本
推送能力有限完整
支付微信支付多种需对接
用户获取搜索/扫码/分享应用商店链接
包大小限制2MB(分包20MB)无限制无限制
适合场景轻量服务/工具/电商复杂应用信息展示

1.2 技术方案选择

方案语言特点适合
<strong>原生开发</strong>WXML+WXSS+JS性能最好,能力完整功能复杂/性能要求高
<strong>uni-app</strong>Vue.js一套代码多端(小程序/H5/APP)需要多端发布
<strong>Taro</strong>ReactReact语法写小程序React团队
<strong>mpvue</strong>Vue.jsVue语法(已停止维护)不推荐新项目
<strong>WePY</strong>类Vue早期框架(已过时)不推荐
新手推荐:原生开发(学习成本最低,文档最完善) 多端需求推荐:uni-app(同时生成H5和APP) React团队推荐:Taro


二、注册与准备

2.1 注册小程序账号

第1步:访问微信公众平台
├── 网址:https://mp.weixin.qq.com
├── 点击「立即注册」
└── 选择「小程序」

第2步:填写注册信息
├── 邮箱(未注册过公众平台的邮箱)
├── 密码
├── 验证邮箱
└── 选择主体类型

第3步:选择主体类型
├── 个人
│   ├── 需要:身份证信息
│   ├── 限制:不能微信支付、不能使用某些API
│   ├── 适合:个人工具、学习项目
│   └── 认证费:不可认证
│
├── 企业
│   ├── 需要:营业执照、对公账户
│   ├── 能力:完整功能(支付、直播等)
│   ├── 认证费:300元/年
│   └── 推荐:商业项目必选
│
├── 个体工商户
│   ├── 需要:营业执照
│   ├── 能力:支持微信支付
│   ├── 认证费:300元/年
│   └── 适合:小型商业项目
│
├── 政府
│   ├── 需要:组织机构代码证
│   └── 认证费:免费
│
└── 其他组织
    ├── 需要:组织机构代码证
    └── 认证费:300元/年

第4步:完善信息
├── 登录小程序后台
├── 设置 → 基本设置
│   ├── 小程序名称(唯一,不可与已有重复)
│   ├── 小程序头像
│   ├── 小程序简介
│   └── 服务类目(选择对应行业)
└── 开发 → 开发管理 → 开发设置
    ├── AppID(小程序唯一标识,重要!)
    ├── AppSecret(密钥,不要泄露)
    └── 服务器域名(合法域名白名单)

2.2 服务类目与资质要求

不同服务类目需要不同的资质:

无需资质:
├── 工具(计算器、天气、日历等)
├── 教育(在线教育信息)
├── 生活服务(家政、维修)
└── 旅游(旅游攻略)

需要资质:
├── 电商 → ICP备案(可选,平台类需要EDI)
├── 餐饮 → 食品经营许可证
├── 医疗 → 互联网医疗保健信息服务许可证
├── 金融 → 金融业务许可证
├── 教育培训 → 教育培训资质
├── 新闻 → 互联网新闻信息服务许可证
├── 出版 → 网络出版服务许可证
├── 游戏 → 网络文化经营许可证
├── 直播 → 信息网络传播视听节目许可证
└── 社交 → ICP备案

注意:选择的服务类目必须与实际功能一致
     微信会定期审核,功能不符会被下架

2.3 开发环境搭建

第1步:下载微信开发者工具
├── 下载地址:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
├── 选择对应系统版本(Windows/macOS)
└── 安装并登录(使用注册小程序的微信扫码)

第2步:创建项目
├── 打开开发者工具
├── 点击「+」新建项目
├── 填写信息
│   ├── 项目目录:选择本地文件夹
│   ├── AppID:填写真实AppID(不要用测试号)
│   ├── 项目名称
│   └── 开发模式:小程序
├── 后端服务:不使用云服务 / 使用微信云开发
└── 模板:选择「基础模板」或「空白项目」

第3步:项目设置
├── 详情 → 本地设置
│   ├── 勾选「不校验合法域名」(开发阶段)
│   ├── 勾选「ES6转ES5」
│   ├── 勾选「增强编译」
│   └── 勾选「使用npm模块」
└── 详情 → 基本信息
    ├── 确认AppID正确
    └── 查看项目配置


三、小程序开发详解

3.1 项目结构

miniprogram/
├── app.js                    # 小程序入口(全局逻辑)
├── app.json                  # 全局配置(页面路由/窗口/TabBar)
├── app.wxss                  # 全局样式
├── project.config.json       # 项目配置
├── sitemap.json              # 搜索优化配置
│
├── pages/                    # 页面目录
│   ├── index/                # 首页
│   │   ├── index.js          # 页面逻辑
│   │   ├── index.json        # 页面配置
│   │   ├── index.wxml        # 页面模板(类似HTML)
│   │   └── index.wxss        # 页面样式(类似CSS)
│   ├── category/             # 分类页
│   │   ├── category.js
│   │   ├── category.json
│   │   ├── category.wxml
│   │   └── category.wxss
│   ├── detail/               # 详情页
│   │   ├── detail.js
│   │   ├── detail.json
│   │   ├── detail.wxml
│   │   └── detail.wxss
│   ├── cart/                 # 购物车
│   │   ├── cart.js
│   │   ├── cart.json
│   │   ├── cart.wxml
│   │   └── cart.wxss
│   └── user/                 # 个人中心
│       ├── user.js
│       ├── user.json
│       ├── user.wxml
│       └── user.wxss
│
├── components/               # 自定义组件
│   ├── product-card/         # 商品卡片组件
│   │   ├── product-card.js
│   │   ├── product-card.json
│   │   ├── product-card.wxml
│   │   └── product-card.wxss
│   └── loading/              # 加载组件
│       ├── loading.js
│       ├── loading.json
│       ├── loading.wxml
│       └── loading.wxss
│
├── utils/                    # 工具函数
│   ├── request.js            # 网络请求封装
│   ├── auth.js               # 登录鉴权
│   ├── storage.js            # 本地存储
│   └── util.js               # 通用工具
│
├── services/                 # 业务接口
│   ├── user.js               # 用户相关接口
│   ├── product.js            # 商品相关接口
│   └── order.js              # 订单相关接口
│
├── images/                   # 图片资源
│   ├── icons/
│   └── tabbar/
│
└── miniprogram_npm/          # npm构建后的包

3.2 核心配置文件

// app.json - 全局配置
{
  "pages": [
    "pages/index/index",
    "pages/category/category",
    "pages/detail/detail",
    "pages/cart/cart",
    "pages/user/user",
    "pages/login/login",
    "pages/order/order",
    "pages/address/address"
  ],
  "window": {
    "navigationBarBackgroundColor": "#ffffff",
    "navigationBarTitleText": "我的小程序",
    "navigationBarTextStyle": "black",
    "backgroundColor": "#f5f5f5",
    "backgroundTextStyle": "dark"
  },
  "tabBar": {
    "color": "#999999",
    "selectedColor": "#ff6b00",
    "backgroundColor": "#ffffff",
    "borderStyle": "black",
    "list": [
      {
        "pagePath": "pages/index/index",
        "text": "首页",
        "iconPath": "images/tabbar/home.png",
        "selectedIconPath": "images/tabbar/home-active.png"
      },
      {
        "pagePath": "pages/category/category",
        "text": "分类",
        "iconPath": "images/tabbar/category.png",
        "selectedIconPath": "images/tabbar/category-active.png"
      },
      {
        "pagePath": "pages/cart/cart",
        "text": "购物车",
        "iconPath": "images/tabbar/cart.png",
        "selectedIconPath": "images/tabbar/cart-active.png"
      },
      {
        "pagePath": "pages/user/user",
        "text": "我的",
        "iconPath": "images/tabbar/user.png",
        "selectedIconPath": "images/tabbar/user-active.png"
      }
    ]
  },
  "permission": {
    "scope.userLocation": {
      "desc": "用于获取您的位置信息,提供附近服务"
    }
  },
  "requiredPrivateInfos": ["getLocation"],
  "usingComponents": {
    "loading": "/components/loading/loading"
  },
  "networkTimeout": {
    "request": 10000,
    "downloadFile": 10000
  },
  "lazyCodeLoading": "requiredComponents"
}

// project.config.json - 项目配置
{
  "description": "项目配置文件",
  "packOptions": {
    "ignore": [
      { "type": "file", "value": ".eslintrc.js" }
    ]
  },
  "setting": {
    "urlCheck": false,          // 开发阶段关闭域名校验
    "es6": true,                // ES6转ES5
    "enhance": true,            // 增强编译
    "postcss": true,            // 自动补全CSS
    "preloadBackgroundData": false,
    "minified": true,           // 代码压缩
    "newFeature": true,
    "autoAudits": false,
    "checkInvalidKey": true,
    "checkSiteMap": true,
    "uploadWithSourceMap": true,
    "compileHotReLoad": true,
    "babelSetting": {
      "ignore": [],
      "disablePlugins": [],
      "outputPath": ""
    }
  },
  "compileType": "miniprogram",
  "appid": "your-appid-here",
  "projectname": "my-miniprogram",
  "condition": {}
}

3.3 核心代码示例

// app.js - 全局入口
App({
  globalData: {
    userInfo: null,
    token: null,
    baseUrl: 'https://api.example.com'
  },

  onLaunch() {
    // 小程序启动时执行
    this.checkLogin()
    this.getSystemInfo()
  },

  // 检查登录状态
  checkLogin() {
    const token = wx.getStorageSync('token')
    if (token) {
      this.globalData.token = token
    }
  },

  // 获取系统信息
  getSystemInfo() {
    const info = wx.getSystemInfoSync()
    this.globalData.statusBarHeight = info.statusBarHeight
    this.globalData.screenHeight = info.screenHeight
    this.globalData.isIPhoneX = info.model.includes('iPhone X') || 
                                 info.safeArea.top > 20
  }
})

// utils/request.js - 网络请求封装
const app = getApp()

const request = (options) => {
  return new Promise((resolve, reject) => {
    wx.request({
      url: `${app.globalData.baseUrl}${options.url}`,
      method: options.method || 'GET',
      data: options.data || {},
      header: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${app.globalData.token || ''}`,
        ...options.header
      },
      success(res) {
        if (res.statusCode === 200) {
          if (res.data.code === 0) {
            resolve(res.data.data)
          } else if (res.data.code === 401) {
            // token过期,跳转登录
            wx.removeStorageSync('token')
            wx.navigateTo({ url: '/pages/login/login' })
            reject(new Error('登录已过期'))
          } else {
            wx.showToast({ title: res.data.message || '请求失败', icon: 'none' })
            reject(new Error(res.data.message))
          }
        } else {
          wx.showToast({ title: `网络错误(${res.statusCode})`, icon: 'none' })
          reject(new Error(`HTTP ${res.statusCode}`))
        }
      },
      fail(err) {
        wx.showToast({ title: '网络连接失败', icon: 'none' })
        reject(err)
      }
    })
  })
}

module.exports = { request }

<!-- pages/index/index.wxml - 首页模板 -->
<view class="container">
  <!-- 搜索栏 -->
  <view class="search-bar" bindtap="goSearch">
    <view class="search-input">
      <text class="icon-search"></text>
      <text class="placeholder">搜索商品</text>
    </view>
  </view>

  <!-- 轮播图 -->
  <swiper class="banner" 
          indicator-dots="{{true}}" 
          autoplay="{{true}}" 
          interval="{{3000}}"
          circular="{{true}}">
    <swiper-item wx:for="{{banners}}" wx:key="id">
      <image src="{{item.image}}" mode="aspectFill" 
             bindtap="onBannerTap" data-id="{{item.linkId}}"/>
    </swiper-item>
  </swiper>

  <!-- 分类导航 -->
  <view class="category-nav">
    <view class="category-item" 
          wx:for="{{categories}}" wx:key="id"
          bindtap="goCategory" data-id="{{item.id}}">
      <image src="{{item.icon}}" class="category-icon"/>
      <text class="category-name">{{item.name}}</text>
    </view>
  </view>

  <!-- 商品列表 -->
  <view class="section">
    <view class="section-title">热门推荐</view>
    <view class="product-list">
      <view class="product-card" 
            wx:for="{{products}}" wx:key="id"
            bindtap="goDetail" data-id="{{item.id}}">
        <image src="{{item.image}}" mode="aspectFill" class="product-image"/>
        <view class="product-info">
          <text class="product-name">{{item.name}}</text>
          <text class="product-desc">{{item.desc}}</text>
          <view class="product-price-row">
            <text class="product-price">¥{{item.price}}</text>
            <text class="product-origin-price" wx:if="{{item.originPrice}}">
              ¥{{item.originPrice}}
            </text>
          </view>
        </view>
      </view>
    </view>
  </view>

  <!-- 加载更多 -->
  <view class="load-more" wx:if="{{hasMore}}">
    <loading wx:if="{{loading}}"/>
    <text wx:else bindtap="loadMore">加载更多</text>
  </view>
  <view class="no-more" wx:if="{{!hasMore && products.length > 0}}">
    — 没有更多了 —
  </view>
</view>

// pages/index/index.js - 首页逻辑
const { request } = require('../../utils/request')

Page({
  data: {
    banners: [],
    categories: [],
    products: [],
    page: 1,
    hasMore: true,
    loading: false
  },

  onLoad() {
    this.loadBanners()
    this.loadCategories()
    this.loadProducts()
  },

  // 下拉刷新
  onPullDownRefresh() {
    this.setData({ page: 1, products: [], hasMore: true })
    Promise.all([
      this.loadBanners(),
      this.loadProducts()
    ]).finally(() => {
      wx.stopPullDownRefresh()
    })
  },

  // 上拉加载更多
  onReachBottom() {
    if (this.data.hasMore && !this.data.loading) {
      this.loadMore()
    }
  },

  // 加载轮播图
  async loadBanners() {
    const banners = await request({ url: '/api/banners' })
    this.setData({ banners })
  },

  // 加载分类
  async loadCategories() {
    const categories = await request({ url: '/api/categories' })
    this.setData({ categories })
  },

  // 加载商品
  async loadProducts() {
    if (this.data.loading) return
    this.setData({ loading: true })
    try {
      const products = await request({
        url: '/api/products',
        data: { page: this.data.page, limit: 10 }
      })
      this.setData({
        products: this.data.page === 1 
          ? products 
          : [...this.data.products, ...products],
        hasMore: products.length >= 10,
        page: this.data.page + 1
      })
    } finally {
      this.setData({ loading: false })
    }
  },

  loadMore() {
    this.loadProducts()
  },

  goSearch() {
    wx.navigateTo({ url: '/pages/search/search' })
  },

  goCategory(e) {
    const id = e.currentTarget.dataset.id
    wx.navigateTo({ url: `/pages/category/category?id=${id}` })
  },

  goDetail(e) {
    const id = e.currentTarget.dataset.id
    wx.navigateTo({ url: `/pages/detail/detail?id=${id}` })
  },

  onBannerTap(e) {
    const id = e.currentTarget.dataset.id
    if (id) {
      wx.navigateTo({ url: `/pages/detail/detail?id=${id}` })
    }
  },

  // 分享
  onShareAppMessage() {
    return {
      title: '发现好物,快来看看!',
      path: '/pages/index/index'
    }
  },

  onShareTimeline() {
    return {
      title: '发现好物,快来看看!'
    }
  }
})

// pages/index/index.json - 首页页面配置
{
  "navigationBarTitleText": "首页",
  "enablePullDownRefresh": true,
  "backgroundTextStyle": "dark",
  "usingComponents": {
    "loading": "/components/loading/loading"
  }
}

/* pages/index/index.wxss - 首页样式 */
.container {
  background: #f5f5f5;
  min-height: 100vh;
}

.search-bar {
  padding: 20rpx 30rpx;
  background: #fff;
}

.search-input {
  display: flex;
  align-items: center;
  padding: 16rpx 24rpx;
  background: #f5f5f5;
  border-radius: 36rpx;
  gap: 12rpx;
}

.placeholder {
  color: #999;
  font-size: 28rpx;
}

.banner {
  width: 100%;
  height: 360rpx;
}

.banner image {
  width: 100%;
  height: 100%;
}

.category-nav {
  display: flex;
  flex-wrap: wrap;
  padding: 30rpx 20rpx;
  background: #fff;
  margin-bottom: 20rpx;
}

.category-item {
  width: 20%;
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-bottom: 20rpx;
}

.category-icon {
  width: 88rpx;
  height: 88rpx;
  margin-bottom: 10rpx;
}

.category-name {
  font-size: 24rpx;
  color: #333;
}

.section {
  background: #fff;
  padding: 30rpx;
}

.section-title {
  font-size: 32rpx;
  font-weight: bold;
  color: #333;
  margin-bottom: 24rpx;
}

.product-list {
  display: flex;
  flex-wrap: wrap;
  gap: 20rpx;
}

.product-card {
  width: calc(50% - 10rpx);
  background: #fff;
  border-radius: 16rpx;
  overflow: hidden;
  box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
}

.product-image {
  width: 100%;
  height: 340rpx;
}

.product-info {
  padding: 16rpx 20rpx;
}

.product-name {
  font-size: 26rpx;
  color: #333;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.product-desc {
  font-size: 22rpx;
  color: #999;
  margin-top: 8rpx;
}

.product-price-row {
  display: flex;
  align-items: baseline;
  gap: 12rpx;
  margin-top: 12rpx;
}

.product-price {
  font-size: 32rpx;
  color: #ff6b00;
  font-weight: bold;
}

.product-origin-price {
  font-size: 22rpx;
  color: #ccc;
  text-decoration: line-through;
}

.load-more, .no-more {
  text-align: center;
  padding: 30rpx;
  color: #999;
  font-size: 24rpx;
}

3.4 微信登录与用户信息

// utils/auth.js - 登录模块
const { request } = require('./request')

// 微信登录(获取openid)
const wxLogin = () => {
  return new Promise((resolve, reject) => {
    wx.login({
      success(res) {
        if (res.code) {
          // 将code发送到后端换取openid和session_key
          request({
            url: '/api/auth/wx-login',
            method: 'POST',
            data: { code: res.code }
          }).then(data => {
            // 保存token
            wx.setStorageSync('token', data.token)
            getApp().globalData.token = data.token
            getApp().globalData.userInfo = data.userInfo
            resolve(data)
          }).catch(reject)
        } else {
          reject(new Error('登录失败'))
        }
      },
      fail: reject
    })
  })
}

// 获取用户信息(需要用户授权)
const getUserProfile = () => {
  return new Promise((resolve, reject) => {
    wx.getUserProfile({
      desc: '用于完善用户资料',
      success(res) {
        resolve(res.userInfo)
      },
      fail(err) {
        reject(err)
      }
    })
  })
}

// 检查登录状态并跳转
const checkLoginAndRedirect = () => {
  const token = wx.getStorageSync('token')
  if (!token) {
    wx.navigateTo({ url: '/pages/login/login' })
    return false
  }
  return true
}

module.exports = { wxLogin, getUserProfile, checkLoginAndRedirect }

// services/user.js - 用户相关接口
const { request } = require('../utils/request')

// 获取用户信息
const getUserInfo = () => request({ url: '/api/user/info' })

// 更新用户信息
const updateUserInfo = (data) => request({
  url: '/api/user/info',
  method: 'PUT',
  data
})

// 获取收货地址列表
const getAddressList = () => request({ url: '/api/user/addresses' })

// 添加收货地址
const addAddress = (data) => request({
  url: '/api/user/addresses',
  method: 'POST',
  data
})

module.exports = { getUserInfo, updateUserInfo, getAddressList, addAddress }

3.5 微信支付集成

// utils/payment.js - 微信支付
const { request } = require('./request')

/**
 * 发起微信支付
 * @param {string} orderId 订单ID
 */
const wxPayment = (orderId) => {
  return new Promise(async (resolve, reject) => {
    try {
      // 1. 从后端获取支付参数
      const payParams = await request({
        url: '/api/pay/create',
        method: 'POST',
        data: { orderId }
      })

      // 2. 调用微信支付
      wx.requestPayment({
        timeStamp: payParams.timeStamp,
        nonceStr: payParams.nonceStr,
        package: payParams.package,
        signType: payParams.signType || 'MD5',
        paySign: payParams.paySign,
        
        success(res) {
          // 支付成功
          resolve(res)
        },
        fail(err) {
          if (err.errMsg.includes('cancel')) {
            // 用户取消
            reject(new Error('用户取消支付'))
          } else {
            // 支付失败
            reject(new Error('支付失败'))
          }
        }
      })
    } catch (err) {
      reject(err)
    }
  })
}

module.exports = { wxPayment }


四、自定义组件开发

// components/product-card/product-card.js
Component({
  // 属性
  properties: {
    product: {
      type: Object,
      value: {}
    },
    showAction: {
      type: Boolean,
      value: true
    }
  },

  // 数据
  data: {
    isFavorite: false
  },

  // 方法
  methods: {
    onTap() {
      this.triggerEvent('tap', { id: this.properties.product.id })
    },

    onFavorite(e) {
      this.setData({ isFavorite: !this.data.isFavorite })
      this.triggerEvent('favorite', { 
        id: this.properties.product.id,
        isFavorite: this.data.isFavorite
      })
    },

    onAddCart(e) {
      this.triggerEvent('addcart', { id: this.properties.product.id })
    }
  }
})

<!-- components/product-card/product-card.wxml -->
<view class="card" bindtap="onTap">
  <image src="{{product.image}}" mode="aspectFill" class="image"/>
  <view class="info">
    <text class="name">{{product.name}}</text>
    <view class="bottom">
      <text class="price">¥{{product.price}}</text>
      <view class="actions" wx:if="{{showAction}}">
        <view class="btn-fav {{isFavorite ? 'active' : ''}}" 
              catchtap="onFavorite">
          {{isFavorite ? '已收藏' : '收藏'}}
        </view>
        <view class="btn-cart" catchtap="onAddCart">加入购物车</view>
      </view>
    </view>
  </view>
</view>

// components/product-card/product-card.json
{
  "component": true,
  "usingComponents": {}
}


五、云开发(可选)

微信云开发是Serverless方案,无需自己搭建服务器。

功能:
├── 云函数:Node.js运行环境,按调用计费
├── 云数据库:JSON数据库,类似MongoDB
├── 云存储:文件上传下载
└── 云托管:容器化部署

开通步骤:
1. 开发者工具 → 云开发 → 开通
2. 创建环境(免费版有配额限制)
3. 在app.js中初始化

费用(按量计费):
├── 云函数:0.00011108元/GB·秒
├── 数据库:0.007元/万次读,0.035元/万次写
├── 存储:0.0043元/GB·天
└── 免费额度:每月有一定的免费配额

// 云函数示例:cloud/functions/login/index.js
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })

exports.main = async (event) => {
  const wxContext = cloud.getWXContext()
  
  return {
    openid: wxContext.OPENID,
    appid: wxContext.APPID,
    unionid: wxContext.UNIONID
  }
}

// 前端调用云函数
wx.cloud.callFunction({
  name: 'login',
  data: {},
  success(res) {
    console.log('openid:', res.result.openid)
  }
})

// 云数据库操作
const db = wx.cloud.database()
const _ = db.command

// 添加
await db.collection('todos').add({
  data: { text: '学习小程序', done: false, createTime: db.serverDate() }
})

// 查询
const { data } = await db.collection('todos')
  .where({ done: false })
  .orderBy('createTime', 'desc')
  .limit(20)
  .get()

// 更新
await db.collection('todos').doc('doc-id').update({
  data: { done: true }
})

// 删除
await db.collection('todos').doc('doc-id').remove()


六、体验版与审核前测试

6.1 体验版发布

体验版用于内部测试,无需审核。

步骤:
1. 开发者工具 → 点击「上传」
2. 填写版本号(如 1.0.0)和项目备注
3. 上传成功后,在小程序后台操作
4. 登录 mp.weixin.qq.com
5. 管理 → 版本管理
6. 在「开发版本」中找到刚上传的版本
7. 点击「选为体验版」
8. 设置体验版有效期(最长30天)

添加体验成员:
1. 成员管理 → 体验成员
2. 添加微信号(最多15人,未认证账号)
3. 认证后最多200人

体验成员使用:
1. 微信扫码体验版二维码
2. 或搜索小程序名称 → 切换到体验版

6.2 调试与排查

常见问题排查:

1. 白屏/页面不显示
   ├── 检查pages路径是否正确
   ├── 检查JSON配置是否有语法错误
   └── 查看Console日志

2. 网络请求失败
   ├── 检查是否配置了合法域名
   ├── 开发阶段:设置 → 不校验合法域名
   ├── 生产环境:必须配置HTTPS域名
   └── 检查域名是否有ICP备案

3. 登录失败
   ├── 确认AppID是否正确
   ├── 确认后端session_key处理是否正确
   └── 不要将session_key传给前端

4. 支付失败
   ├── 确认已开通微信支付
   ├── 确认商户号与小程序已关联
   ├── 确认支付参数签名正确
   └── 确认金额单位为分

5. 组件不显示
   ├── 检查usingComponents配置
   ├── 检查组件路径是否正确
   └── 检查组件JSON中component字段是否为true


七、提交审核与发布

7.1 提交审核完整流程

第1步:代码上传
├── 开发者工具 → 点击「上传」
├── 版本号:语义化版本(如 1.0.0)
├── 项目备注:说明本次更新内容
└── 等待上传完成

第2步:配置审核信息
├── 登录 mp.weixin.qq.com
├── 管理 → 版本管理
├── 在「开发版本」中找到版本
├── 点击「提交审核」
├── 填写审核信息:
│   ├── 测试账号(如果需要登录)
│   │   ├── 账号:xxx
│   │   └── 密码:xxx
│   ├── 测试密码(如果功能有密码保护)
│   ├── 补充说明(审核员需要注意的事项)
│   └── 配置功能页面(重要!)
│       ├── 添加小程序的功能页面路径
│       ├── 填写标题
│       └── 上传截图(展示核心功能)
└── 确认提交

第3步:等待审核
├── 审核时间:通常1-7天
├── 加急审核:每年有3次加急机会,2小时内出结果
├── 查看审核状态:
│   ├── mp.weixin.qq.com → 版本管理
│   └── 微信通知
└── 审核结果通知方式:
    ├── 邮件通知
    ├── 微信公众平台通知
    └── 微信服务通知

第4步:审核结果处理
├── 审核通过
│   ├── 可选择「立即发布」或「定时发布」
│   ├── 发布后全量用户可用
│   └── 建议在流量低峰期发布(凌晨)
│
├── 审核被拒
│   ├── 查看拒绝原因(详细说明)
│   ├── 修复问题
│   ├── 重新上传并提交
│   └── 可在7天内申诉
│
└── 常见拒绝原因及解决
    ├── 功能不完整/无法使用
    │   └── 确保所有页面和功能可正常访问
    ├── 内容违规
    │   └── 检查是否违反平台规则
    ├── 类目不符
    │   └── 修改服务类目或取得相应资质
    ├── 缺少测试账号
    │   └── 提供可登录的测试账号
    ├── 页面无法访问
    │   └── 确保服务器正常运行
    └── UI设计问题
        └── 确保界面完整、美观、无乱码

7.2 审核要点清单

提交前自查清单:

□ 所有页面可以正常打开
□ 所有功能可以正常使用(不要有TODO/占位符)
□ 网络请求域名已配置到合法域名
□ 服务器正常运行,接口返回正常
□ 登录功能正常(如需要登录)
□ 支付功能正常(如有支付)
□ 图片和资源加载正常
□ 页面布局在不同机型上正常显示
□ 没有明显的Bug和崩溃
□ 没有测试数据和调试代码
□ 隐私政策页面可访问
□ 用户协议页面可访问(如有)
□ 服务类目与实际功能一致
□ 已取得所需资质(如有)
□ 提供了测试账号(如需要登录)
□ 没有诱导分享、诱导关注等行为
□ 没有虚拟支付(iOS端限制)
□ 没有未报备的直播功能
□ 内容健康,不违反法律法规

7.3 版本更新与灰度发布

版本更新流程:
1. 开发新版本
2. 上传代码
3. 提交审核
4. 审核通过
5. 发布(可选择灰度发布)

灰度发布(逐步放量):
├── 发布时选择「灰度发布」
├── 设置灰度比例(如先放10%用户)
├── 观察数据和反馈
├── 没有问题后逐步增加比例
└── 最终全量发布

版本回退:
├── 如果新版本有严重问题
├── 版本管理 → 已发布版本 → 回退
├── 只能回退到上一个版本
└── 回退后需要重新提交审核才能再次发布


八、小程序运营与数据分析

8.1 数据分析

小程序后台提供的数据:

1. 概况数据
   ├── 累计用户数
   ├── 昨日新增用户
   ├── 昨日活跃用户
   └── 今日实时数据

2. 访问分析
   ├── 访问次数/人数
   ├── 新访客/老访客比例
   ├── 平均停留时长
   ├── 次均停留时长
   ├── 访问深度分布
   └── 访问页面排行

3. 实时统计
   ├── 实时访问曲线
   ├── 实时访问来源
   └── 实时访客地区分布

4. 用户画像
   ├── 性别分布
   ├── 年龄分布
   ├── 地区分布
   └── 终端分布(机型/系统版本)

5. 来源分析
   ├── 搜索
   ├── 扫描二维码
   ├── 会话分享
   ├── 公众号
   ├── 附近的小程序
   └── 其他来源

8.2 小程序SEO优化

搜索优化配置(sitemap.json):
{
  "rules": [
    {
      "action": "allow",
      "page": "pages/index/index"
    },
    {
      "action": "allow", 
      "page": "pages/detail/detail",
      "params": ["id"],
      "matching": "inclusive"
    },
    {
      "action": "disallow",
      "page": "*"
    }
  ]
}

优化要点:
1. 小程序名称包含核心关键词
2. 小程序描述详细且包含关键词
3. 页面标题(navigationBarTitleText)要有关键词
4. 页面路径清晰有意义
5. 配置sitemap允许搜索引擎收录
6. 提交页面收录(搜索 → 搜索设置 → 页面收录)
7. 保持更新频率

8.3 推广方式

方式说明效果
搜索优化配置关键词、优化描述被动流量,长期有效
二维码线下物料/海报/名片线下场景
公众号关联公众号菜单/文章嵌入私域流量
社交分享用户分享给好友/群裂变传播
附近的小程序基于地理位置本地商家
小程序互跳与其他小程序互相跳转换量合作
微信广告朋友圈广告/公众号广告付费推广
视频号视频号挂载小程序内容引流
搜一搜品牌搜索/服务搜索搜索流量
直播带货小程序内直播电商

九、费用清单

项目费用必须?
小程序注册免费
微信认证300元/年企业必须,个人可选
域名50-100元/年是(需ICP备案)
服务器50-500元/月是(云开发可免费)
SSL证书0-1000元/年是(Let's Encrypt免费)
微信支付商户号0元开通如需支付
支付手续费0.6%每笔交易
短信验证码0.04-0.06元/条如需手机登录
<strong>总计(最低)</strong><strong>约500-1500元/年</strong>基础配置

十、完整开发时间预估

阶段工作内容时间
注册准备账号注册、域名、服务器1-2天
UI设计页面设计、切图3-7天
前端开发页面开发、交互逻辑2-4周
后端开发API接口、数据库2-4周
联调测试前后端联调、Bug修复1-2周
体验测试内部测试、优化3-5天
提交审核审核与修改1-2周
<strong>总计</strong><strong>6-10周</strong>
如果是简单工具类小程序(无后端),可缩短到 2-3周

返回首页