-
Notifications
You must be signed in to change notification settings - Fork 89
KM-16629: storekit2 #355
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
KM-16629: storekit2 #355
Changes from 8 commits
da5f952
00d29cb
2a8d6db
899a0ec
419b915
867f19e
0ef2b33
5b9ebfc
d22ca2b
fff748e
3a073d2
aa71f12
f8b6bff
e38dc3d
3492991
0d0eaf6
ac6e0fd
c0fda09
a9ec5bb
d7fbf4f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| .DS_Store | ||
| /.build | ||
| /Packages | ||
| xcuserdata/ | ||
| DerivedData/ | ||
| .swiftpm/configuration/registries.json | ||
| .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata | ||
| .netrc |
|
kp-mario-nachbaur marked this conversation as resolved.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| // swift-tools-version: 6.3 | ||
| // The swift-tools-version declares the minimum version of Swift required to build this package. | ||
|
|
||
| import PackageDescription | ||
|
|
||
| let package = Package( | ||
| name: "PIABase", | ||
| products: [ | ||
| // Products define the executables and libraries a package produces, making them visible to other packages. | ||
| .library( | ||
| name: "PIABase", | ||
| targets: ["PIABase"] | ||
| ) | ||
| ], | ||
| targets: [ | ||
| // Targets are the basic building blocks of a package, defining a module or a test suite. | ||
| // Targets can depend on other targets in this package and products from dependencies. | ||
| .target( | ||
| name: "PIABase" | ||
| ) | ||
|
|
||
| ], | ||
| swiftLanguageModes: [.v6] | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| // | ||
| // JWS.swift | ||
| // PIAAccount | ||
| // | ||
| // Created by Mario on 30/06/26. | ||
| // Copyright © 2020 Private Internet Access, Inc. | ||
| // | ||
| // This file is part of the Private Internet Access iOS Client. | ||
| // | ||
| // The Private Internet Access iOS Client is free software: you can redistribute it and/or | ||
| // modify it under the terms of the GNU General Public License as published by the Free | ||
| // Software Foundation, either version 3 of the License, or (at your option) any later version. | ||
| // | ||
| // The Private Internet Access iOS Client is distributed in the hope that it will be useful, | ||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
| // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | ||
| // details. | ||
| // | ||
| // You should have received a copy of the GNU General Public License along with the Private | ||
| // Internet Access iOS Client. If not, see <https://www.gnu.org/licenses/>. | ||
| // | ||
|
|
||
| import Foundation | ||
|
|
||
| public struct JWS: Sendable { | ||
| public let value: String | ||
|
|
||
| public init?(_ value: String) { | ||
| if value.isEmpty { return nil } | ||
| self.value = value | ||
| } | ||
|
|
||
| @inlinable | ||
| public var isEmpty: Bool { value.isEmpty } | ||
| } | ||
|
|
||
| extension JWS: Codable { | ||
| public init(from decoder: any Decoder) throws { | ||
| let container = try decoder.singleValueContainer() | ||
| self.value = try container.decode(String.self) | ||
| } | ||
|
|
||
| public func encode(to encoder: any Encoder) throws { | ||
| var container = encoder.singleValueContainer() | ||
| try container.encode(self.value) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,8 @@ | |
| import StoreKit | ||
| import SwiftUI | ||
|
|
||
| import struct PIABase.JWS | ||
|
|
||
| // MARK: - DebugMenuView | ||
|
|
||
| struct ReportResult: Identifiable { | ||
|
|
@@ -21,6 +23,7 @@ public struct DebugMenuView: View { | |
| @State private var isRefundSheetPresented = false | ||
| @State private var availableTransactions: [StoreKit.Transaction] = [] | ||
| @State private var isTransactionPickerPresented = false | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ⚪ LOW · SECURITY_REVIEW — Debug menu exports full StoreKit 2 JWS credential accessible in TestFlight builds The kb · |
||
| @State var entitlementJWS: JWS? = nil | ||
|
kp-mario-nachbaur marked this conversation as resolved.
kp-mario-nachbaur marked this conversation as resolved.
kp-mario-nachbaur marked this conversation as resolved.
|
||
|
|
||
| public var body: some View { | ||
| mainContent | ||
|
|
@@ -66,6 +69,9 @@ public struct DebugMenuView: View { | |
| .onAppear { | ||
| logSnapshot = logs | ||
| } | ||
| .task { | ||
| entitlementJWS = await Client.store.currentEntitlementJWS() | ||
| } | ||
| .onReceive(Timer.publish(every: 2, on: .main, in: .common).autoconnect()) { _ in | ||
| logSnapshot = logs | ||
| } | ||
|
|
@@ -157,11 +163,11 @@ public struct DebugMenuView: View { | |
| } | ||
|
|
||
| private var receiptSection: some View { | ||
| DebugSection("Payment Receipt") { | ||
| if let base64 = receiptBase64 { | ||
| let preview = String(base64.prefix(300)) + "..." | ||
| DebugSection("Transaction (JWS)") { | ||
| if let transactionJWS { | ||
| let preview = String(transactionJWS.value.prefix(300)) + "..." | ||
| VStack(alignment: .leading, spacing: 2) { | ||
| Text("Receipt (preview)") | ||
| Text("Transaction JWS (preview)") | ||
| .font(.caption) | ||
| .foregroundStyle(.secondary) | ||
| Text(preview) | ||
|
|
@@ -179,16 +185,16 @@ public struct DebugMenuView: View { | |
| #if os(iOS) | ||
|
kp-mario-nachbaur marked this conversation as resolved.
kp-mario-nachbaur marked this conversation as resolved.
|
||
| ShareLink( | ||
| item: DebugExportFile( | ||
| content: base64, | ||
| filename: "receipt_\(Int(Date().timeIntervalSince1970)).txt" | ||
| content: transactionJWS.value, | ||
| filename: "transaction_\(Int(Date().timeIntervalSince1970)).txt" | ||
| ), | ||
| preview: SharePreview("Receipt") | ||
| preview: SharePreview("Transaction JWS") | ||
| ) { | ||
| Label("Export", systemImage: "square.and.arrow.up") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ⚪ LOW · SECURITY_REVIEW — Debug menu exports raw StoreKit 2 JWS receipt via iOS share sheet
kb · |
||
| } | ||
| #endif | ||
| } else { | ||
| DebugInfoRow(label: "Receipt", value: "Not available") | ||
| DebugInfoRow(label: "Transaction", value: "Not available") | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,8 @@ | ||
| import Foundation | ||
| @preconcurrency import PIALibrary | ||
|
|
||
| import struct PIABase.JWS | ||
|
|
||
| @available(iOS 16, *) | ||
| extension DebugMenuView { | ||
| var appVersion: String { | ||
|
|
@@ -51,8 +53,8 @@ extension DebugMenuView { | |
| return formatter.string(from: date) | ||
| } | ||
|
|
||
| var receiptBase64: String? { | ||
| Client.store.paymentReceipt?.base64EncodedString() | ||
| var transactionJWS: JWS? { | ||
|
kp-mario-nachbaur marked this conversation as resolved.
kp-mario-nachbaur marked this conversation as resolved.
kp-mario-nachbaur marked this conversation as resolved.
kp-mario-nachbaur marked this conversation as resolved.
kp-mario-nachbaur marked this conversation as resolved.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ⚪ LOW · SECURITY_REVIEW — StoreKit 2 JWS receipt exported in plaintext via debug menu share sheet The new kb · There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ⚪ LOW · SECURITY_REVIEW — StoreKit 2 JWS receipt exposed in TestFlight debug export The debug menu's kb · |
||
| entitlementJWS | ||
| } | ||
|
|
||
| var logs: String { | ||
|
|
@@ -74,8 +76,8 @@ extension DebugMenuView { | |
| lines.append("Is Renewable: \(isRenewable)") | ||
| lines.append("Is Recurring: \(isRecurring)") | ||
| lines.append("") | ||
| lines.append("=== Payment Receipt ===") | ||
| lines.append(receiptBase64 ?? "Not available") | ||
| lines.append("=== Transaction (JWS) ===") | ||
| lines.append(transactionJWS?.value ?? "Not available") | ||
| lines.append("") | ||
| lines.append("=== Logs ===") | ||
| lines.append(logs) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.