|
1 | 1 | import Foundation |
2 | 2 |
|
3 | | -public enum OpenIapError: LocalizedError { |
| 3 | +public enum OpenIapFailure: LocalizedError { |
4 | 4 | case productNotFound(id: String) |
5 | 5 | case purchaseFailed(reason: String) |
6 | 6 | case purchaseCancelled |
@@ -44,10 +44,21 @@ public enum OpenIapError: LocalizedError { |
44 | 44 | } |
45 | 45 | } |
46 | 46 |
|
47 | | -// MARK: - Error Code Constants + Mapping (for bridging) |
| 47 | +// MARK: - Unified Error Event + Codes |
| 48 | +public struct OpenIapError: Codable, Equatable { |
| 49 | + public let code: String |
| 50 | + public let message: String |
| 51 | + public let productId: String? |
| 52 | + |
| 53 | + public init(code: String, message: String, productId: String? = nil) { |
| 54 | + self.code = code |
| 55 | + self.message = message |
| 56 | + self.productId = productId |
| 57 | + } |
| 58 | +} |
| 59 | + |
48 | 60 | public extension OpenIapError { |
49 | | - // Expose the same string codes available on PurchaseError, for convenience |
50 | | - // and to avoid importing two symbols at call sites. |
| 61 | + // Error Code Constants (single source) |
51 | 62 | static let E_UNKNOWN = "E_UNKNOWN" |
52 | 63 | static let E_SERVICE_ERROR = "E_SERVICE_ERROR" |
53 | 64 | static let E_USER_CANCELLED = "E_USER_CANCELLED" |
@@ -83,36 +94,6 @@ public extension OpenIapError { |
83 | 94 | static let E_ITEM_NOT_OWNED = "E_ITEM_NOT_OWNED" |
84 | 95 | static let E_EMPTY_SKU_LIST = "E_EMPTY_SKU_LIST" |
85 | 96 |
|
86 | | - /// OpenIAP string code that corresponds to this error case |
87 | | - var code: String { |
88 | | - switch self { |
89 | | - case .purchaseCancelled: |
90 | | - return Self.E_USER_CANCELLED |
91 | | - case .purchaseDeferred: |
92 | | - return Self.E_DEFERRED_PAYMENT |
93 | | - case .productNotFound: |
94 | | - return Self.E_SKU_NOT_FOUND |
95 | | - case .purchaseFailed: |
96 | | - return Self.E_SERVICE_ERROR |
97 | | - case .paymentNotAllowed: |
98 | | - return Self.E_IAP_NOT_AVAILABLE |
99 | | - case .invalidReceipt: |
100 | | - return Self.E_RECEIPT_FAILED |
101 | | - case .networkError: |
102 | | - return Self.E_NETWORK_ERROR |
103 | | - case .verificationFailed: |
104 | | - return Self.E_TRANSACTION_VALIDATION_FAILED |
105 | | - case .restoreFailed: |
106 | | - return Self.E_SERVICE_ERROR |
107 | | - case .storeKitError: |
108 | | - return Self.E_SERVICE_ERROR |
109 | | - case .notSupported: |
110 | | - return Self.E_FEATURE_NOT_SUPPORTED |
111 | | - case .unknownError: |
112 | | - return Self.E_UNKNOWN |
113 | | - } |
114 | | - } |
115 | | - |
116 | 97 | /// Dictionary of error keys to OpenIAP codes |
117 | 98 | static func errorCodes() -> [String: String] { |
118 | 99 | return [ |
@@ -168,55 +149,7 @@ public extension OpenIapError { |
168 | 149 | } |
169 | 150 | } |
170 | 151 |
|
171 | | -// MARK: - Unified Error Event under OpenIapError namespace |
172 | | -public struct OpenIapErrorEvent: Codable, Equatable { |
173 | | - public let code: String |
174 | | - public let message: String |
175 | | - public let productId: String? |
176 | | - |
177 | | - public init(code: String, message: String, productId: String? = nil) { |
178 | | - self.code = code |
179 | | - self.message = message |
180 | | - self.productId = productId |
181 | | - } |
182 | | - |
183 | | - // Re-export error code constants (single source under OpenIapError) |
184 | | - public static let E_USER_CANCELLED = OpenIapError.E_USER_CANCELLED |
185 | | - public static let E_USER_ERROR = OpenIapError.E_USER_ERROR |
186 | | - public static let E_DEFERRED_PAYMENT = OpenIapError.E_DEFERRED_PAYMENT |
187 | | - public static let E_INTERRUPTED = OpenIapError.E_INTERRUPTED |
188 | | - public static let E_ITEM_UNAVAILABLE = OpenIapError.E_ITEM_UNAVAILABLE |
189 | | - public static let E_SKU_NOT_FOUND = OpenIapError.E_SKU_NOT_FOUND |
190 | | - public static let E_SKU_OFFER_MISMATCH = OpenIapError.E_SKU_OFFER_MISMATCH |
191 | | - public static let E_QUERY_PRODUCT = OpenIapError.E_QUERY_PRODUCT |
192 | | - public static let E_ALREADY_OWNED = OpenIapError.E_ALREADY_OWNED |
193 | | - public static let E_ITEM_NOT_OWNED = OpenIapError.E_ITEM_NOT_OWNED |
194 | | - public static let E_NETWORK_ERROR = OpenIapError.E_NETWORK_ERROR |
195 | | - public static let E_SERVICE_ERROR = OpenIapError.E_SERVICE_ERROR |
196 | | - public static let E_REMOTE_ERROR = OpenIapError.E_REMOTE_ERROR |
197 | | - public static let E_INIT_CONNECTION = OpenIapError.E_INIT_CONNECTION |
198 | | - public static let E_SERVICE_DISCONNECTED = OpenIapError.E_SERVICE_DISCONNECTED |
199 | | - public static let E_CONNECTION_CLOSED = OpenIapError.E_CONNECTION_CLOSED |
200 | | - public static let E_IAP_NOT_AVAILABLE = OpenIapError.E_IAP_NOT_AVAILABLE |
201 | | - public static let E_BILLING_UNAVAILABLE = OpenIapError.E_BILLING_UNAVAILABLE |
202 | | - public static let E_FEATURE_NOT_SUPPORTED = OpenIapError.E_FEATURE_NOT_SUPPORTED |
203 | | - public static let E_SYNC_ERROR = OpenIapError.E_SYNC_ERROR |
204 | | - public static let E_RECEIPT_FAILED = OpenIapError.E_RECEIPT_FAILED |
205 | | - public static let E_RECEIPT_FINISHED = OpenIapError.E_RECEIPT_FINISHED |
206 | | - public static let E_RECEIPT_FINISHED_FAILED = OpenIapError.E_RECEIPT_FINISHED_FAILED |
207 | | - public static let E_TRANSACTION_VALIDATION_FAILED = OpenIapError.E_TRANSACTION_VALIDATION_FAILED |
208 | | - public static let E_EMPTY_SKU_LIST = OpenIapError.E_EMPTY_SKU_LIST |
209 | | - public static let E_NOT_PREPARED = OpenIapError.E_NOT_PREPARED |
210 | | - public static let E_NOT_ENDED = OpenIapError.E_NOT_ENDED |
211 | | - public static let E_DEVELOPER_ERROR = OpenIapError.E_DEVELOPER_ERROR |
212 | | - public static let E_PURCHASE_ERROR = OpenIapError.E_PURCHASE_ERROR |
213 | | - public static let E_ACTIVITY_UNAVAILABLE = OpenIapError.E_ACTIVITY_UNAVAILABLE |
214 | | - public static let E_ALREADY_PREPARED = OpenIapError.E_ALREADY_PREPARED |
215 | | - public static let E_PENDING = OpenIapError.E_PENDING |
216 | | - public static let E_UNKNOWN = OpenIapError.E_UNKNOWN |
217 | | -} |
218 | | - |
219 | | -public extension OpenIapErrorEvent { |
| 152 | +public extension OpenIapError { |
220 | 153 | /// Default human-readable message for a given error code |
221 | 154 | static func defaultMessage(for code: String) -> String { |
222 | 155 | switch code { |
@@ -269,21 +202,21 @@ public extension OpenIapErrorEvent { |
269 | 202 | } |
270 | 203 |
|
271 | 204 | /// Convenience factory that fills a default message for the code |
272 | | - static func make(code: String, productId: String? = nil, message: String? = nil) -> OpenIapErrorEvent { |
273 | | - return OpenIapErrorEvent( |
| 205 | + static func make(code: String, productId: String? = nil, message: String? = nil) -> OpenIapError { |
| 206 | + return OpenIapError( |
274 | 207 | code: code, |
275 | 208 | message: message ?? defaultMessage(for: code), |
276 | 209 | productId: productId |
277 | 210 | ) |
278 | 211 | } |
279 | 212 |
|
280 | 213 | /// Convenience: create error for empty SKU list (parity with previous API) |
281 | | - static func emptySkuList() -> OpenIapErrorEvent { |
282 | | - return OpenIapErrorEvent(code: OpenIapError.E_EMPTY_SKU_LIST, message: "Empty SKU list provided") |
| 214 | + static func emptySkuList() -> OpenIapError { |
| 215 | + return OpenIapError(code: OpenIapError.E_EMPTY_SKU_LIST, message: "Empty SKU list provided") |
283 | 216 | } |
284 | 217 |
|
285 | 218 | /// Create from OpenIapError |
286 | | - init(from error: OpenIapError, productId: String? = nil) { |
| 219 | + init(from error: OpenIapFailure, productId: String? = nil) { |
287 | 220 | switch error { |
288 | 221 | case .purchaseCancelled: |
289 | 222 | self.init(code: Self.E_USER_CANCELLED, message: "User cancelled the purchase flow", productId: productId) |
@@ -346,5 +279,35 @@ public extension OpenIapErrorEvent { |
346 | 279 | } |
347 | 280 | } |
348 | 281 |
|
349 | | -// Backward compatibility: keep previous public type names |
350 | | -// (Removed backward-compat typealiases as requested) |
| 282 | +// MARK: - Mapping from thrown errors to codes |
| 283 | +public extension OpenIapFailure { |
| 284 | + /// OpenIAP string code that corresponds to this error case |
| 285 | + var code: String { |
| 286 | + switch self { |
| 287 | + case .purchaseCancelled: |
| 288 | + return OpenIapError.E_USER_CANCELLED |
| 289 | + case .purchaseDeferred: |
| 290 | + return OpenIapError.E_DEFERRED_PAYMENT |
| 291 | + case .productNotFound: |
| 292 | + return OpenIapError.E_SKU_NOT_FOUND |
| 293 | + case .purchaseFailed: |
| 294 | + return OpenIapError.E_SERVICE_ERROR |
| 295 | + case .paymentNotAllowed: |
| 296 | + return OpenIapError.E_IAP_NOT_AVAILABLE |
| 297 | + case .invalidReceipt: |
| 298 | + return OpenIapError.E_RECEIPT_FAILED |
| 299 | + case .networkError: |
| 300 | + return OpenIapError.E_NETWORK_ERROR |
| 301 | + case .verificationFailed: |
| 302 | + return OpenIapError.E_TRANSACTION_VALIDATION_FAILED |
| 303 | + case .restoreFailed: |
| 304 | + return OpenIapError.E_SERVICE_ERROR |
| 305 | + case .storeKitError: |
| 306 | + return OpenIapError.E_SERVICE_ERROR |
| 307 | + case .notSupported: |
| 308 | + return OpenIapError.E_FEATURE_NOT_SUPPORTED |
| 309 | + case .unknownError: |
| 310 | + return OpenIapError.E_UNKNOWN |
| 311 | + } |
| 312 | + } |
| 313 | +} |
0 commit comments