Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Public OSS repository that packages a StoreKit 2 iOS interop wrapper into a cons

A NuGet package that:
- provides a minimal managed API for StoreKit 2 purchase and restore flows;
- exposes store-formatted subscription prices plus an optional annual-to-monthly equivalent formatted with StoreKit's native price style;
- redistributes the native wrapper `xcframework` inside the `.nupkg`;
- injects the wrapper into consuming apps through `buildTransitive` `NativeReference`.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ private struct OfferMetadataPayload: Codable {
let introOfferDays: Int?
let currentPrice: Decimal
let currentPriceDisplayText: String
let monthlyEquivalentPriceDisplayText: String?
}

private final class PurchaseCallbackContext: @unchecked Sendable {
Expand Down Expand Up @@ -226,6 +227,19 @@ private func totalDays(for offer: Product.SubscriptionOffer?) -> Int? {
return unitValue * max(offer.periodCount, 1)
}

private func monthlyEquivalentPriceDisplayText(
for product: Product,
subscription: Product.SubscriptionInfo
) -> String? {
guard subscription.subscriptionPeriod.unit == .year,
subscription.subscriptionPeriod.value == 1 else {
return nil
}

let monthlyPrice = product.price / Decimal(12)
return monthlyPrice.formatted(product.priceFormatStyle)
}

private struct PromotionalOfferInput {
let offerId: String
let keyId: String
Expand Down Expand Up @@ -652,7 +666,11 @@ public func kstorekit2_offer_metadata_start(
isEligibleForIntroOffer: isEligibleForIntroOffer,
introOfferDays: introOfferDays,
currentPrice: product.price,
currentPriceDisplayText: product.displayPrice
currentPriceDisplayText: product.displayPrice,
monthlyEquivalentPriceDisplayText: monthlyEquivalentPriceDisplayText(
for: product,
subscription: subscription
)
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ public sealed record StoreKitOfferMetadata(
bool IsEligibleForIntroOffer,
int? IntroOfferDays,
decimal? CurrentPrice,
string? CurrentPriceDisplayText
string? CurrentPriceDisplayText,
string? MonthlyEquivalentPriceDisplayText = null
);

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ internal sealed class StoreKitOfferMetadataPayload

[JsonPropertyName("currentPriceDisplayText")]
public string? CurrentPriceDisplayText { get; init; }

[JsonPropertyName("monthlyEquivalentPriceDisplayText")]
public string? MonthlyEquivalentPriceDisplayText { get; init; }
}

internal static unsafe partial class StoreKitNativeInterop
Expand Down Expand Up @@ -622,7 +625,8 @@ private static IReadOnlyList<StoreKitOfferMetadata> ParseOfferMetadata(string? p
item.IsEligibleForIntroOffer,
item.IntroOfferDays,
item.CurrentPrice,
item.CurrentPriceDisplayText
item.CurrentPriceDisplayText,
item.MonthlyEquivalentPriceDisplayText
))
.ToArray();
}
Expand Down
1 change: 1 addition & 0 deletions src/Kapusch.StoreKit2ApisForiOSComponents/nuget-readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
- Target framework: `net10.0-ios`
- Native wrapper: `kstorekit2.xcframework`
- Native injection: `buildTransitive` `NativeReference`
- Offer metadata: store-formatted current price and optional monthly equivalent for one-year subscriptions
Loading