跳至内容
WebViewGold 从 Vibe Coding 到 App Store
中文
获取 WebViewGold

Claude Code

Claude Code + Supabase 技术栈在 App Store 和 Google Play 上的配置

Claude Code 和 Supabase 是天生一对:代理编写数据库结构、策略和边缘函数,Supabase 负责运行它们。在 WebViewGold 应用中,有五件事需要特别注意,而浏览器从来不会对您提出这些要求:WebView 中的身份验证、魔法链接、账户删除、推送用户 ID 和商店内购买。下面是配置清单。

每个平台一次性 $109 起,或由我们的团队全程代劳,$698 起。

  • 审核通过保证 – 否则 14 天内退款
  • 无需编程
  • 一次性付费,免费更新
  • 7×24 小时人工支持
  • 2014 年起德国出品 · ISO 27001

WebView 中的 Supabase Auth

邮箱和密码登录无需任何改动:会话保存在 WebView 的存储中,只要封装层不清除它,就会一直保留(Config.swift 中的 deletecache 和 Config.java 中的 CLEAR_CACHE_ON_STARTUP 保持为 false)。OAuth 则不同。Google 拒绝在嵌入式 WebView 中完成登录(disallowed_useragent 错误),因此 WebViewGold 提供了 Social Login Helper:您列出登录提供方流程的 URL 前缀,封装层就会在一个提供方认可的专用登录窗口中打开这部分流程,完成后再返回您的应用。对于使用 Google 登录的 Supabase,触发规则是 https://accounts.google.com,在 google_login_helper_triggers(Config.swift)和 GOOGLE_LOGIN_HELPER_TRIGGERS(Config.java)中设置。Sign in with Apple 无需任何配置:封装层会自动识别 appleid.apple.com。

也就是说:在 Supabase 后台中启用 Apple 提供方(Services ID、密钥、Team ID、回调 URL),在 Google 按钮旁添加 Apple 按钮,以满足准则 4.8,并让 Claude Code 为两者接入 signInWithOAuth,重定向地址指向您的生产域名。

在应用内打开的魔法链接

邮件中的魔法链接默认会在浏览器中打开。Universal Links 和 App Links 则会把它送进应用。

  1. 提供关联文件

    让 Claude Code 在 Web 项目中添加 /.well-known/apple-app-site-association(包含您的 Team ID 和 Bundle ID 的 JSON,不带文件扩展名,并以 JSON 内容类型提供)和 /.well-known/assetlinks.json(您的包名和签名证书指纹)。在 Next.js 中,就是 public 文件夹加一条响应头规则。

  2. 在封装层中启用该能力

    iOS:在 Xcode 中添加 Associated Domains,值为 applinks:app.example.com,并在 Config.swift 中把 ShowExternalLink 设为 true。Android:在 AndroidManifest.xml 中为您的域名添加 intent filter,并在 Config.java 中把 IS_DEEP_LINKING_ENABLED 设为 true。详情见Universal Links 文档和App Links 文档。

  3. 让 Supabase 指向您的域名

    把站点 URL 和重定向白名单设为 https://app.example.com/auth/callback。这样邮件中的链接就会落在您的域名上,而只要应用已安装,系统就会把它交给应用。

  4. 提供验证码作为备用方案

    有些邮件应用会在自己的浏览器中打开链接。让 Claude Code 添加一个六位数 OTP 选项(在 Supabase 后台的魔法链接邮件模板中加入 token 变量),这样即使用户最终进入了 Safari,也仍然可以在应用内完成登录。如果您使用 PKCE 流程,这个备用方案就更加重要,因为 code verifier 只存在于发起登录的那个上下文中。

用边缘函数实现账户删除

Apple 5.1.1 和 Google Play 要求支持应用内删除;在 Supabase 中只需一个函数就能做到,service role 密钥始终保留在服务器端。

给 Claude Code 的提示词
按照 Apple 和 Google Play 的要求,为这个 Supabase 应用实现账户删除。
1. 创建一个 Supabase 边缘函数 delete-account:从 Authorization 请求头读取用户 JWT,并用 anon 客户端验证;然后使用只在函数内部创建的 service-role 客户端,删除该用户在所有引用 auth.users 的表中的数据行(从数据库结构中列出这些表;缺少 ON DELETE CASCADE 外键的地方优先补上,并编写迁移),删除该用户在存储桶中的文件,最后调用 auth.admin.deleteUser(userId)。成功时返回 204,否则返回清晰的错误信息。
2. 在 Web 应用中添加“设置 - 删除账户”,带确认对话框,说明会删除哪些内容;用当前会话调用该函数,退出登录并显示确认页面。如果存在 RevenueCat 订阅,提示用户先在 App Store 或 Google Play 设置中取消订阅。
3. 添加一个公开的 /delete-account 页面,为没有安装应用的用户说明删除流程。
4. 在 /privacy 中加一句关于账户删除的说明。
5. 编写一个测试:创建一个临时用户,插入数据行,调用该函数,并断言所有数据都已删除。

出色的工作!无需任何编码就能轻松完成。简单快捷!创作者也提供了大力帮助!

卢卡斯·杜波依斯(Lucas Dubois) · CodeCanyon

上线前的 RLS 提醒

anon 密钥本来就设计为放在客户端代码中,而已发布的应用任何人都可以下载。让这一切保持安全的,是行级安全(Row Level Security)。

  • public schema 中的每张表都启用了 RLS,并且针对 select、insert、update 和 delete 使用 auth.uid() 设置了明确的策略。让 Claude Code 列出没有启用 RLS 的表,并编写缺失的策略。
  • 存储桶也需要策略;公开的存储桶对所有人公开,包括那些从未打开过您应用的人。
  • service-role 密钥只出现在边缘函数和服务器代码中,绝不能出现在 Vite 或 Next.js 的客户端代码包里。在构建产物中用 grep 搜索一下。
  • 视图和 RPC 函数要遵从调用者的权限;除非确实需要 definer 权限,否则把函数标记为 security invoker。
  • 对身份验证和开销大的 RPC 调用设置速率限制,因为商店应用一上架就会吸引自动化流量。

把推送订阅 ID 保存到用户资料中

把 autoInjectVariable / AUTO_INJECT_VARIABLES 设为 true 后,封装层会在每个页面上注入 onesignalplayerid;否则就用 getonesignalplayerid:// 来请求它。把它保存到用户资料中,这样边缘函数就能定向推送给单个用户。

javascript
// after login, inside the native app only
import { supabase } from "./supabase";
import { isNativeApp, readInjected, callNative } from "./native";

export async function syncPushSubscription(userId) {
  if (!isNativeApp()) return;
  let playerId = window.onesignalplayerid; // present when auto-inject is on
  if (!playerId) {
    callNative("getonesignalplayerid://");
    playerId = await readInjected("onesignalplayerid", 3000).catch(function () { return null; });
  }
  if (!playerId) return;
  await supabase.from("profiles").update({ onesignal_player_id: playerId }).eq("id", userId);
}

// RLS policy to pair with it (SQL):
// create policy "users update own profile" on profiles for update
//   using (auth.uid() = id) with check (auth.uid() = id);

RevenueCat webhook 以及资金流的其余部分

从 Web 应用发起购买

在应用内,“升级”按钮会导航到 revenuecat://purchase?external_id=SUPABASE_USER_ID&product=PRODUCT_ID。正是把 Supabase 用户 ID 作为 external_id 传入,webhook 才能把这笔购买对应回数据库中的某一行。

Webhook 边缘函数

提示词:“创建一个边缘函数 revenuecat-webhook,验证在 RevenueCat 中配置的 Authorization 请求头,把事件以 app_user_id 为键 upsert 到 subscriptions 表中,并根据事件类型设置 is_active 标志。”客户端通过 RLS 读取权益,绝不依赖客户端的购买结果。

网页端继续使用 Stripe

浏览器中可以继续使用 Stripe。使用同一套权益模型(一张带有 source 列的 subscriptions 表),这样无论用户在哪里付款,功能都会以同样的方式解锁。请参阅RevenueCat 设置指南。

佣金

Apple 小型企业计划和 Google 的 15% 费率档:每年收入 100 万美元以下的部分佣金为 15%,超出部分为 30%。在两个控制台中申请,并告知 RevenueCat。

常见问题

商店应用需要 Supabase 的原生 SDK 吗?

不需要。在 WebViewGold 中运行的就是使用 supabase-js 的 Web 应用。原生层只通过 URL scheme 添加推送、生物识别、购买和深度链接。

Supabase 会话在应用重启后还会保留吗?

会,只要封装层不在启动时清除存储。把 deletecache(iOS)和 CLEAR_CACHE_ON_STARTUP(Android)保持为 false,并在 Supabase 后台中设置合理的会话有效期。

Google 登录在浏览器中可以用,在应用中却不行。为什么?

Google 会阻止嵌入式 WebView。在两个 WebViewGold 配置中为 accounts.google.com 设置 Social Login Helper 触发规则;封装层随后会在一个被认可的窗口中完成登录,然后返回您的应用。

Claude Code 能安全地编写 RLS 策略吗?

只要您提供数据库结构,并用通俗的语言描述访问规则,它就能写出不错的初稿。审阅每一条策略,用两个不同的用户测试,并且绝不要因为演示能跑通就发布一张没有 RLS 的表。

购买应该在哪里验证,客户端还是服务器?

服务器。RevenueCat webhook 调用边缘函数,这才是可信的数据来源;客户端只读取由此产生的数据行。在任何可下载的应用中,客户端的标志都可能被伪造。

让您的应用上架商店的三种方式

结果相同,只是您需要投入的工作量不同。三种方式都附带审核通过保证和 7×24 小时人工支持。

自己动手

$109 每个平台,一次性付费

WebViewGold 许可证:一个现成的 Xcode 或 Android Studio 项目。粘贴您的 URL,设置名称和图标,开启所需功能,构建并提交。永久免费更新。

在主页查看方案

Cloud Builder

$349 每个许可证,一次性附加购买

无需 Mac、Xcode 或 Android Studio:在浏览器中完成配置,我们在云端构建两个应用,并将其交付到 App Store Connect 和 Play Console。

Cloud Builder 如何运作 试用免费演示

Full Service

$698 每个平台 $798

把您的 URL 和图标发给我们。我们的团队在 72 小时内完成配置、构建并交付您的应用,白标,附源码项目。两个平台共 $1,158。

Full Service 详情 服务提供方: WeSetupYourWebViewApp

冬季特惠价格有效期至 2026年12月31日。

准备好发布您的应用了吗?

App Store & Google Play 审核通过保证 – 否则 14 天内退款

想直接交给我们?Full Service:我们在 72 小时内完成配置、构建并交付,每个平台 $698 起。有疑问?通过 7×24 小时在线聊天联系我们。

退款依据我们 FAQ 中列出的条件:应用因非内容原因被 Apple 和/或 Google 拒审,并在购买后 14 天内提出申请。