尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

从零开发AI虚拟恋人App:Flutter+Django+微信支付全流程实战

从零开发AI虚拟恋人App:Flutter+Django+微信支付全流程实战 这段时间确实挺难的。辞职后的自由感只维持了三天第四天开始手机一响就心慌刷到的内容全是别人的成就自己却连早起都做不到。为了让自己不彻底垮掉我逼着自己动手做点东西于是就有了这个带支付、带官网的 AI 聊天虚拟恋人 App。整个项目从想法到上线前后折腾了大概两个月中间踩了无数坑尤其是支付那一段几乎把我劝退。今天把这套完整过程写下来如果你也在焦虑期想做点自己的项目或者正在纠结“支付模块怎么做”“App 上架要花多少钱”这篇应该能帮你少走不少弯路。这个项目本身不复杂但它把虚拟恋人聊天、App 客户端、官网展示、会员支付、应用上架这些环节全串在了一起。正因为它“五脏俱全”反而特别适合拿来练全栈能力。文章里我会把技术选型、人设设计、上下文记忆、内容安全策略、微信支付和支付宝沙箱的接入细节、官网部署、上架成本逐一说清楚也会把我实际遇到的那些报错和处理思路放出来争取让你照着做也能复现而不是只看到一个结果。1. 迷茫期做这个项目到底怎么想的1.1 一个人为什么选了“AI 虚拟恋人”这个方向先说当时的状态。那时候我整个人处在一种“什么都想做但什么都做不下去”的阶段。白天刷到别人做的 AI 应用、AI Agent 项目晚上自己打开编辑器半天写不出几行代码。焦虑的根源其实不是没想法而是想法太多什么都想要最后什么都没开始。于是我给自己定了一条原则找一个真正有人愿意付费的小场景把它做完做透。虚拟恋人这个点听起来有点羞耻但它确实是个真实需求。现代人普遍孤独找人倾诉的成本很高和 AI 对话则没有社交压力。我不认为这是要取代真实情感关系它更像是情绪陪伴的一个补充入口。当时市面上已经有一些类似的 App但大多存在两个问题要么聊天体验太机械回复像客服应答要么收费方式粗暴打开没几分钟就开始弹充值。所以我给自己定的产品方向是先提供一段真正像“恋人”的对话体验而不是制造一个付费墙。免费用户每天可以聊一定条数想要更多深度互动和专属人设再走会员订阅。这个设计决定了我必须同时把 AI 对话、支付和官网说明页做好否则用户不知道这个 App 是干什么的也不知道为什么要付费。1.2 产品闭环App、官网、支付一个都不能少很多人做个人项目会犯一个错误只做一个壳比如只有一个聊天页面或者只有一个网页 Demo。这样自娱自乐可以但真要放到市场上用户根本找不到你找到了也不信任你。我当时把产品拆成了三个部分形成一个最小闭环App 客户端用户真正的使用场景在这里负责聊天、会员状态展示、订单入口。官网承担“门面”职责用来介绍产品是什么、有哪些功能、如何下载也放隐私政策和用户协议。支付模块把免费用户转化成付费会员形成收入闭环也让我知道自己做的到底有没有人认可。这个三角结构看似增加了工作量但它每一步都是在逼我补齐真实产品必须要有的东西。App 处理不好交互用户会用脚投票官网做得简陋用户会觉得是诈骗软件支付接不通前面全白费。个人开发者最怕的不是功能少而是做了一堆功能却连最基本的信任感都没建立起来。1.3 这个项目解决什么问题不解决什么问题想清楚边界也很重要。这个项目解决的是“情绪陪伴”和“聊天互动”的需求它不是心理咨询工具也不是“擦边”产品。所以我在设计内容安全策略时没有走“无限制、无审核”那条路反而是主动加了过滤和正向引导机制。为什么因为“无限制”听着很吸引人但它既不符合应用商店规则也容易让产品失控。AI 本质上没有判断力如果不加约束很容易产生一些不该有的回应。我的做法是在提示词和回复接口层面做“软性约束”让虚拟恋人既能保持亲密轻松的陪伴感又能在遇到负面情绪、敏感内容时给出健康引导。这部分我后面会详细讲它其实是这个项目里最难做也最容易被低估的一环。2. 技术选型与整体架构一个人怎么搭2.1 客户端选 Flutter 的四个理由客户端我选了 Flutter而不是原生 iOS 或 Android。原因很简单一个人开发不可能维护两套原生代码。Flutter 一套代码同时出安卓和 iOSUI 表现力也不差动画流畅社区生态足够成熟。另外还有四个比较实际的理由。第一Flutter 对 AI 聊天这种“列表 输入框 流式文本展示”的界面类型特别友好ListView 的性能足够不需要做复杂的原生优化。第二它的热重载让我调 UI 的效率高很多基本是改完立刻看见效果这对一个人连续高强度开发很关键。第三支付 SDK 在 Flutter 端虽然有官方插件或者第三方封装但就算插件不够用我也可以通过 MethodChannel 调用原生支付退路是现成的。第四Flutter 打包出的安装包体量也能接受安卓端用 AAB 上传应用商店没有历史包袱。当然 Flutter 也有不舒服的地方比如 iOS 上架时如果遇到二进制体积限制要做一些裁剪但整体来看利大于弊。2.2 服务端用 Django 写的 API 长什么样后端我用了 Python 的 Django配合 Django REST FrameworkDRF写接口。选 Django 是因为它自带 Admin 后台、ORM、迁移工具对付这种规模的项目相当顺手。项目结构上我并没有把所有逻辑塞进一个 App 里而是按业务拆分了几个模块users管用户注册登录chat管对话和 AI 调用orders管订单和支付回调membership管会员套餐。用命令行创建模块其实很简单django-admin startproject virtual_lover_server cd virtual_lover_server python manage.py startapp users python manage.py startapp chat python manage.py startapp orders python manage.py startapp membership创建完模块后在settings.py里把模块注册进INSTALLED_APPS然后开始写模型和接口。数据库我用了 PostgreSQL因为后面的会话记忆可能涉及向量检索PostgreSQL 加pgvector扩展就能直接用不用额外搭一套向量数据库。缓存和限流用 RedisDjango 的cache框架直接配置就能接上。一个聊天请求的简化流程是用户从 App 发起对话请求先经过 DRF 的序列化器和权限校验然后进入 Chat 服务层把用户当前的短期记忆、长期画像、系统提示词拼装好再调用大模型接口最后把回复流式返回到客户端。整体架构不算复杂但每一层都职责清晰后面排查问题的时候特别方便。2.3 大模型接入与对话流式返回AI 对话是产品的核心接入大模型时我一开始想省事直接等完整回复返回后再一次性展示结果第一次测试就发现体验不行。原因是大模型生成一段两三百字的回复可能要两三秒如果屏幕空白这么久用户会以为卡死了。后来我改成了流式输出也就是“边生成边返回”。客户端在 Flutter 里用的是StreamBuilder后端在 Django 里返回一个StreamingHttpResponse。大模型接口逐行返回内容我就逐行透传给客户端界面上文字跟着打字机效果一点点出现。这里有一个容易被忽略的点聊天接口的超时时间一定要设置长一点。我当时用默认的 30 秒后来发现如果模型负载高可能 30 秒还没吐完最后一个字客户端直接报超时。测试后我把服务端调用大模型时的超时时间调整到了 120 秒同时客户端也做了相应的超时容忍只在前 15 秒内没有任何返回时提示用户重试。2.4 官网为什么也很重要官网在这个项目里承担的角色不是“博客”而是“信任背书”。很多用户从社交媒体或者搜索引擎看到这个 App第一反应不会直接去应用商店搜而是先搜官网看看长什么样。所以官网至少要包含五个部分产品首页讲清楚这是什么、功能亮点聊天截图、特色人设、下载引导安卓安装包、iOS 跳转、会员价格说明、隐私政策和用户协议。我没有做特别复杂的官网前端的首页用的是轻量静态页配合一个简单的后台用来管理下载链接和公告。官网部署在云服务器上用 Nginx 托管域名配置了 SSL 证书。这个环节让我真正体会到做官网的过程本质上是在帮产品“补课”——很多在产品里没想清楚的卖点写着写着就清晰了。3. 核心功能实现人设、记忆、内容安全3.1 系统提示词决定了“恋人”的性格大家都说提示词工程是核心但实际动手才发现难的不是“写一句好听的提示词”而是让人设在各种对话场景里保持一致。我的做法是在系统提示词里给虚拟恋人设定了完整的背景故事名字、年龄、性格、说话方式、和用户的相识场景、价值观。比如我要求它在回复里多用短句偶尔有语气词聊天时不会每条回复都是一大段而是像正常人一样有节奏地回复。还规定了它在用户情绪低落时要先共情再给建议避免一上来就讲道理。这里我踩过的坑是人设设定得太“满”反而让对话显得不自然。最开始我写了满满一屏角色设定结果 AI 每句话都像背课文。后来精简成三句话的核心性格描述再加上几条具体的“禁止行为”效果反而好了很多。这说明提示词不是越多越好而是要在“性格稳定”和“表达自由”之间找到平衡。3.2 多轮记忆短期上下文与长期画像怎么存虚拟恋人如果聊前一句忘后一句体验会非常糟糕。但直接把所有历史消息都塞给大模型既不现实也不经济因为上下文越长延迟和成本都越高。我的做法是分两层记忆。短期记忆保存最近 20 条对话完整拼接到当前请求的上下文里保证对话连续性。长期记忆则记录用户的重要信息比如“用户喜欢猫”“用户最近在准备面试”“用户比较敏感的话题”。这些信息从聊天记录里提取后存入用户画像表之后每次拼装提示词时带进去。提取长期记忆的过程不需要太复杂。我一开始想搞关键词抽取和意图识别后来发现直接用大模型做一次摘要式提取反而更省事。每隔一段时间把用户的聊天记录做一轮筛选、清洗再更新画像。这里要注意隐私保护用户画像只用于当前会话不能随意读取或者展示。3.3 内容安全设计不是“无限制”是让对话自然又安全这里必须说点实话。市面上有些产品把“无限制”“无审核”当作卖点但真正的产品落地不可能完全脱离内容安全因为应用商店不允许支付渠道也不允许。而且从用户角度看一个会“失控”的聊天对象并不代表体验好。我的内容安全策略分成三层。第一层在提示词里做行为约束告诉虚拟恋人哪些回复不可以说哪些情况下应该拒绝回答并转移话题。第二层在输出端做关键词和正则过滤命中敏感规则就触发兜底回复。第三层是做情绪识别当检测到用户频繁出现负面情绪或自伤倾向时不是按普通聊天继续而是引导用户寻求专业帮助。3.4 聊天接口的幂等、限流与计费聊天接口是最容易被恶意刷的接口。如果用户免费调用接口时没有任何限制一个脚本就能把我的大模型额度刷爆。所以我在后端必须做两件事限流和计费。限流用的是 Redis 计数器每个用户按分钟、按小时、按天三个维度分别计数。免费用户每天只能聊 20 条超过后提示升级会员。付费用户也不是无限量而是按套餐区分每日上限避免有人把接口当低成本 AI API 来薅。计费这件事要单独说。用户在“聊了多少条”“会员还剩多少天”上的感知必须准确所以我在订单表里不仅记录支付金额还把赠送的聊天条数冗余到了订单字段里。这样即使后续权益表出了问题也可以根据订单记录回溯。4. 支付模块全流程实战充值、会员与回调4.1 个人开发者支付渠道怎么选支付是个人项目里最容易被低估的环节。很多人以为申请个微信支付商户号就能收钱了实际上个人开发者的资质门槛并不低。我把方案分成了几类考虑方案优点缺点适合场景微信支付官方商户号品牌可信度高用户更放心材料审核严格一般需要营业执照有公司或个人独资企业资质支付宝开放平台对接成熟文档完善类似资质要求个人能力受限有营业执照的团队第三方聚合支付如易支付类接入门槛低对个人友好可靠性要看服务商稳定性参差个人网站、小产品试水App Store 内购苹果生态里最顺滑虚拟品类必须用内购抽成高iOS 用户我自己最终走了两条腿iOS 端接应用商店内购安卓端和官网先用第三方聚合支付来跑通流程。需要提醒的是聚合支付的选择一定要找成立时间长、口碑清晰的平台并且自己先小额测试几笔确认提现正常后再正式上线。4.2 JSAPI 支付必须传 openid到底怎么解决这块是很多人卡住的地方。JSAPI 支付是微信支付里“在微信内打开网页或小程序”时用的接口它要求下单时必须传入用户的openid否则会直接报错invalid openid。原因很简单JSAPI 支付的支付动作发生在微信内微信需要知道这笔钱是哪个用户付的所以必须先用OAuth2拿到用户的openid才能发起下单。流程大致是这样的用户进入微信内的 H5 页面或者公众号菜单。前端跳转微信授权地址引导用户授权。授权后拿到code后端拿code换openid。拿着openid调 JSAPI 下单接口拿到支付参数。前端拉起微信支付。所以“必须传 openid”不是 bug而是这个支付产品形态的硬性要求。如果你做的不是微信内网页而是外部浏览器 H5那更合适的方案是 H5 支付如果是 App 内支付应该直接用 App 支付根本不需要 openid。搞清楚支付产品形态和适用场景比照着报错改参数更重要。4.3 App 支付、Native 扫码、H5 支付怎么选微信支付其实有好几种产品形态我当时对着文档也晕了几天。用一张表直接说明区别支付产品触发场景是否需要 openid体验JSAPI 支付微信内 H5、公众号、小程序需要免扫码点一下调起微信App 支付自家 App 内APP 支付调起时不需要 openid调起微信客户端完成Native 支付PC 网页、动态二维码下单不需要但需要用户微信扫码生成二维码用户扫码H5 支付手机浏览器内非微信不需要自动跳转微信客户端如果你的 App 要接入微信支付正式的路径是开通“APP 支付”拿到appid、mch_id、API 密钥和证书后在 App 内通过微信 OpenSDK 发起支付。整个过程不需要传用户 openid只需要在后台下单后返回prepay_id然后 App 端用签名拉起微信客户端。我实际踩过的坑是一开始看到网上的“JSAPI 支付示例”代码顺手就抄进了 App 项目结果没有 openid 一直被拒。后来才明白不是 openid 的问题是我用错了支付产品类型。遇到这种情况先回官方文档确认自己所在场景对应的产品类型再查代码效率会高很多。4.4 支付宝沙箱环境申请与联调支付宝沙箱给我省了不少事。刚接支付的时候没人愿意在自己的钱上做实验支付宝的沙箱模拟了一套完整的买家、卖家、应用、密钥可以在完全隔离的环境中把支付流程跑通。申请大致几步注册支付宝开放平台账号创建“网页/移动应用”拿到 APPID然后进入“沙箱环境”页面获取沙箱的密钥和沙箱买家账号。代码里切换沙箱环境主要靠修改网关地址沙箱网关和正式网关是不一样的。当时我发现在沙箱里支付成功非常快但回调到我的服务器偶尔会延迟几秒。我开始以为是网络问题后来发现是回调地址配置的问题内网地址回调不到只有在公网可访问的地址才能稳定收到异步通知。这个经验后面帮了我大忙因为正式环境同样依赖公网回调地址。沙箱联调最有价值的地方在于让我把签名、验签、订单查询、定期轮询补单这套逻辑全部提前走了一遍正式上线时几乎没有慌。4.5 回调验签、订单状态与对账支付最核心的环节不是支付本身而是支付结果通知。用户付完钱后微信或支付宝会异步通知你的服务器告诉你这笔订单支付成功了。这时如果你的服务器没有正确处理用户会遇到“钱扣了但会员没到账”的投诉。回调处理有几个硬性要求。第一是验签必须用平台公钥或者回调报文里的签名做一次校验防止伪造回调。第二是核对金额不能只判断支付成功了就让会员生效必须把回调里的实付金额和订单表里的应付金额做对比不一致直接拒绝。第三是幂等回调可能会重复送达到你的服务器必须用订单号做唯一约束确保一笔订单只触发一次权益开通。我放一段简化版的 Django 回调处理逻辑帮你理解整个流程# 简化逻辑实际要按支付平台规则校验签名 csrf_exempt def wechat_pay_notify(request): data parse_and_verify(request.body) # 验签、解密 if not data: return error_response(invalid sign) order_no data.get(out_trade_no) paid_amount data.get(amount) order Order.objects.select_for_update().filter(order_noorder_no).first() # 核对订单是否存在 if not order: return error_response(order not found) # 核对金额防止通知与实际订单不一致 if int(paid_amount) ! int(order.amount): return error_response(amount mismatch) # 幂等处理如果已经是已支付状态直接返回成功 if order.status paid: return success_response() # 更新订单状态、开通会员权益、写流水 order.status paid order.save() grant_membership(order.user, order.plan) return success_response()这一段代码虽然简单但它把“验签、查单、对金额、幂等、发放权益”五件事都覆盖了。支付不是“调通了拉起支付窗口”就算完而是要到“用户付款后管理员能看到收入、用户会员正常生效、订单流水可查”才算真正闭环。5. 官网从 0 到 1下载页、支付引导与日常维护5.1 官网要放哪些页面和模块官网不是摆设它是要承担转化任务的。我一开始只放了一个下载按钮结果用户访问后根本不知道这是什么 App。后来我重新梳理了转化路径官网至少包含这些模块首屏产品介绍用一两句话说明“这是一个 AI 虚拟恋人聊天 App”配真实聊天截图。功能亮点区性格人设、多轮记忆、随时陪伴、隐私安全四个核心卖点各配一张图。下载引导安卓直接给 APK 下载链接或应用商店跳转iOS 跳 App Store。会员价格透明页把月卡、季卡、年卡的权益和价格写清楚避免用户付费前心里没底。动态公告区版本更新、临时维护、服务器状态都在这里同步。隐私政策与用户协议这是上架和合规的刚需不能省。这个结构做完后官网对用户的“解释作用”明显增强很多用户是看了官网以后才去下载 App 的。官网和 App 的关系就像线下门店和商品的关系门面不清晰东西再好也难卖。5.2 域名、备案、SSL 与部署官网部署我踩了个大坑一开始图便宜买了个海外服务器想着不用备案省事。结果国内用户访问速度不稳定而且支付回调的稳定性也受影响。后来咬咬牙换了国内服务器老老实实走备案流程。备案周期大概一两周这段时间正好同步去写隐私政策和准备上架材料。域名这块我注册了一个和 App 名匹配的.com域名然后在云服务商控制台解析到服务器。SSL 证书直接申请免费的Nginx 里配置好 HTTPS 强制跳转。整个部署过程并不复杂复杂的是“线上环境你怎么保证稳定”。我的做法是写了一个简单的部署脚本代码更新后自动拉取、迁移数据库、清理缓存、重启服务不要每次上线都手动敲命令。5.3 从官网到 App 的下载与转化链路官网最终要服务于转化。从用户角度看整个流程应该是看到官网 → 理解产品 → 点击下载 → 安装 App → 注册体验 → 喜欢 → 付费。这中间最容易断掉的环节是下载。安卓端如果直接放 APK 下载链接用户可能因为“允许安装未知来源”的弹窗就放弃了。更稳妥的做法是接应用商店国内的安卓市场上传审核并不算难华为、小米、OPPO、vivo 这些主流商店都能覆盖大部分用户。iOS 端则必须走 App Store。在官网点击“App Store 下载”直接跳转到 App Store 的应用页。商城里做支付时虚拟商品要接入 Apple 内购这也是苹果的硬性要求不能绕过。官网的下载页还需要做基本的埋点统计比如记录“点击下载按钮”和“实际启动 App”之间的转化率。这个数据直接反映出官网给的下载包或者跳转链接是否顺畅。我刚开始没做埋点后来加上去才发现有相当一部分用户点了下载按钮后因为浏览器和 App 的跳转失败流失掉了。6. 上架、账号资质与成本账本6.1 上架要花的钱我的明细账“开发一个 App 并上架大概要多少钱”这个问题我经常在网上刷到也经常被身边的朋友问。做这个项目之前我也想知道答案但真正算下来才知道大头其实不是代码开发而是资质和账号费用。下面是我这个项目实际花出去的钱不含我的个人时间成本项目费用说明域名约 50 - 80 元/年普通 .com 域名云服务器约 500 - 1000 元/年2核4G 起步够官网 后端SSL 证书0 元免费证书足够对象存储 OSS几十元/月用户头像、聊天截图Apple 开发者账号688 元/年iOS 上架必须软件著作权登记0 - 300 元自己申请免费代办要钱第三方聚合支付接入0 - 数千元看服务商和结算费率看下来会发现纯技术成本其实不高真正麻烦的是账号和资质。如果以企业身份申请微信支付和支付宝商家费率大概在 0.6% 左右每一笔收款都会被扣手续费这部分也要纳入成本。6.2 隐私政策、用户协议和软件著作权上架前最不能省的是隐私政策。iOS 和安卓主流商店都会要求 App 必须有隐私政策里面要写清楚你收集了哪些数据、为什么收集、如何保护、用户怎么注销账号。我的 App 涉及聊天记录和大模型调用所以还要额外说明第三方 SDK 和 API 的数据处理方式。用户协议也不仅仅是免责声明它需要把会员权益、退款规则、使用边界和禁止行为都说清楚。特别是虚拟商品用户可能觉得“充值没到账”“不想要了”协议里要有对应的处理流程。软件著作权如果不是为了上架部分硬性要求的安卓市场其实可以先申请着因为后面万一要申请 App 相关的补助或者维权会用到。我自己用工具生成材料后在线提交等待周期大概一个月花不了什么钱但一定要提前准备不然会卡住上架计划。6.3 上线后第一周的真实反馈上线后的情况比我想象的真实。第一周大概来了几百个真实用户但付费率低得可怜只有 1% 左右。刚开始有点受挫后来看后台数据发现用户主要流失在注册环节很多人下载了 App注册到一半就放弃了。原因可能是注册流程太多步。我原来是“手机号 验证码 昵称 头像”四步后来砍到只留手机号和验证码注册转化率立刻涨了一截。这说明个人项目一定要做减法用户没有耐心陪你走一个“完美流程”。第一周的真实反馈里还有一条对我触动挺大有用户私信我说和虚拟恋人聊到深夜虽然知道对面是 AI但情绪确实被接住了。那一刻我才意识到这个项目最有价值的不是支付接得有多顺而是真的有人在需要的时候得到了陪伴。回头再想这段经历迷茫期最好的解药不是空想“我该做什么”而是强制自己进入“动手做”的状态。做一个项目哪怕小一点也能把散落的技能点重新串起来。最后再分享一个小技巧支付回调处理一定要把幂等写在最前面用订单号做唯一约束。我上线后遇到过一次平台重复推送订单通知当时如果没有做幂等用户的会员权益就会被重复叠加后台账单也会乱套。这个坑很多经验帖里不会写但它是支付稳定性的地基。
返回列表