Creght 的后端能力:用 Func 写服务端逻辑、做登录、收支付
站点自己的服务端逻辑、数据、登录、验证码和支付都在平台内部完成:Func 有公网可访问的 HTTPS 地址,能接收支付异步通知;JSON 表用 ctx.db 存订单和报名;登录默认用 useAuth,自有规则收口到 ctx.auth.login。含每块能力的文档入口与边界说明。
「AI 生成的网站」听起来像一堆静态页面:能看、能改样式、能发出去,但一碰到「用户要登录」「订单要存下来」「支付成功后要改状态」就得换一套工具重做。
这个印象在 Creght 上不成立。站点自己的服务端逻辑、数据、登录、支付和邮件都在平台内部,写在同一个项目里,跟着同一次发布上线。这篇把这几块能力一次讲清楚,每节都给出对应文档。
Func:站点自己的服务端
Func 是运行在服务端的函数。你在项目里写一个函数并给它一个函数键,页面就能调用它。密钥、第三方 API、数据库读写这些不能放进浏览器的事情,都在这里做。
ctx 提供的能力包括数据、鉴权、用户目录、缓存、请求与响应、Cookie、资源、邮件、流式事件和诊断。
有一件事经常被误解,值得单独说:已发布的 Func 有公网可访问的 HTTPS 地址。所以它不只是「网站主动去请求别人」,也可以作为第三方回调你的入口——支付异步通知、消息推送、Webhook 都能送达。
数据:JSON 表
持久化用 JSON 表。先在 /platform/table/<key>.json 声明一张表,再在 Func 里用 ctx.db 读写和查询。文件名就是表键,表 ID 和 project_id 永远不出现在代码和浏览器 payload 里。
它刻意不是通用数据库:没有 join、没有聚合、没有事务、没有模糊匹配。能力范围正好覆盖预约、订单、报名、配额、日志这类站点自己的业务数据。需要复杂关系型查询的系统,本来也不该塞进建站平台。
另外要分清两件事:展示型内容(文章、产品、案例)用 CMS 管理,业务数据才用 JSON 表。
登录:先用平台的,不够再自己写
平台内置账号体系。页面用 useAuth() 拿当前用户,注册、登录、找回与修改密码都有现成实现;「注册必须验证邮箱」可以按项目策略强制开启,开启后验证是一次独立的服务端动作,页面代码里不需要传验证码参数。
只有两种情况需要在 Func 里自己写登录:SDK 表达不了的免密码验证码登录,以及登录时要跑封禁、实名、多租户这类自有规则。这时用 ctx.auth.login(ref) 给已有用户签发会话。
return ctx.auth.login({ userId: user.id })
有一条规则不能写错:ctx.auth.login 的参数必须来自服务端刚刚验证过的事实。直接把浏览器传来的 email 塞进去,等于「浏览器说自己是谁就是谁」,那不是登录。
会话 cookie 由平台写在响应上,Func 代码看不到会话 token,也造不出一个。在 Func 里判断身份用 ctx.auth.currentUser(),未登录直接拒绝用 ctx.auth.requireUser()。
邮件与验证码:平台已经做完了容易错的部分
在编辑器后端 → 集成接一次 Resend,就能在 Func 里用 ctx.email 发事务邮件和验证码。
ctx.email.sendCode({ to: input.email, scene: "login" })
随机码生成、过期、一次性作废、常数时间比对、错误次数上限和限频都由平台保证——这六件事里错任何一件都是真实的安全问题,而且错了通常不报错,只是静默地不安全。
支付:收款闭环在站内完成
文档给出支付宝电脑网站支付的完整实现:RSA2 签名、可选 AES 内容加密、服务端可信订单、异步通知验签、金额校验和幂等处理。
两条容易踩的边界写在文档里,这里先提醒:金额必须由服务端商品表决定,浏览器只传 productId;支付成功状态只能来自验签通过的异步通知,不能相信前端回跳参数。
而异步通知地址(notify_url)填的就是已发布的 Func 地址,形如 https://your-domain.com/func/alipay.notify。这也是前面说「Func 能作为公网回调入口」的实际用途。
边界:什么不适合放进来
说清楚能做什么,也要说清楚不能做什么:
JSON 表不做 join、聚合、事务和模糊匹配。需要这些的系统应该用真正的数据库,Func 去调它。
目前文档覆盖的支付渠道是支付宝网站支付。其他渠道需要按同样的模式自己接。
用户目录
ctx.users.find/query的作用域是全项目,不是当前调用者——所以「谁能查谁」的门禁必须自己写,平台不会替你判断。
