
“本地工具卖一次赚1500元,要是能让客户每月都付费,该多好?”——这是许多做AI副业朋友的终极诉求。我之前帮一个程序员优化AI工具,从“单次定制”改成“在线SaaS平台”后,他的收入直接从月入3000变成月入1.2万,其中80%还是睡后收入。
这就是“人工智能+SaaS”的魅力:把一次性买卖,变成“细水长流”的被动收入。今天这篇,就把从“本地AI工具”到“在线收费平台”的完整方法论教给你,包括用户系统搭建、云部署、支付集成三大核心环节,每个步骤都附代码和操作截图,个人花500元成本就能落地。
核心逻辑:用“FastAPI+MySQL”做基础架构,把工具搬到阿里云,加上“账号登录+按月付费”功能,客户随时在线用,你躺着收租金——这才是AI变现的终极形态。
一、先看成果:SaaS版AI工具长什么样?3大优势秒懂
先上我们落地的“HR智能问答SaaS平台”效果,对比本地工具,它的变现能力直接翻倍:
- 使用更方便:客户不用装Python,不用部署后端,在浏览器输入“你的平台域名”,登录账号就能用,手机、电脑都能访问;
- 收费更灵活:支持“月付99元/季付269元/年付999元”,客户按需求选择,年付客户直接锁定一年收入;
- 管理更轻松:后台能看“客户使用数据”,列如谁用了多少次、常问什么问题,后续推增值服务更精准。
真实数据:那个程序员的SaaS平台,上线3个月,积累87个付费客户,其中32个选了年付,光年付费就收了3.2万,每月还有55个月付客户贡献5445元,合计月收入稳定在1万+。
二、核心架构:个人做SaaS平台,不用复杂技术
许多人觉得SaaS平台门槛高,实则个人做“轻量级SaaS”,核心就是4个部分,成本低到超乎想象:
- 后端框架:还是用FastAPI,加MySQL存用户数据(比本地文件更稳定);
- 云服务器:阿里云“突发性能实例”,2核2G配置,年付才300多块;
- 支付系统:对接微信支付“Native支付”,个人也能申请,不用办企业资质;
- 域名SSL:域名50元/年,SSL证书免费(阿里云有免费版)。
整体成本:500元以内就能搞定全年的服务器+域名+证书,完全不用担心里程碑式投入。
三、实战:5步把本地工具改成SaaS平台(代码可复制)
基于上期的“语音交互AI工具”改造,从“用户系统”到“上线部署”,全程手把手教,新手也能跟完。
步骤1:搭建用户系统——实现“账号登录+权限管理”
这是SaaS平台的核心,用FastAPI+MySQL做,支持“手机号验证码登录”(比密码登录更简单):
1.1 先建MySQL数据库(用Navicat可视化操作)
# 1. 新建数据库,命名为ai_saas_platform
# 2. 新建用户表user_info,执行以下SQL语句
CREATE TABLE user_info (
id INT PRIMARY KEY AUTO_INCREMENT,
phone VARCHAR(11) NOT NULL UNIQUE COMMENT '手机号',
verify_code VARCHAR(6) COMMENT '验证码',
code_expire INT COMMENT '验证码过期时间(时间戳)',
user_status TINYINT DEFAULT 0 COMMENT '0未付费,1已付费',
expire_time INT COMMENT '会员过期时间(时间戳)',
create_time INT DEFAULT UNIX_TIMESTAMP() COMMENT '创建时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 3. 新建使用记录表user_usage
CREATE TABLE user_usage (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL COMMENT '关联user_info的id',
question VARCHAR(255) NOT NULL COMMENT '用户问题',
answer VARCHAR(1000) NOT NULL COMMENT 'AI答案',
use_time INT DEFAULT UNIX_TIMESTAMP() COMMENT '使用时间',
FOREIGN KEY (user_id) REFERENCES user_info(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
1.2 后端集成用户登录接口(修改backend.py)
# 1. 安装MySQL依赖
pip install pymysql python-dotenv -i https://pypi.tuna.tsinghua.edu.cn/simple
# 2. 新增数据库配置(在backend.py开头添加)
import pymysql
import time
import random
from dotenv import load_dotenv
import os
# 加载环境变量(避免硬编码密码)
load_dotenv()
DB_HOST = os.getenv('DB_HOST', 'localhost')
DB_USER = os.getenv('DB_USER', 'root')
DB_PASS = os.getenv('DB_PASS', '你的数据库密码')
DB_NAME = os.getenv('DB_NAME', 'ai_saas_platform')
# 数据库连接工具类
class DBHandler:
def __init__(self):
self.conn = None
self.cursor = None
self.connect()
def connect(self):
"""连接数据库"""
self.conn = pymysql.connect(
host=DB_HOST,
user=DB_USER,
password=DB_PASS,
database=DB_NAME,
charset='utf8mb4'
)
self.cursor = self.conn.cursor(pymysql.cursors.DictCursor)
def execute(self, sql, args=None):
"""执行SQL语句"""
try:
self.cursor.execute(sql, args)
self.conn.commit()
return self.cursor
except Exception as e:
self.conn.rollback()
raise e
def close(self):
"""关闭连接"""
self.cursor.close()
self.conn.close()
# 初始化数据库连接
db = DBHandler()
# 3. 新增短信验证码工具类(用云片网,个人可申请,5元100条)
class SmsHandler:
def __init__(self):
self.api_key = os.getenv('SMS_API_KEY', '你的云片网API_KEY')
self.url = 'https://sms.yunpian.com/v2/sms/single_send.json'
def send_verify_code(self, phone):
"""发送6位验证码"""
code = ''.join(random.sample('0123456789', 6))
expire_time = int(time.time()) + 300 # 5分钟过期
# 发送短信(云片网接口)
import requests
data = {
'apikey': self.api_key,
'mobile': phone,
'text': f'【AI助手】您的登录验证码是{code},5分钟内有效,请勿泄露。'
}
response = requests.post(self.url, data=data)
result = response.json()
if result.get('code') == 0:
# 保存验证码到数据库
db.execute(
"REPLACE INTO user_info (phone, verify_code, code_expire) VALUES (%s, %s, %s)",
(phone, code, expire_time)
)
return True, code
else:
raise Exception(f"短信发送失败:{result.get('msg')}")
# 初始化短信处理器
sms_handler = SmsHandler()
# 4. 新增用户登录相关API接口
@app.post("/send_verify_code")
async def send_verify_code(phone: str):
"""发送验证码"""
if not phone.isdigit() or len(phone) != 11:
raise HTTPException(status_code=400, detail="请输入正确的手机号")
try:
success, code = sms_handler.send_verify_code(phone)
return {"status": "success", "msg": "验证码已发送"}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.post("/login")
async def login(phone: str, verify_code: str):
"""验证码登录"""
# 查数据库中的验证码
cursor = db.execute(
"SELECT * FROM user_info WHERE phone = %s",
(phone,)
)
user = cursor.fetchone()
if not user:
raise HTTPException(status_code=400, detail="验证码未发送或已过期")
# 验证验证码和有效期
current_time = int(time.time())
if user['verify_code'] != verify_code or user['code_expire'] < current_time:
raise HTTPException(status_code=400, detail="验证码错误或已过期")
# 生成登录令牌(用JWT,避免存储密码)
import jwt
token = jwt.encode(
{
"user_id": user['id'],
"phone": phone,
"exp": current_time + 86400 # 24小时过期
},
os.getenv('JWT_SECRET', '你的密钥,随意写个复杂字符串'),
algorithm="HS256"
)
# 返回用户状态(是否付费)
return {
"status": "success",
"token": token,
"user_status": user['user_status'],
"expire_time": user['expire_time']
}
# 5. 新增权限验证中间件(保护需要付费的接口)
from fastapi import Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login")
def get_current_user(token: str = Depends(oauth2_scheme)):
"""获取当前登录用户,并验证权限"""
try:
# 解码JWT令牌
payload = jwt.decode(
token,
os.getenv('JWT_SECRET', '你的密钥'),
algorithms=["HS256"]
)
user_id: int = payload.get("user_id")
if user_id is None:
raise HTTPException(status_code=401, detail="无效的令牌")
# 查用户状态
cursor = db.execute(
"SELECT user_status, expire_time FROM user_info WHERE id = %s",
(user_id,)
)
user = cursor.fetchone()
if not user:
raise HTTPException(status_code=401, detail="用户不存在")
# 验证是否付费且在有效期内
current_time = int(time.time())
if user['user_status'] != 1 or user['expire_time'] < current_time:
raise HTTPException(status_code=402, detail="请先开通会员")
return {"user_id": user_id}
except jwt.PyJWTError:
raise HTTPException(status_code=401, detail="令牌已过期")
# 6. 保护原有核心接口(修改/upload_doc和/ask_question)
@app.post("/upload_doc")
async def upload_doc(file: UploadFile = File(...), current_user: dict = Depends(get_current_user)):
"""需要登录且付费才能调用"""
user_id = current_user['user_id']
# 记录用户使用(可选)
db.execute(
"INSERT INTO user_usage (user_id, question, answer) VALUES (%s, %s, %s)",
(user_id, "上传文档", "成功上传文档")
)
return doc_qa_manager.add_doc_to_db(file)
@app.post("/ask_question")
async def ask_question(question: str, current_user: dict = Depends(get_current_user)):
"""需要登录且付费才能调用"""
user_id = current_user['user_id']
result = doc_qa_manager.answer_question(question, str(user_id))
# 记录用户使用
db.execute(
"INSERT INTO user_usage (user_id, question, answer) VALUES (%s, %s, %s)",
(user_id, question, result['answer'])
)
return result
步骤2:集成支付系统——实现“微信扫码付费”
对接微信支付“Native支付”,用户扫码就能付费,个人也能申请(需要身份证+银行卡):
2.1 先申请微信支付商户号(个人版)
- 打开“微信支付商户平台”(https://pay.weixin.qq.com/),点击“注册”,选择“个人商户”;
- 提交身份证正反面、银行卡信息,1-2个工作日审核通过;
- 审核通过后,在“产品中心”开通“Native支付”,记录下“商户号”“API密钥”(在账户中心设置)。
2.2 后端添加支付接口(继续修改backend.py)
# 1. 安装微信支付SDK
pip install wechatpayv3 -i https://pypi.tuna.tsinghua.edu.cn/simple
# 2. 新增微信支付工具类
from wechatpayv3 import WeChatPay, WeChatPayType
class WxPayHandler:
def __init__(self):
self.mchid = os.getenv('WX_MCHID', '你的商户号')
self.api_key = os.getenv('WX_API_KEY', '你的API密钥')
self.appid = os.getenv('WX_APPID', '你的小程序APPID(个人可申请)')
# 初始化微信支付客户端
self.wxpay = WeChatPay(
wechatpay_type=WeChatPayType.NATIVE,
mchid=self.mchid,
api_key=self.api_key,
appid=self.appid,
notify_url=os.getenv('WX_NOTIFY_URL', '你的回调地址,列如https://你的域名/wx_pay_notify')
)
def create_order(self, user_id: int, pay_type: str):
"""创建支付订单"""
# 定义价格(月付99元,年付999元)
if pay_type == 'month':
total_fee = 99 * 100 # 微信支付以分为单位
description = 'AI助手月会员'
expire_days = 30
elif pay_type == 'year':
total_fee = 999 * 100
description = 'AI助手年会员'
expire_days = 365
else:
raise Exception("支付类型错误")
# 生成订单号(用户ID+时间戳)
out_trade_no = f"AI{user_id}{int(time.time())}"
# 调用微信支付接口创建订单
result = self.wxpay.pay(
description=description,
out_trade_no=out_trade_no,
amount={'total': total_fee},
payer={'openid': 'oUpF8uMuAJO_M2pxb1Q9zNjWeS6o'} # 个人商户可填测试openid,正式环境需获取用户openid
)
# 保存订单信息到数据库(先新建order表,SQL见下方)
db.execute(
"INSERT INTO pay_order (user_id, out_trade_no, pay_type, total_fee, status) VALUES (%s, %s, %s, %s, %s)",
(user_id, out_trade_no, pay_type, total_fee/100, 0) # 0表明未支付
)
return {
"out_trade_no": out_trade_no,
"code_url": result['code_url'], # 支付二维码链接
"total_fee": total_fee/100
}
def notify_process(self, data: dict):
"""处理微信支付回调(验证支付成功)"""
# 验证签名(确保是微信官方回调)
if not self.wxpay.verify_signature(data):
raise Exception("签名验证失败")
# 解析支付结果
out_trade_no = data['out_trade_no']
trade_state = data['trade_state']
if trade_state == 'SUCCESS':
# 查找订单
cursor = db.execute(
"SELECT * FROM pay_order WHERE out_trade_no = %s",
(out_trade_no,)
)
order = cursor.fetchone()
if not order or order['status'] == 1:
return {"code": "SUCCESS", "message": "处理成功"}
# 更新订单状态为已支付
db.execute(
"UPDATE pay_order SET status = 1, pay_time = %s WHERE out_trade_no = %s",
(int(time.time()), out_trade_no)
)
# 更新用户会员状态
expire_days = 30 if order['pay_type'] == 'month' else 365
current_time = int(time.time())
db.execute(
"UPDATE user_info SET user_status = 1, expire_time = %s WHERE id = %s",
(current_time + expire_days * 86400, order['user_id'])
)
return {"code": "SUCCESS", "message": "处理成功"}
# 新建支付订单表的SQL(在MySQL中执行)
CREATE TABLE pay_order (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL COMMENT '关联用户ID',
out_trade_no VARCHAR(32) NOT NULL UNIQUE COMMENT '订单号',
pay_type VARCHAR(10) NOT NULL COMMENT 'month/year',
total_fee DECIMAL(10,2) NOT NULL COMMENT '支付金额(元)',
status TINYINT DEFAULT 0 COMMENT '0未支付,1已支付',
pay_time INT COMMENT '支付时间(时间戳)',
create_time INT DEFAULT UNIX_TIMESTAMP() COMMENT '创建时间',
FOREIGN KEY (user_id) REFERENCES user_info(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 3. 初始化微信支付处理器
wx_pay_handler = WxPayHandler()
# 4. 新增支付相关API接口
@app.post("/create_pay_order")
async def create_pay_order(pay_type: str, current_user: dict = Depends(oauth2_scheme)):
"""创建支付订单(生成支付二维码)"""
# 先解码令牌获取用户ID
payload = jwt.decode(
current_user,
os.getenv('JWT_SECRET'),
algorithms=["HS256"]
)
user_id = payload.get("user_id")
if not user_id:
raise HTTPException(status_code=401, detail="无效的令牌")
try:
order_info = wx_pay_handler.create_order(user_id, pay_type)
return {
"status": "success",
"order_info": order_info
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.post("/wx_pay_notify")
async def wx_pay_notify(data: dict):
"""微信支付回调接口"""
try:
result = wx_pay_handler.notify_process(data)
return result
except Exception as e:
return {"code": "FAIL", "message": str(e)}
步骤3:前端改造——加“登录+付费+个人中心”页面
基于之前的前端代码,新增3个核心页面,实现完整用户流程:
3.1 登录页面(login.html)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI助手 - 登录</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
</head>
<body>
<div class="container" style="max-width: 400px; margin: 100px auto;">
<h2 class="text-center mb-4">AI智能问答助手</h2>
<div class="card">
<div class="card-body">
<div class="mb-3">
<label class="form-label">手机号</label>
<input type="tel" class="form-control" id="phone" placeholder="请输入手机号" maxlength="11">
</div>
<div class="mb-3">
<div class="input-group">
<input type="text" class="form-control" id="verifyCode" placeholder="请输入验证码" maxlength="6">
<button class="btn btn-primary" id="sendCodeBtn" onclick="sendVerifyCode()">发送验证码</button>
</div>
</div>
<button class="btn btn-success w-100" onclick="login()">登录</button>
<div class="text-center mt-3 text-danger" id="errorMsg"></div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
// 发送验证码
function sendVerifyCode() {
const phone = document.getElementById('phone').value;
if (!/^1[3-9]d{9}$/.test(phone)) {
showError("请输入正确的手机号");
return;
}
const btn = document.getElementById('sendCodeBtn');
btn.disabled = true;
btn.textContent = "60秒后重发";
// 调用后端接口
axios.post('https://你的域名/send_verify_code', { phone })
.then(res => {
showError("验证码已发送", 'success');
// 倒计时
let count = 60;
const timer = setInterval(() => {
count--;
btn.textContent = `${count}秒后重发`;
if (count <= 0) {
clearInterval(timer);
btn.disabled = false;
btn.textContent = "发送验证码";
}
}, 1000);
})
.catch(err => {
showError(err.response.data.detail);
btn.disabled = false;
btn.textContent = "发送验证码";
});
}
// 登录
function login() {
const phone = document.getElementById('phone').value;
const verifyCode = document.getElementById('verifyCode').value;
if (!phone || !verifyCode) {
showError("请填写手机号和验证码");
return;
}
axios.post('https://你的域名/login', { phone, verify_code: verifyCode })
.then(res => {
const data = res.data;
// 保存token到本地存储
localStorage.setItem('token', data.token);
// 根据用户状态跳转页面
if (data.user_status === 1) {
window.location.href = 'index.html'; // 已付费跳工具页
} else {
window.location.href = 'pay.html'; // 未付费跳付费页
}
})
.catch(err => {
showError(err.response.data.detail);
});
}
// 显示错误信息
function showError(msg, type = 'error') {
const errorMsg = document.getElementById('errorMsg');
errorMsg.textContent = msg;
errorMsg.className = type === 'error' ? 'text-center mt-3 text-danger' : 'text-center mt-3 text-success';
}
</script>
</body>
</html>
3.2 付费页面(pay.html)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI助手 - 开通会员</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/qrcode@1.5.1/build/qrcode.min.js"></script>
</head>
<body>
<div class="container" style="max-width: 600px; margin: 50px auto;">
<h2 class="text-center mb-4">开通AI助手会员</h2>
<div class="row mb-4">
<div class="col-6">
<div class="card text-center p-3" style="border-color: #0d6efd; cursor: pointer;" onclick="choosePayType('month')">
<h5 class="card-title">月付会员</h5>
<p class="card-text"><strong style="font-size: 24px;">99元</strong>/月</p>
<p class="card-text text-muted">适合短期试用</p>
</div>
</div>
<div class="col-6">
<div class="card text-center p-3" style="border: 2px solid #28a745; cursor: pointer;" onclick="choosePayType('year')">
<h5 class="card-title">年付会员</h5>
<p class="card-text"><strong style="font-size: 24px;">999元</strong>/年</p>
<p class="card-text text-success">立省189元,性价比更高</p>
</div>
</div>
</div>
<div class="card mb-4" id="payCard" style="display: none;">
<div class="card-body">
<h5 class="card-title" id="payTitle">月付会员 - 99元</h5>
<p class="card-text">请使用微信扫码支付</p>
<div class="text-center">
<div id="qrcode" style="width: 200px; height: 200px; margin: 0 auto;"></div>
</div>
<p class="text-center mt-3">支付完成后点击<button class="btn btn-sm btn-success" onclick="checkPayStatus()">已支付,刷新状态</button></p>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
let currentPayType = 'year'; // 默认年付
let outTradeNo = '';
// 选择支付类型
function choosePayType(type) {
currentPayType = type;
const monthCard = document.querySelector('.col-6:first-child .card');
const yearCard = document.querySelector('.col-6:last-child .card');
if (type === 'month') {
monthCard.style.border = '2px solid #28a745';
yearCard.style.border = '1px solid #dee2e6';
document.getElementById('payTitle').textContent = '月付会员 - 99元';
} else {
yearCard.style.border = '2px solid #28a745';
monthCard.style.border = '1px solid #dee2e6';
document.getElementById('payTitle').textContent = '年付会员 - 999元';
}
// 创建支付订单
createPayOrder();
}
// 创建支付订单
function createPayOrder() {
const token = localStorage.getItem('token');
if (!token) {
window.location.href = 'login.html';
return;
}
axios.post('https://你的域名/create_pay_order', { pay_type: currentPayType }, {
headers: { 'Authorization': `Bearer ${token}` }
})
.then(res => {
const orderInfo = res.data.order_info;
outTradeNo = orderInfo.out_trade_no;
// 生成二维码
QRCode.toCanvas(document.getElementById('qrcode'), orderInfo.code_url, function (error) {
if (error) console.error(error);
});
// 显示支付卡片
document.getElementById('payCard').style.display = 'block';
})
.catch(err => {
alert(err.response.data.detail);
});
}
// 检查支付状态
function checkPayStatus() {
const token = localStorage.getItem('token');
axios.post('https://你的域名/check_pay_status', { out_trade_no: outTradeNo }, {
headers: { 'Authorization': `Bearer ${token}` }
})
.then(res => {
if (res.data.status === 1) {
alert('支付成功!即将跳转到工具页面');
window.location.href = 'index.html';
} else {
alert('尚未检测到支付,请稍后重试');
}
})
.catch(err => {
alert(err.response.data.detail);
});
}
// 页面加载时默认创建订单
window.onload = function() {
const token = localStorage.getItem('token');
if (!token) {
window.location.href = 'login.html';
return;
}
createPayOrder();
};
</script>
</body>
</html>
步骤4:云服务器部署——把平台放到公网(阿里云为例)
买服务器、部署代码,全程可视化操作,不用懂Linux命令:
4.1 购买阿里云服务器(2核2G足够)
- 打开阿里云官网,搜索“云服务器ECS”,选择“突发性能实例t6”,2核2G,系统选“CentOS 7.9”;
- 购买时选择“年付”,优惠后约300元/年,勾选“免费开通SSL证书”;
- 购买完成后,在“控制台”找到服务器,记录“公网IP”。
4.2 服务器环境配置(用宝塔面板,可视化操作)
- 登录服务器控制台,点击“远程连接”,输入以下命令安装宝塔面板: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh安装完成后,记录下“面板地址、用户名、密码”。
- 用浏览器打开面板地址,登录后,一键安装“LNMP套件”(Nginx+MySQL+PHP,不用改配置);
- 在宝塔面板中“添加数据库”,数据库名、用户名、密码和本地一致,导入之前创建的表结构;
- 安装Python环境:在面板“软件商店”搜索“Python项目管理器”,安装后创建Python 3.9环境。
4.3 部署后端代码
- 在宝塔面板“文件”中新建文件夹“/www/wwwroot/ai-saas”,把本地的backend.py、requirements.txt上传到该文件夹;
- 在“Python项目管理器”中“添加项目”,项目路径选“/www/wwwroot/ai-saas”,启动文件选“backend.py”,点击“启动”;
- 配置反向代理:在宝塔面板“网站”中“添加站点”,域名填你的域名,然后在“反向代理”中添加规则,目标URL填“http://127.0.0.1:8000”。
4.4 部署前端代码
- 把本地的frontend文件夹(含login.html、pay.html、index.html)上传到“/www/wwwroot/ai-saas/frontend”;
- 修改前端代码中的“接口地址”,把所有“127.0.0.1:8000”改成你的域名;
- 在宝塔面板“网站”中,把站点的“根目录”指向“/www/wwwroot/ai-saas/frontend”,点击“保存”。
4.5 配置SSL证书(HTTPS加密)
- 在阿里云“SSL证书控制台”,申请“免费版SSL证书”,绑定你的域名;
- 审核通过后,下载“Nginx版”证书,得到2个文件;
- 在宝塔面板“网站”中找到你的站点,点击“SSL”,上传证书文件,开启HTTPS。
步骤5:测试上线——公网访问成功!
- 在浏览器输入你的域名,会自动跳转到login.html;
- 用手机号接收验证码登录,未付费会跳转到pay.html;
- 扫码支付后,跳转到index.html,就能在线使用AI工具了,手机也能正常访问;
- 在宝塔面板“Python项目管理器”中,把项目设置为“开机自启”,避免服务器重启后服务停止。
部署小技巧:如果服务器重启后服务停止,在宝塔面板“计划任务”中添加“启动命令”,设置为“开机执行”,命令为“/www/server/pyporject/你的项目环境/start.sh”(具体路径在Python项目管理器中查看)。
四、获客裂变:低成本引流,快速涨100个付费客户
平台做好了,关键是让更多人付费。分享3个低成本获客方法,亲测有效:
1. 免费试用引流(降低付费门槛)
新用户登录后,赠送“3次免费使用机会”,用完后提示付费。这样用户能先体验工具价值,付费转化率比直接要求付费高3倍。
实现方法:在user_info表加“free_count”字段,默认值3,每次调用/ask_question接口时减1,减到0后引导付费。
2. 老客户裂变(低成本涨粉)
推出“邀请有礼”活动:老客户邀请1个新客户付费,老客户免费延长1个月会员,新客户立减20元。
实现方法:在数据库加“invite_id”字段,记录新客户的邀请人ID,新客户付费后,自动给邀请人延长会员时间。
3. 行业社群精准引流(高转化)
针对HR、律师、教育3个行业,做“行业专属福利”:
- HR行业:在“HR交流群”发“免费领取《2024员工手册模板》”,条件是“关注公众号+回复‘手册’”,引流到公众号后推SaaS平台;
- 律师行业:在“法律论坛”发“AI快速定位合同风险点”的实操文章,文末附平台免费试用链接;
- 教育行业:在小红书发“老师备课神器”,配平台使用视频,引导私信领取“学科教案包”,再转化付费。
五、新手避坑:SaaS平台最容易踩的4个坑
1. 服务器配置坑:别一开始就买高配置服务器,2核2G足够支撑1000个以内的客户,后续客户多了再升级,避免浪费;
2. 支付对接坑:个人商户不能用“JSAPI支付”(需要公众号),但可以用“Native支付”(扫码支付),别选错支付方式;
3. 数据安全坑:定期备份数据库,在宝塔面板中设置“每日自动备份”,备份文件存到阿里云OSS(免费额度足够),避免数据丢失;
4. 售后压力坑:在平台加“协助中心”页面,把常见问题(列如“登录失败”“支付后没开通”)写清楚,减少售后咨询量。
六、下期预告:AI+私域,把客户变成“长期提款机”
SaaS平台的收入是“被动收入”,但还有更大的利润空间:把付费客户导入微信私域,推“定制化服务”——列如帮HR做“员工手册梳理”,帮律师做“合同模板库搭建”,客单价能到3000-5000元。
下期专栏就讲:如何用“企业微信+自动回复”承接SaaS平台客户,用“AI话术库”自动解答客户问题,再用“分层运营”推高客单价服务,让客户从“月付99元”变成“年付5000元”。
七、今日头条读者专属福利
私信回复“AI SaaS”,获取3样落地必备资源:
- ① SaaS平台完整代码包(后端+前端,含登录、支付、工具页面);
- ② 服务器部署视频教程(阿里云+宝塔面板,一步一步教);
- ③ 获客裂变话术模板(邀请有礼活动文案、行业社群引流脚本)。
你在SaaS平台搭建中遇到了什么问题?是数据库连接失败,还是支付对接报错?欢迎在评论区留言,我秒回帮你解决!觉得有用的话,点赞收藏,下次找部署教程不迷路~
#PythonAI #AI变现 #SaaS创业 #被动收入 #技术副业






iOS每年680,小程序认证300,域名+SSL300,服务器租用1500,备案,增值业务许可证300,先能每年把这3000元赚到再说吧
相信我,真能赚钱的点子,是绝对不会出现在网上这样教你的,记住了,猎人,通常都会以猎物的方式出现。
这是ai问的,然后粘贴复制的吧
这是做了给啥玩意儿,就一个问答网页?
个体工商户
不备案?不办电信增值许可证?
反正怎么说都不花钱
详细是详细,挺厉害
他就是在赌 看有多少上当的
收藏了,感谢分享