Install
$ agentstack add skill-lh17708357536-gif-flutter-cn-overseas-app-skills-ios-app-store ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
iOS App Store 发布 Skill
> 适用于 Flutter iOS 上架 App Store / TestFlight。所有 ` 替换为项目实际值。 > > **跨平台共用规则在 ~/.claude/skills/_shared/rules.md`**: > - §3 buildNumber + Changelog 三件套(双平台共用) > - §5 ICP 备案应用名(iOS / Android 共用) > > 本 skill 只补充 iOS 特有的内容。
1. TestFlight train-closed 409 应对(iOS 独有)
症状:上传 IPA 后 Apple Connect 返回:
Validation failed (409)
Invalid Pre-Release Train. The train version 'X.Y.Z' is closed for new build submissions
根因:上一发布(如 1.0.1+19)已在 App Store 上线,App Store Connect 自动关闭 1.0.1 这条 pre-release train,不再接受任何 1.0.1+N build。
应对:必须按版本号纪律 patch +1,开新 train:
1.0.1+21→1.0.2+22(patch +1,buildNumber 同步 +1)pubspec.yaml、所有docs/changelog/{ios,android}/*.md文件名、CHANGELOG.mdheader 全部同步改名/同步号
2. build_ios_testflight.sh 模板
完整可执行模板见 [templates/build_ios_testflight.sh.template](templates/buildiostestflight.sh.template)。落地步骤:
cp ~/.claude/skills/ios-app-store/templates/build_ios_testflight.sh.template scripts/build_ios_testflight.sh- 替换 ``
chmod +x scripts/build_ios_testflight.sh
调用:
./scripts/build_ios_testflight.sh --build-name 1.0.2 --build-number 22
3. pubspec.yaml Release 默认值
name:
description: ""
publish_to: 'none'
version: 1.0.0+1
environment:
sdk: ^3.10.0
生产口径:iOS / TestFlight / App Store 生产包默认后端必须固定(不能 fallback 到 localhost / 空值)。build_ios_testflight.sh 强制传 API_BASE_URL。
4. Info.plist 关键字段
CFBundleDisplayName
CFBundleName
CFBundleShortVersionString
$(FLUTTER_BUILD_NAME)
CFBundleVersion
$(FLUTTER_BUILD_NUMBER)
NSCameraUsageDescription
用于扫码、拍照等业务功能
NSMicrophoneUsageDescription
用于语音输入和通话功能
NSPhotoLibraryUsageDescription
用于选择照片上传
中国区 App Store ICP 备案 → CFBundleDisplayName 必须等于备案名,详见 ~/.claude/skills/_shared/rules.md §5。
5. 设备标识(IDFV / ATT)
只用 IDFV,不用 IDFA:
identifierForVendor(IDFV) = vendor 级标识,App 卸载即重置,不需要 ATT 弹窗- IDFA = 跨 App 广告追踪标识,需要 ATT 授权
如果不用 IDFA:
Info.plist不写NSUserTrackingUsageDescription- 隐私营养标签(App Store Connect 后台)"用于跟踪您的数据" = "未收集"
- 用户在 iOS Settings → 隐私与安全性 → 跟踪 → 你的 app 应不出现在列表中
Flutter 端 IDFV 读取(device_info_plus):
final ios = await DeviceInfoPlugin().iosInfo;
final stableId = ios.identifierForVendor ?? ios.utsname.machine;
6. Privacy Manifest(PrivacyInfo.xcprivacy)— 强制项
> 自 2024 年 5 月起,App Store 强制要求 app 主体 + 三方 SDK 都附带 Privacy Manifest。缺失或不一致会触发 ITMS-91053 / ITMS-91056 警告。
主 manifest 位置:ios/Runner/PrivacyInfo.xcprivacy,并在 Xcode 中将文件加入 Runner target 的 Copy Bundle Resources。
最小模板(仅用 IDFV、不跟踪):见 [templates/PrivacyInfo.xcprivacy](templates/PrivacyInfo.xcprivacy)。模板含 4 类常见 Required Reason API 速查(FileTimestamp / UserDefaults / SystemBootTime / DiskSpace + 对应 reason code)。
SDK manifest 检查:三方 SDK(fluwx、tobias、firebase、jpush 等)需各自在 framework 内带 PrivacyInfo.xcprivacy:
# 列出 ipa 内所有 PrivacyInfo.xcprivacy
unzip -l build/ios/ipa/.ipa | grep -i 'PrivacyInfo.xcprivacy'
主 app + 每个 framework 都应该有一份。少哪个就升级哪个 SDK 到带 manifest 的版本。
审核警告查阅:上传后到 App Store Connect → TestFlight → build 详情 → "Apple-issued warnings",看具体是哪个 SDK / 哪个 API 缺 reason code。
7. IAP capability 判定(不要看 entitlements)
> 铁律:iOS 项目的 Runner.entitlements 不会包含 In-App Purchase 相关的 key(不像 APNs 的 aps-environment 或 HealthKit 的 com.apple.developer.healthkit)。IAP capability 只在 Apple Developer Portal 的 App ID Capabilities 页面勾选,Provisioning Profile 重生成后即生效。
禁止根据 Runner.entitlements 不含 com.apple.InAppPurchase 就判定 "IAP capability 缺失 / 100% 会被拒"。这是误判。
正确判定方式(任选其一):
- 询问用户:是否在 Apple Developer Portal 的 App ID 上勾选了 In-App Purchase
- 或解 ipa 看 embedded mobileprovision:
``bash unzip -p Runner.ipa Payload/Runner.app/embedded.mobileprovision \ | security cms -D \ | grep -A2 Entitlements ``
- 或问用户:TestFlight / Sandbox 是否能跑通购买流程
8. IAP 服务端验证(App Store Server API)
> 客户端 in_app_purchase 拿到 JWSRepresentation 后必须由后端验签,不能信客户端自报的 productId / transactionId。
.env 配置:
APPLE_ISSUER_ID= # App Store Connect → Users and Access → Integrations → App Store Server API
APPLE_KEY_ID= # 同页面新建的 Key 的 KEY ID
APPLE_PRIVATE_KEY_PATH=/keys/AuthKey_.p8
APPLE_BUNDLE_ID= # 例:com.acme.myapp
APPLE_ENVIRONMENT=Production # Sandbox(TestFlight)/ Production(正式)
验签流程(NestJS 模板):
import { AppStoreServerAPIClient, Environment, SignedDataVerifier } from '@apple/app-store-server-library';
const verifier = new SignedDataVerifier(
appleRootCAs, true, Environment.PRODUCTION, process.env.APPLE_BUNDLE_ID!,
);
const decoded = await verifier.verifyAndDecodeTransaction(jwsRepresentation);
// decoded.productId / .transactionId / .originalTransactionId / .purchaseDate / .expiresDate
// 用 decoded.productId 查 DEFAULT_IAP_PRICING;按 transactionId 幂等入账
// 写 IapTransaction 表(transactionId 唯一索引,防重)
Sandbox vs Production 切换:
- TestFlight + Sandbox 测试账号 →
APPLE_ENVIRONMENT=Sandbox - App Store 正式购买 →
APPLE_ENVIRONMENT=Production - 同一台后端可用 environment fallback 策略:先 Production 验,失败时降级 Sandbox 重试
App Store Server Notifications V2:
- App Store Connect → App → App Store Server Notifications 配置 webhook URL(
https:///api/v1/payment/apple/webhook) - 后端 webhook 收
SUBSCRIBED / DID_RENEW / DID_FAIL_TO_RENEW / REFUND等事件 - webhook 也是 JWS,用同一个
verifyAndDecodeNotification验签
9. APNs 推送
iOS 推送链路:
- Flutter 端:
firebase_messaging(如 overseas flavor)或原生APNStoken 注册 - 后端:用 Apple JWS(JWT)签
.p8key 调 APNs HTTP/2 接口 .env:
APPLE_ISSUER_ID=
APPLE_KEY_ID=
APPLE_PRIVATE_KEY_PATH=/keys/AuthKey_.p8
APPLE_BUNDLE_ID=
APPLE_WEBHOOK_ENVIRONMENT=Sandbox
.p8 私钥不进 git,单独通过 rsync --ignore-existing 推到 keys/ 目录。
10. App Store Connect 上传
方式 A(推荐)—Transporter:
- 打开 macOS App「Transporter」(App Store 免费下载)
- 把
build/ios/ipa/.ipa拖入 - 点 Deliver 上传
方式 B—命令行 altool:
xcrun altool --upload-app \
--type ios \
-f "build/ios/ipa/.ipa" \
--apiKey \
--apiIssuer
上传成功后在 App Store Connect → TestFlight 看 build 状态:
Processing(5-30 分钟)Ready to Submit(外测开关 + 选择测试组)
11. Privacy Nutrition Labels(隐私营养标签)
App Store Connect → My Apps → App Privacy → Manage
最少集(如本 app 只用 IDFV):
- "Identifiers" → 是的
- "User ID" / "Device ID" → ❌ 未收集
- "Identifier for Vendors" 不在标签选项中(IDFV 不算 trackable)
- "Contact Info" → ❌ 未收集
- "Tracking" → ❌ 未收集(确认无 IDFA)
- 所收集均"链接到您的身份" / "不用于跟踪"
12. iOS 商店投放文案模板
docs/changelog/ios/.md 模板(buildNumber + Changelog 三件套规则在 _shared/rules.md §3,本节只是 iOS 商店特有的字数限制 + 文案约定):
# x.y.z+n · iOS(App Store / TestFlight)
> 字数限制:≤ 4000 字符(App Store What's New)。
> 禁止内部编号;禁止第三方 AI 品牌名(统一产品名);动词开头,每条 1 句话。
## 中文(zh-Hans / zh-Hant 投放)
- 新增:[功能名] [一句话价值]
- 优化:[XX] [改进点]
- 修复:[XX] [问题]
## English (en + global locales)
- New: [feature] [value]
- Improved: [thing] [improvement]
- Fixed: [thing] [issue]
CHANGELOG.md 总索引格式见 _shared/rules.md §3。
13. iOS 隐私政策 v1.x 升级流程
新版隐私政策上线(如 v1.0 → v1.1)时:
- App 启动检测当前用户已同意的版本号 `)
- 备案 App 名称必须与
CFBundleDisplayName一致(详见_shared/rules.md§5) - App Store Connect → App Information → "China Mainland" 区域填 ICP 信息
- 工信部备案的 App 名称、版号一致;版号变化时需在工信部更新备案
参考
- 配套 skill:
backend-production-deploy(APNs.env)、flutter-coding-conventions(buildNumber 纪律双平台共用)、cn-android-flavor(备案名同步)、overseas-android-google-play(海外用 FCM 而非 APNs) - App Store Review Guidelines:https://developer.apple.com/app-store/review/guidelines/
- Privacy Nutrition Label 文档:https://developer.apple.com/app-store/app-privacy-details/
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: lh17708357536-gif
- Source: lh17708357536-gif/flutter-cn-overseas-app-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.