Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx skills add wangjianqi/AppStore --skill 08-subscription-paywallgit clone --depth 1 https://github.com/wangjianqi/AppStoreWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/wangjianqi/appstore/08-subscription-paywall)<a href="https://agentmods.dev/skills/wangjianqi/appstore/08-subscription-paywall"><img src="https://agentmods.dev/badge/skills/wangjianqi/appstore/08-subscription-paywall.svg" alt="Measured on agentmods" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00038 | $0.02105 |
| Opus 5 | $0.00019 | $0.01052 |
| Sonnet 5 | $0.00008 | $0.00421 |
| Haiku 4.5 | $0.00004 | $0.00211 |
Grade A, and why
subscription-paywall scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 8d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 293 lines — stays where its author put it; the contents beside it link to each section on GitHub.
订阅 & Paywall
技术栈
- StoreKit 2(iOS 15+)
- 产品配置:App Store Connect → Subscriptions
- 本地权益验证:
Transaction.currentEntitlements - 服务端验证(可选):JWS Transaction 发送到后端校验
订阅产品结构
enum SubscriptionProduct: String, CaseIterable {
case monthly = "com.app.subscription.monthly"
case yearly = "com.app.subscription.yearly"
}
extension SubscriptionProduct {
var displayName: String {
switch self {
case .monthly: return "月度会员"
case .yearly: return "年度会员"
}
}
var pricePerMonth: String {
switch self {
case .monthly: return "按月付费"
case .yearly: return "按年付费(省 40%)"
}
}
}
SubscriptionManager 完整封装
import StoreKit
final class SubscriptionManager {
static let shared = SubscriptionManager()
private(set) var isPro: Bool = false
private(set) var activeSubscription: SubscriptionProduct?
private(set) var expirationDate: Date?
var onEntitlementChanged: ((Bool) -> Void)?
private var transactionListener: Task<Void, Never>?
private init() {
transactionListener = listenForTransactions()
Task { await checkEntitlement() }
}
deinit {
transactionListener?.cancel()
}
func loadProducts() async throws -> [Product] {
let productIDs = SubscriptionProduct.allCases.map(\.rawValue)
return try await Product.products(for: productIDs)
}
func purchase(_ product: Product) async throws -> Bool {
let result = try await product.purchase()
switch result {
case .success(let verification):
let transaction = try checkVerification(verification)
await transaction.finish()
await updateEntitlement(transaction)
return true
case .userCancelled:
return false
case .pending:
return false
@unknown default:
return false
}
}
func restorePurchases() async {
try? await AppStore.sync()
await checkEntitlement()
}
func checkEntitlement() async {
var isSubscribed = false
var latestTransaction: StoreKit.Transaction?
for await result in Transaction.currentEntitlements {
if case .verified(let transaction) = result {
if transaction.productType == .autoRenewable,
transaction.revocationDate == nil {
isSubscribed = true
if latestTransaction == nil || transaction.expirationDate ?? .distantPast > latestTransaction?.expirationDate ?? .distantPast {
latestTransaction = transaction
}
}
}
}
isPro = isSubscribed
if let transaction = latestTransaction {
activeSubscription = SubscriptionProduct(rawValue: transaction.productID)
expirationDate = transaction.expirationDate
}
onEntitlementChanged?(isPro)
}
private func listenForTransactions() -> Task<Void, Never> {
Task.detached { [weak self] in
for await result in Transaction.updates {
if case .verified(let transaction) = result {
await transaction.finish()
await self?.updateEntitlement(transaction)
}
}
}
}
private func updateEntitlement(_ transaction: StoreKit.Transaction) async {
isPro = transaction.revocationDate == nil
activeSubscription = SubscriptionProduct(rawValue: transaction.productID)
expirationDate = transaction.expirationDate
onEntitlementChanged?(isPro)
}
private func checkVerification(_ result: VerificationResult<StoreKit.Transaction>) throws -> StoreKit.Transaction {
switch result {
case .unverified(_, let error):
throw error
case .verified(let transaction):
return transaction
}
}
}
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 8d ago First seen · 293 lines · 38 tokens per session scan A 688914921d1b
subscription-paywall is a skill published in the GitHub repository wangjianqi/AppStore (11 stars, last pushed 3mo ago), licensed MIT. It adds 38 tokens to every session and 2,105 once invoked, about $0.0002 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.
Other skills, from other repositories
user-journey-tracking
Track user journeys with intent context and friction signals. Use when instrumenting onboarding, checkout, or any multi-step flow where you need to understand WHY users fail.
onesub
Use this skill when the user wants to add in-app purchases (subscriptions, consumables, or non-consumables) to a React Native / Expo mobile app. onesub is the open-source server side of react-native-iap — one line of Express middleware validates Apple StoreKit 2 and Google Play Billing receipts. Pair it with the…
storekit
In-app purchases and subscriptions on iOS/iPadOS/macOS with StoreKit 2 (iOS 26 era) — fetch products with Product.products(for:), buy with Product.purchase and switch on PurchaseResult (.success/.pending/.userCancelled), always unwrap VerificationResult (.verified/.unverified), gate access from…
ipaship-audit
Use when auditing iOS/Android app submissions for compliance with Apple App Store Review Guidelines or Google Play Developer Policies. Scan .ipa, .apk, or .zip files against official store policies, generate structured compliance reports, and identify violations with remediation steps.
storekit
Implement, review, or improve in-app purchases and subscriptions using StoreKit 2. Use when building paywalls with SubscriptionStoreView or ProductView, processing transactions with Product and Transaction APIs, verifying entitlements, handling purchase flows (consumable, non-consumable, auto-renewable), implementing…
ax-storekit
StoreKit 2 in-app purchases, subscriptions, transactions.