diff --git a/StripeCardScan/StripeCardScanTests/Unit/API Bindings/ScanStatsPayloadAPIBindingsTests.swift b/StripeCardScan/StripeCardScanTests/Unit/API Bindings/ScanStatsPayloadAPIBindingsTests.swift index 22a4123c9e01..cb4d62e48856 100644 --- a/StripeCardScan/StripeCardScanTests/Unit/API Bindings/ScanStatsPayloadAPIBindingsTests.swift +++ b/StripeCardScan/StripeCardScanTests/Unit/API Bindings/ScanStatsPayloadAPIBindingsTests.swift @@ -74,7 +74,7 @@ class ScanStatsPayloadAPIBindingsTests: XCTestCase { /// Check that scan stats tasks is encoded properly func testScanStatsTasks() throws { /// Check that scan stats tasks is encoded properly - let jsonDictionary = try scanStatsTasks.encodeJSONDictionary() + let jsonDictionary = try StripeJSONEncoder().encodeJSONDictionary(scanStatsTasks) let tasksDictionary = jsonDictionary["tasks"] as! [String: Any] let repeatingTaskDictionary = jsonDictionary["repeating_tasks"] as! [String: Any] @@ -85,7 +85,7 @@ class ScanStatsPayloadAPIBindingsTests: XCTestCase { /// Check that non repeating tasks are encoded properly func testNonRepeatingTasks() throws { /// Check that the JSON dictionary is formed properly - let jsonDictionary = try nonRepeatingTasks.encodeJSONDictionary() + let jsonDictionary = try StripeJSONEncoder().encodeJSONDictionary(nonRepeatingTasks) let jsonCameraPermissions = jsonDictionary["camera_permission"] as! [[String: Any]] XCTAssertEqual(jsonCameraPermissions.count, 1) XCTAssertEqual(jsonCameraPermissions[0]["result"] as! String, "success") @@ -111,7 +111,7 @@ class ScanStatsPayloadAPIBindingsTests: XCTestCase { /// Check that repeating tasks are encoded properly func testRepeatingTasks() throws { /// Check that the JSON dictionary is formed properly - let jsonDictionary = try repeatingTasks.encodeJSONDictionary() + let jsonDictionary = try StripeJSONEncoder().encodeJSONDictionary(repeatingTasks) let jsonMainLoop = jsonDictionary["main_loop_images_processed"] as! [String: Any] XCTAssertEqual(jsonMainLoop["executions"] as? Int, -1) } @@ -130,7 +130,7 @@ class ScanStatsPayloadAPIBindingsTests: XCTestCase { scanStats: scanStatsTasks ) ) - let jsonDictionary = try scanStatsPayload.encodeJSONDictionary() + let jsonDictionary = try StripeJSONEncoder().encodeJSONDictionary(scanStatsPayload) /// Create query string let queryString = URLEncoder.queryString(from: jsonDictionary) diff --git a/StripeCardScan/StripeCardScanTests/Unit/API Bindings/VerifyFramesAPIBindingsTests.swift b/StripeCardScan/StripeCardScanTests/Unit/API Bindings/VerifyFramesAPIBindingsTests.swift index 64df6671f8af..311f945de308 100644 --- a/StripeCardScan/StripeCardScanTests/Unit/API Bindings/VerifyFramesAPIBindingsTests.swift +++ b/StripeCardScan/StripeCardScanTests/Unit/API Bindings/VerifyFramesAPIBindingsTests.swift @@ -26,7 +26,7 @@ class VerifyFramesAPIBindingsTests: XCTestCase { ) /// encodeJSONDictionary used when forming the request body - let jsonDictionary = try verifyFrames.encodeJSONDictionary() + let jsonDictionary = try StripeJSONEncoder().encodeJSONDictionary(verifyFrames) XCTAssertEqual(jsonDictionary["client_secret"] as! String, CIVIntentMockData.clientSecret) XCTAssertEqual( @@ -59,7 +59,7 @@ class VerifyFramesAPIBindingsTests: XCTestCase { ) /// encodeJSONDictionary used when forming the request body - let jsonDictionary = try verificationFramesData.encodeJSONDictionary() + let jsonDictionary = try StripeJSONEncoder().encodeJSONDictionary(verificationFramesData) let jsonDictionaryViewfinderMargins = jsonDictionary["viewfinder_margins"] as! [String: Any] XCTAssertEqual(jsonDictionary["image_data"] as! String, "aW1hZ2VfZGF0YQ==") diff --git a/StripeCore/StripeCore/Source/API Bindings/STPAPIClient.swift b/StripeCore/StripeCore/Source/API Bindings/STPAPIClient.swift index 1f57054e779a..507982da34ed 100644 --- a/StripeCore/StripeCore/Source/API Bindings/STPAPIClient.swift +++ b/StripeCore/StripeCore/Source/API Bindings/STPAPIClient.swift @@ -494,7 +494,7 @@ extension STPAPIClient { completion: @escaping (Result) -> Void ) { do { - let jsonDictionary = try object.encodeJSONDictionary() + let jsonDictionary = try StripeJSONEncoder().encodeJSONDictionary(object) let formData = URLEncoder.queryString(from: jsonDictionary).data(using: .utf8) var request = configuredRequest( for: url, diff --git a/StripeCore/StripeCore/Source/API Bindings/StripeError.swift b/StripeCore/StripeCore/Source/API Bindings/StripeError.swift index f4a4083cac50..2f1b40fa1346 100644 --- a/StripeCore/StripeCore/Source/API Bindings/StripeError.swift +++ b/StripeCore/StripeCore/Source/API Bindings/StripeError.swift @@ -9,7 +9,7 @@ import Foundation /// Error codes returned from STPAPIClient. -@_spi(STP) public enum StripeError: Error { +@_spi(STP) @frozen public enum StripeError: Error { /// The server returned an API error. case apiError(StripeAPIError) diff --git a/StripeCore/StripeCore/Source/Analytics/STPAnalyticEvent.swift b/StripeCore/StripeCore/Source/Analytics/STPAnalyticEvent.swift index 0323c8d1d9ba..1ad9a06114f6 100644 --- a/StripeCore/StripeCore/Source/Analytics/STPAnalyticEvent.swift +++ b/StripeCore/StripeCore/Source/Analytics/STPAnalyticEvent.swift @@ -9,7 +9,7 @@ import Foundation /// Enumeration of all the analytic events logged by our SDK. -@_spi(STP) public enum STPAnalyticEvent: String { +@_spi(STP) @frozen public enum STPAnalyticEvent: String { // MARK: - Payment Creation case tokenCreation = "stripeios.token_creation" diff --git a/StripeCore/StripeCore/Source/Coder/StripeCodable.swift b/StripeCore/StripeCore/Source/Coder/StripeCodable.swift index 03e9206a810d..659ef75f93c3 100644 --- a/StripeCore/StripeCore/Source/Coder/StripeCodable.swift +++ b/StripeCore/StripeCore/Source/Coder/StripeCodable.swift @@ -64,10 +64,6 @@ extension UnknownFieldsDecodable { self._allResponseFieldsStorage!.storage = newValue } } - - static func decodedObject(jsonData: Data) throws -> Self { - return try StripeJSONDecoder.decode(jsonData: jsonData) - } } extension UnknownFieldsEncodable { @@ -97,16 +93,6 @@ extension UnknownFieldsEncodable { } } -extension Encodable { - @_spi(STP) public func encodeJSONDictionary(includingUnknownFields: Bool = true) throws -> [String: Any] { - let encoder = StripeJSONEncoder() - return try encoder.encodeJSONDictionary( - self, - includingUnknownFields: includingUnknownFields - ) - } -} - @_spi(STP) public enum UnknownFieldsCodableFloats: String { case PositiveInfinity = "Inf" case NegativeInfinity = "-Inf" diff --git a/StripeCore/StripeCore/Source/Coder/StripeJSONEncoder.swift b/StripeCore/StripeCore/Source/Coder/StripeJSONEncoder.swift index fd85a1d15b59..7ff2d9478517 100644 --- a/StripeCore/StripeCore/Source/Coder/StripeJSONEncoder.swift +++ b/StripeCore/StripeCore/Source/Coder/StripeJSONEncoder.swift @@ -14,6 +14,8 @@ import Foundation @_spi(STP) public var outputFormatting: JSONSerialization.WritingOptions = [] + @_spi(STP) public init() {} + @_spi(STP) public func encode(_ value: T, includingUnknownFields: Bool = true) throws -> Data where T: Encodable { var outputFormatting = self.outputFormatting @@ -30,7 +32,7 @@ import Foundation ) } else { return try JSONSerialization.data( - withJSONObject: castToNSObject(value), + withJSONObject: StripeEncodingUtils.castToNSObject(userInfo: userInfo, value), options: outputFormatting ) } @@ -55,7 +57,7 @@ import Foundation // Encode the object to JSON data let jsonData = try JSONSerialization.data( - withJSONObject: castToNSObject(value), + withJSONObject: StripeEncodingUtils.castToNSObject(userInfo: userInfo, value), options: outputFormatting ) @@ -73,9 +75,6 @@ import Foundation } } -// Make sure StripeJSONEncoder can call castToNSObject -extension StripeJSONEncoder: StripeEncodingContainer {} - class _stpinternal_JSONEncoder: Encoder { var codingPath: [CodingKey] = [] @@ -131,8 +130,7 @@ class _stpinternal_JSONEncoder: Encoder { } } -struct STPKeyedEncodingContainer: StripeEncodingContainer, KeyedEncodingContainerProtocol -where K: CodingKey { +struct STPKeyedEncodingContainer: KeyedEncodingContainerProtocol where K: CodingKey { var codingPath: [CodingKey] typealias Key = K @@ -155,59 +153,59 @@ where K: CodingKey { } mutating func encode(_ value: Bool, forKey key: K) throws { - try encode(object: castToNSObject(value), forKey: key) + try encode(object: StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value), forKey: key) } mutating func encode(_ value: String, forKey key: K) throws { - try encode(object: castToNSObject(value), forKey: key) + try encode(object: StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value), forKey: key) } mutating func encode(_ value: Double, forKey key: K) throws { - try encode(object: castToNSObject(value), forKey: key) + try encode(object: StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value), forKey: key) } mutating func encode(_ value: Float, forKey key: K) throws { - try encode(object: castToNSObject(value), forKey: key) + try encode(object: StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value), forKey: key) } mutating func encode(_ value: Int, forKey key: K) throws { - try encode(object: castToNSObject(value), forKey: key) + try encode(object: StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value), forKey: key) } mutating func encode(_ value: Int8, forKey key: K) throws { - try encode(object: castToNSObject(value), forKey: key) + try encode(object: StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value), forKey: key) } mutating func encode(_ value: Int16, forKey key: K) throws { - try encode(object: castToNSObject(value), forKey: key) + try encode(object: StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value), forKey: key) } mutating func encode(_ value: Int32, forKey key: K) throws { - try encode(object: castToNSObject(value), forKey: key) + try encode(object: StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value), forKey: key) } mutating func encode(_ value: Int64, forKey key: K) throws { - try encode(object: castToNSObject(value), forKey: key) + try encode(object: StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value), forKey: key) } mutating func encode(_ value: UInt, forKey key: K) throws { - try encode(object: castToNSObject(value), forKey: key) + try encode(object: StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value), forKey: key) } mutating func encode(_ value: UInt8, forKey key: K) throws { - try encode(object: castToNSObject(value), forKey: key) + try encode(object: StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value), forKey: key) } mutating func encode(_ value: UInt16, forKey key: K) throws { - try encode(object: castToNSObject(value), forKey: key) + try encode(object: StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value), forKey: key) } mutating func encode(_ value: UInt32, forKey key: K) throws { - try encode(object: castToNSObject(value), forKey: key) + try encode(object: StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value), forKey: key) } mutating func encode(_ value: UInt64, forKey key: K) throws { - try encode(object: castToNSObject(value), forKey: key) + try encode(object: StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value), forKey: key) } mutating func encode(_ value: T, forKey key: K) throws where T: Encodable { @@ -219,7 +217,7 @@ where K: CodingKey { if let seValue = value as? UnknownFieldsEncodable { seValue.applyUnknownFieldEncodingTransforms(userInfo: userInfo, codingPath: newPath) } - try encode(object: castToNSObject(codingPath: newPath, value), forKey: key) + try encode(object: StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: newPath, value), forKey: key) } mutating func nestedContainer( @@ -264,7 +262,7 @@ where K: CodingKey { } } -struct STPUnkeyedEncodingContainer: UnkeyedEncodingContainer, StripeEncodingContainer { +struct STPUnkeyedEncodingContainer: UnkeyedEncodingContainer { var codingPath: [CodingKey] var count: Int = 0 @@ -278,72 +276,72 @@ struct STPUnkeyedEncodingContainer: UnkeyedEncodingContainer, StripeEncodingCont } mutating func encode(_ value: Bool) throws { - try array.add(castToNSObject(value)) + try array.add(StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) count += 1 } mutating func encode(_ value: String) throws { - try array.add(castToNSObject(value)) + try array.add(StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) count += 1 } mutating func encode(_ value: Double) throws { - try array.add(castToNSObject(value)) + try array.add(StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) count += 1 } mutating func encode(_ value: Float) throws { - try array.add(castToNSObject(value)) + try array.add(StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) count += 1 } mutating func encode(_ value: Int) throws { - try array.add(castToNSObject(value)) + try array.add(StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) count += 1 } mutating func encode(_ value: Int8) throws { - try array.add(castToNSObject(value)) + try array.add(StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) count += 1 } mutating func encode(_ value: Int16) throws { - try array.add(castToNSObject(value)) + try array.add(StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) count += 1 } mutating func encode(_ value: Int32) throws { - try array.add(castToNSObject(value)) + try array.add(StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) count += 1 } mutating func encode(_ value: Int64) throws { - try array.add(castToNSObject(value)) + try array.add(StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) count += 1 } mutating func encode(_ value: UInt) throws { - try array.add(castToNSObject(value)) + try array.add(StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) count += 1 } mutating func encode(_ value: UInt8) throws { - try array.add(castToNSObject(value)) + try array.add(StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) count += 1 } mutating func encode(_ value: UInt16) throws { - try array.add(castToNSObject(value)) + try array.add(StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) count += 1 } mutating func encode(_ value: UInt32) throws { - try array.add(castToNSObject(value)) + try array.add(StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) count += 1 } mutating func encode(_ value: UInt64) throws { - try array.add(castToNSObject(value)) + try array.add(StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) count += 1 } @@ -356,7 +354,7 @@ struct STPUnkeyedEncodingContainer: UnkeyedEncodingContainer, StripeEncodingCont if let seValue = value as? UnknownFieldsEncodable { seValue.applyUnknownFieldEncodingTransforms(userInfo: userInfo, codingPath: newPath) } - try array.add(castToNSObject(codingPath: newPath, value)) + try array.add(StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: newPath, value)) count += 1 } @@ -401,7 +399,7 @@ struct STPUnkeyedEncodingContainer: UnkeyedEncodingContainer, StripeEncodingCont } -struct STPSingleValueEncodingContainer: SingleValueEncodingContainer, StripeEncodingContainer { +struct STPSingleValueEncodingContainer: SingleValueEncodingContainer { var codingPath: [CodingKey] var encodingBlock: (NSObject) -> Void @@ -412,59 +410,59 @@ struct STPSingleValueEncodingContainer: SingleValueEncodingContainer, StripeEnco } mutating func encode(_ value: Bool) throws { - encodingBlock(try castToNSObject(value)) + encodingBlock(try StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) } mutating func encode(_ value: String) throws { - encodingBlock(try castToNSObject(value)) + encodingBlock(try StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) } mutating func encode(_ value: Double) throws { - encodingBlock(try castToNSObject(value)) + encodingBlock(try StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) } mutating func encode(_ value: Float) throws { - encodingBlock(try castToNSObject(value)) + encodingBlock(try StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) } mutating func encode(_ value: Int) throws { - encodingBlock(try castToNSObject(value)) + encodingBlock(try StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) } mutating func encode(_ value: Int8) throws { - encodingBlock(try castToNSObject(value)) + encodingBlock(try StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) } mutating func encode(_ value: Int16) throws { - encodingBlock(try castToNSObject(value)) + encodingBlock(try StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) } mutating func encode(_ value: Int32) throws { - encodingBlock(try castToNSObject(value)) + encodingBlock(try StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) } mutating func encode(_ value: Int64) throws { - encodingBlock(try castToNSObject(value)) + encodingBlock(try StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) } mutating func encode(_ value: UInt) throws { - encodingBlock(try castToNSObject(value)) + encodingBlock(try StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) } mutating func encode(_ value: UInt8) throws { - encodingBlock(try castToNSObject(value)) + encodingBlock(try StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) } mutating func encode(_ value: UInt16) throws { - encodingBlock(try castToNSObject(value)) + encodingBlock(try StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) } mutating func encode(_ value: UInt32) throws { - encodingBlock(try castToNSObject(value)) + encodingBlock(try StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) } mutating func encode(_ value: UInt64) throws { - encodingBlock(try castToNSObject(value)) + encodingBlock(try StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) } mutating func encode(_ value: T) throws where T: Encodable { @@ -475,19 +473,17 @@ struct STPSingleValueEncodingContainer: SingleValueEncodingContainer, StripeEnco if let seValue = value as? UnknownFieldsEncodable { seValue.applyUnknownFieldEncodingTransforms(userInfo: userInfo, codingPath: codingPath) } - encodingBlock(try castToNSObject(value)) - } -} - -protocol StripeEncodingContainer { - var userInfo: [CodingUserInfoKey: Any] { - get set + encodingBlock(try StripeEncodingUtils.castToNSObject(userInfo: userInfo, codingPath: codingPath, value)) } } -extension StripeEncodingContainer { - fileprivate func castToNSObject(codingPath: [CodingKey] = [], _ value: T) throws -> NSObject - where T: Encodable { +/// Utility for encoding Swift values to NSObject types compatible with NSJSONSerialization +enum StripeEncodingUtils { + static func castToNSObject( + userInfo: [CodingUserInfoKey: Any], + codingPath: [CodingKey] = [], + _ value: T + ) throws -> NSObject where T: Encodable { switch value { case let n as Bool: return n as NSObject diff --git a/StripeCore/StripeCore/Source/Coder/UnknownFields.swift b/StripeCore/StripeCore/Source/Coder/UnknownFields.swift index 281bfbe4456a..0dc1759a7670 100644 --- a/StripeCore/StripeCore/Source/Coder/UnknownFields.swift +++ b/StripeCore/StripeCore/Source/Coder/UnknownFields.swift @@ -77,7 +77,8 @@ extension UnknownFieldsDecodable { // When the object is later re-encoded, the additionalParameters will // be re-added to the encoded JSON. if var encodableValue = object as? UnknownFieldsEncodable { - let encodedDictionary = try encodableValue.encodeJSONDictionary( + let encodedDictionary = try StripeJSONEncoder().encodeJSONDictionary( + encodableValue, includingUnknownFields: false ) encodableValue.additionalParameters = jsonDictionary.subtracting(encodedDictionary) diff --git a/StripeCore/StripeCore/Source/Connections Bindings/LinkMode.swift b/StripeCore/StripeCore/Source/Connections Bindings/LinkMode.swift index a4e567e10042..92f08997fe5f 100644 --- a/StripeCore/StripeCore/Source/Connections Bindings/LinkMode.swift +++ b/StripeCore/StripeCore/Source/Connections Bindings/LinkMode.swift @@ -7,7 +7,7 @@ import Foundation -@_spi(STP) public enum LinkMode: String { +@_spi(STP) @frozen public enum LinkMode: String { case linkPaymentMethod = "LINK_PAYMENT_METHOD" case passthrough = "PASSTHROUGH" case linkCardBrand = "LINK_CARD_BRAND" diff --git a/StripeCore/StripeCore/Source/Helpers/STPError.swift b/StripeCore/StripeCore/Source/Helpers/STPError.swift index a4bf66abc3d0..054afad08003 100644 --- a/StripeCore/StripeCore/Source/Helpers/STPError.swift +++ b/StripeCore/StripeCore/Source/Helpers/STPError.swift @@ -297,7 +297,7 @@ extension NSError { /// /// These values will come back in the error `userInfo` dictionary /// under the `STPCardErrorCodeKey` key. -public enum STPCardErrorCode: String { +@frozen public enum STPCardErrorCode: String { /// The card number is not a valid credit card number. case invalidNumber = "com.stripe.lib:InvalidNumber" /// The card has an invalid expiration month. diff --git a/StripeCore/StripeCore/Source/Helpers/STPNumericStringValidator.swift b/StripeCore/StripeCore/Source/Helpers/STPNumericStringValidator.swift index 6f84c71c2278..6197453c3903 100644 --- a/StripeCore/StripeCore/Source/Helpers/STPNumericStringValidator.swift +++ b/StripeCore/StripeCore/Source/Helpers/STPNumericStringValidator.swift @@ -8,7 +8,7 @@ import Foundation -@_spi(STP) public enum STPTextValidationState: Int { +@_spi(STP) @frozen public enum STPTextValidationState: Int { case empty case incomplete case complete diff --git a/StripeCore/StripeCoreTests/API Bindings/StripeCodableTest.swift b/StripeCore/StripeCoreTests/API Bindings/StripeCodableTest.swift index b03b035f163f..e3abf8eb94b6 100644 --- a/StripeCore/StripeCoreTests/API Bindings/StripeCodableTest.swift +++ b/StripeCore/StripeCoreTests/API Bindings/StripeCodableTest.swift @@ -71,7 +71,7 @@ class StripeAPIRequestTest: APIStubbedTestCase { completion: @escaping ([String: Any], Result) -> Void ) { let e = expectation(description: "Request completed") - let encodedDict = try! codable.encodeJSONDictionary() + let encodedDict = try! StripeJSONEncoder().encodeJSONDictionary(codable) let encodedData = try? JSONSerialization.data(withJSONObject: encodedDict, options: []) let apiClient = stubbedAPIClient() @@ -163,7 +163,7 @@ class StripeAPIRequestTest: APIStubbedTestCase { resultObject.nested!.deeplyNested!.deeplyNestedProperty, codable.nested!.deeplyNested!.deeplyNestedProperty ) - let newDictionary = try! resultObject.encodeJSONDictionary() as NSDictionary + let newDictionary = try! StripeJSONEncoder().encodeJSONDictionary(resultObject) as NSDictionary XCTAssert(newDictionary.isEqual(to: codableDict)) } } @@ -193,7 +193,7 @@ class StripeAPIRequestTest: APIStubbedTestCase { resultObject.nested!.deeplyNested!.deeplyNestedProperty, codable.nested!.deeplyNested!.deeplyNestedProperty ) - let newDictionary = try! resultObject.encodeJSONDictionary() as NSDictionary + let newDictionary = try! StripeJSONEncoder().encodeJSONDictionary(resultObject) as NSDictionary XCTAssert(newDictionary.isEqual(to: codableDict)) XCTAssertEqual( resultObject.nested!.nestedProperty, diff --git a/StripeFinancialConnections/StripeFinancialConnections/Source/API Bindings/FinancialConnectionsAsyncAPIClient.swift b/StripeFinancialConnections/StripeFinancialConnections/Source/API Bindings/FinancialConnectionsAsyncAPIClient.swift index b2734d3ebc4a..2dbae9e3468f 100644 --- a/StripeFinancialConnections/StripeFinancialConnections/Source/API Bindings/FinancialConnectionsAsyncAPIClient.swift +++ b/StripeFinancialConnections/StripeFinancialConnections/Source/API Bindings/FinancialConnectionsAsyncAPIClient.swift @@ -894,7 +894,7 @@ extension FinancialConnectionsAsyncAPIClient { } if let clientAttributionMetadata { - parameters["client_attribution_metadata"] = try clientAttributionMetadata.encodeJSONDictionary() + parameters["client_attribution_metadata"] = try StripeJSONEncoder().encodeJSONDictionary(clientAttributionMetadata) } return try await post(endpoint: .paymentDetails, parameters: parameters) @@ -932,7 +932,7 @@ extension FinancialConnectionsAsyncAPIClient { } if let clientAttributionMetadata { - parameters["client_attribution_metadata"] = try clientAttributionMetadata.encodeJSONDictionary() + parameters["client_attribution_metadata"] = try StripeJSONEncoder().encodeJSONDictionary(clientAttributionMetadata) } let parametersWithFraudDetection = await updateAndApplyFraudDetection(to: parameters) @@ -966,7 +966,7 @@ extension FinancialConnectionsAsyncAPIClient { } if let clientAttributionMetadata { - parameters["client_attribution_metadata"] = try clientAttributionMetadata.encodeJSONDictionary() + parameters["client_attribution_metadata"] = try StripeJSONEncoder().encodeJSONDictionary(clientAttributionMetadata) } let parametersWithFraudDetection = await updateAndApplyFraudDetection(to: parameters) diff --git a/StripeIdentity/StripeIdentityTests/Unit/API Bindings/IdentityAPIClientTest.swift b/StripeIdentity/StripeIdentityTests/Unit/API Bindings/IdentityAPIClientTest.swift index 5330ee908035..5eed135f800d 100644 --- a/StripeIdentity/StripeIdentityTests/Unit/API Bindings/IdentityAPIClientTest.swift +++ b/StripeIdentity/StripeIdentityTests/Unit/API Bindings/IdentityAPIClientTest.swift @@ -77,7 +77,7 @@ final class IdentityAPIClientTest: APIStubbedTestCase { func testUpdateVerificationPageData() throws { let mockVerificationData = VerificationPageDataUpdateMock.default let encodedMockVerificationData = URLEncoder.queryString( - from: try mockVerificationData.encodeJSONDictionary() + from: try StripeJSONEncoder().encodeJSONDictionary(mockVerificationData) ) let mockVerificationPageData = VerificationPageDataMock.response200 diff --git a/StripeIdentity/StripeIdentityTests/Unit/API Bindings/TruncatedDecimalTest.swift b/StripeIdentity/StripeIdentityTests/Unit/API Bindings/TruncatedDecimalTest.swift index ab665f0f234d..2fb1ab2eca73 100644 --- a/StripeIdentity/StripeIdentityTests/Unit/API Bindings/TruncatedDecimalTest.swift +++ b/StripeIdentity/StripeIdentityTests/Unit/API Bindings/TruncatedDecimalTest.swift @@ -42,7 +42,7 @@ extension TruncatedDecimalTest { // wrapped in quotations or represented as a nested container let container = Container(number: truncatedDecimal) - let jsonDict = try container.encodeJSONDictionary() + let jsonDict = try StripeJSONEncoder().encodeJSONDictionary(container) let queryString = URLEncoder.queryString(from: jsonDict) XCTAssertEqual( queryString, diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/LinkPaymentMethodType.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/LinkPaymentMethodType.swift index c2098ca584d1..ebc8fe4e56fb 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/LinkPaymentMethodType.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/LinkPaymentMethodType.swift @@ -7,7 +7,7 @@ import Foundation -@_spi(STP) public enum LinkPaymentMethodType: String, CaseIterable { +@_spi(STP) @frozen public enum LinkPaymentMethodType: String, CaseIterable { case card = "CARD" case bankAccount = "BANK_ACCOUNT" } diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/LinkRequestSurface.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/LinkRequestSurface.swift index 858e41c294d6..e8ea0c11956d 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/LinkRequestSurface.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/LinkRequestSurface.swift @@ -7,7 +7,7 @@ import Foundation -@_spi(STP) public enum LinkRequestSurface: String { +@_spi(STP) @frozen public enum LinkRequestSurface: String { /// Used for requests from the `StripePaymentSheet` SDK. case paymentElement = "ios_payment_element" /// Used for requests from the `StripeCryptoOnramp` SDK. diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/v1-elements-sessions/ExperimentData.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/v1-elements-sessions/ExperimentData.swift index 58f33fe8eed2..97c5336af199 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/v1-elements-sessions/ExperimentData.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/v1-elements-sessions/ExperimentData.swift @@ -7,7 +7,7 @@ import Foundation -@_spi(STP) public enum ExperimentGroup: String { +@_spi(STP) @frozen public enum ExperimentGroup: String { case control case treatment case holdback diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerAdapter/CustomerPaymentOption.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerAdapter/CustomerPaymentOption.swift index b90b9dc3ab66..1ac91281d08e 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerAdapter/CustomerPaymentOption.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerAdapter/CustomerPaymentOption.swift @@ -6,7 +6,7 @@ import Foundation /// A representation of a Payment Method option, used for persisting the user's default payment method. -public enum CustomerPaymentOption: Equatable { +@frozen public enum CustomerPaymentOption: Equatable { /// The user's default payment method is Apple Pay. /// This is not a specific Apple Pay card. Stripe will present an Apple Pay sheet to the user. case applePay diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerSheet/CustomerSheetError.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerSheet/CustomerSheetError.swift index e964ff64ddba..c143985f9948 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerSheet/CustomerSheetError.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerSheet/CustomerSheetError.swift @@ -7,7 +7,7 @@ import Foundation @_spi(STP) import StripeCore import StripePayments -public enum CustomerSheetError: Error { +@frozen public enum CustomerSheetError: Error { /// Error while fetching saved payment methods attached to a customer case errorFetchingSavedPaymentMethods(Error) /// Error if an unsupported payment method type is specified diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Elements/CardSection/HostedSurface.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Elements/CardSection/HostedSurface.swift index 8bf92f8db6a2..0f73dbd55117 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Elements/CardSection/HostedSurface.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Elements/CardSection/HostedSurface.swift @@ -9,7 +9,7 @@ import Foundation @_spi(STP) import StripeCore // Used to indicate if this card section is being used by either PaymentSheet or CustomerSheet -@_spi(STP) public enum HostedSurface { +@_spi(STP) @frozen public enum HostedSurface { case paymentSheet case customerSheet diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Elements/PaymentMethodElement/PaymentMethodElement.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Elements/PaymentMethodElement/PaymentMethodElement.swift index 574fb1b88ca0..c5f2d52b0fe9 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Elements/PaymentMethodElement/PaymentMethodElement.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Elements/PaymentMethodElement/PaymentMethodElement.swift @@ -24,9 +24,12 @@ protocol PaymentMethodElement: Element { func updateParams(params: IntentConfirmParams) -> IntentConfirmParams? } -extension PaymentMethodElement { - func clearTextFields() { - for element in getAllUnwrappedSubElements() { +// MARK: - PaymentMethodElement utilities +/// Utility methods for working with PaymentMethodElements +enum PaymentMethodElementUtils { + /// Clears all text fields within an element hierarchy + static func clearTextFields(in element: Element) { + for element in element.getAllUnwrappedSubElements() { if let element = element as? TextFieldElement { element.setText("") } else if let element = element as? CVCRecollectionElement { @@ -34,6 +37,18 @@ extension PaymentMethodElement { } } } + + /// Get the mandate text from an element hierarchy, if available + /// - Note: Assumes mandates are SimpleMandateElement + static func getMandateText(from element: Element) -> NSAttributedString? { + guard let mandateText = element.getAllUnwrappedSubElements() + .compactMap({ $0 as? SimpleMandateElement }) + .first?.mandateTextView.attributedText, + !mandateText.string.isEmpty else { + return nil + } + return mandateText + } } // MARK: - Default implementations diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElement+Internal.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElement+Internal.swift index eab734760034..9b6e18786062 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElement+Internal.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElement+Internal.swift @@ -601,7 +601,7 @@ extension EmbeddedPaymentElement { // However: When `rowSelectionBehavior` is `immediateAction` and `embeddedViewDisplaysMandateText` is `true` and the customer selects a PM that has no form but has a mandate, there's a problem. // We'd normally show the mandate in the embedded view, but `immediateAction` implies the merchant will immediately confirm or move the customer to a different screen before they can see or consent to the mandate. // We therefore show a form with the mandate text and proceed as normal as if it were any other PM with a form (customer can continue or confirm in the sheet). - let paymentMethodHasNoFormAndHasAMandate = form.collectsUserInput == false && form.getMandateText() != nil + let paymentMethodHasNoFormAndHasAMandate = form.collectsUserInput == false && PaymentMethodElementUtils.getMandateText(from: form) != nil if case .immediateAction = configuration.rowSelectionBehavior, configuration.embeddedViewDisplaysMandateText, diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/MandateTextProvider.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/MandateTextProvider.swift index d5229b829f98..fab27da73728 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/MandateTextProvider.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/MandateTextProvider.swift @@ -84,7 +84,7 @@ class VerticalListMandateProvider: MandateTextProvider { // If we get to this point, we didn't show the form, so return the mandate from the form if it exists // 🙋‍♂️ Note: assumes mandates are SimpleMandateElement! - return form.getMandateText() + return PaymentMethodElementUtils.getMandateText(from: form) } } } diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/New Payment Method Screen/AddPaymentMethodViewController.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/New Payment Method Screen/AddPaymentMethodViewController.swift index ca2f96519ee8..f5ac3419293c 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/New Payment Method Screen/AddPaymentMethodViewController.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/New Payment Method Screen/AddPaymentMethodViewController.swift @@ -206,7 +206,7 @@ class AddPaymentMethodViewController: UIViewController { } func clearTextFields() { - paymentMethodFormElement.clearTextFields() + PaymentMethodElementUtils.clearTextFields(in: paymentMethodFormElement) } } diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetError.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetError.swift index 9ba0b987270b..600d31c86cc2 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetError.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetError.swift @@ -14,7 +14,7 @@ import StripePayments /// /// Most errors do not originate from PaymentSheet itself; instead, they come from the Stripe API /// or other SDK components like STPPaymentHandler, PassKit (Apple Pay), etc. -public enum PaymentSheetError: Error, LocalizedError { +@frozen public enum PaymentSheetError: Error, LocalizedError { /// An unknown error. case unknown(debugDescription: String) diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Saved Payment Method Screen/SavedPaymentOptionsViewController.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Saved Payment Method Screen/SavedPaymentOptionsViewController.swift index aa4312bd2724..ffdbf87cea6e 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Saved Payment Method Screen/SavedPaymentOptionsViewController.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Saved Payment Method Screen/SavedPaymentOptionsViewController.swift @@ -574,7 +574,7 @@ extension SavedPaymentOptionsViewController: UICollectionViewDataSource, UIColle ) } updateMandateView() - cvcFormElement.clearTextFields() + PaymentMethodElementUtils.clearTextFields(in: cvcFormElement) updateFormElement() delegate?.didUpdateSelection(viewController: self, paymentMethodSelection: viewModel) } diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/ViewControllers/PaymentMethodFormViewController.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/ViewControllers/PaymentMethodFormViewController.swift index b0214d5308ee..b316398e0449 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/ViewControllers/PaymentMethodFormViewController.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/ViewControllers/PaymentMethodFormViewController.swift @@ -172,7 +172,7 @@ class PaymentMethodFormViewController: UIViewController { // MARK: - Helpers func clearTextFields() { - form.clearTextFields() + PaymentMethodElementUtils.clearTextFields(in: form) } /// Sets up the autocomplete button callback for any AddressSectionElement in the form diff --git a/StripePayments/StripePayments/Source/API Bindings/Models/PaymentIntents/STPPaymentIntentEnums.swift b/StripePayments/StripePayments/Source/API Bindings/Models/PaymentIntents/STPPaymentIntentEnums.swift index 24bf4d7ecc18..5e3fdbbc8db8 100644 --- a/StripePayments/StripePayments/Source/API Bindings/Models/PaymentIntents/STPPaymentIntentEnums.swift +++ b/StripePayments/StripePayments/Source/API Bindings/Models/PaymentIntents/STPPaymentIntentEnums.swift @@ -9,7 +9,7 @@ import Foundation /// Status types for an STPPaymentIntent -@objc public enum STPPaymentIntentStatus: Int { +@objc @frozen public enum STPPaymentIntentStatus: Int { /// Unknown status case unknown /// This PaymentIntent requires a PaymentMethod or Source @@ -32,7 +32,7 @@ import Foundation /// Indicates how you intend to use the payment method that your customer provides after the current payment completes. /// If applicable, additional authentication may be performed to comply with regional legislation or network rules required to enable the usage of the same payment method for additional payments. /// - seealso: https://stripe.com/docs/api/payment_intents/object#payment_intent_object-setup_future_usage -@objc public enum STPPaymentIntentSetupFutureUsage: Int { +@objc @frozen public enum STPPaymentIntentSetupFutureUsage: Int { /// Unknown value. Update your SDK, or use `allResponseFields` for custom handling. case unknown /// No value was provided. @@ -72,7 +72,7 @@ import Foundation // MARK: - Deprecated /// Types of Actions from a `STPPaymentIntent`, when the payment intent /// status is `STPPaymentIntentStatusRequiresAction`. -@objc public enum STPPaymentIntentActionType: Int { +@objc @frozen public enum STPPaymentIntentActionType: Int { /// This is an unknown action, that's been added since the SDK /// was last updated. /// Update your SDK, or use the `nextAction.allResponseFields` diff --git a/StripePayments/StripePayments/Source/API Bindings/Models/PaymentMethods/STPPaymentMethodAllowRedisplay.swift b/StripePayments/StripePayments/Source/API Bindings/Models/PaymentMethods/STPPaymentMethodAllowRedisplay.swift index 8150d8d1eb17..165b48f2be22 100644 --- a/StripePayments/StripePayments/Source/API Bindings/Models/PaymentMethods/STPPaymentMethodAllowRedisplay.swift +++ b/StripePayments/StripePayments/Source/API Bindings/Models/PaymentMethods/STPPaymentMethodAllowRedisplay.swift @@ -6,7 +6,7 @@ import Foundation /// Values for STPPaymentMethodAllowRedisplay -@objc public enum STPPaymentMethodAllowRedisplay: Int { +@objc @frozen public enum STPPaymentMethodAllowRedisplay: Int { /// This is the default value for payment methods where allow_redisplay wasn’t set. case unspecified diff --git a/StripePayments/StripePayments/Source/API Bindings/Models/STPCardBrand.swift b/StripePayments/StripePayments/Source/API Bindings/Models/STPCardBrand.swift index c5c87927cc99..3a9bce7cc582 100644 --- a/StripePayments/StripePayments/Source/API Bindings/Models/STPCardBrand.swift +++ b/StripePayments/StripePayments/Source/API Bindings/Models/STPCardBrand.swift @@ -9,7 +9,7 @@ import Foundation /// The various card brands to which a payment card can belong. -@objc public enum STPCardBrand: Int { +@objc @frozen public enum STPCardBrand: Int { /// Visa card case visa /// American Express card diff --git a/StripePayments/StripePayments/Source/API Bindings/Models/STPFPXBankBrand.swift b/StripePayments/StripePayments/Source/API Bindings/Models/STPFPXBankBrand.swift index b5d23533639d..7cf41db51332 100644 --- a/StripePayments/StripePayments/Source/API Bindings/Models/STPFPXBankBrand.swift +++ b/StripePayments/StripePayments/Source/API Bindings/Models/STPFPXBankBrand.swift @@ -9,7 +9,7 @@ import Foundation /// The various bank brands available for FPX payments. -@objc public enum STPFPXBankBrand: Int { +@objc @frozen public enum STPFPXBankBrand: Int { /// Maybank2U case maybank2U /// CIMB Clicks diff --git a/StripePayments/StripePayments/Source/API Bindings/Models/STPFile.swift b/StripePayments/StripePayments/Source/API Bindings/Models/STPFile.swift index d75997b3c7f2..94bcacfb78fe 100644 --- a/StripePayments/StripePayments/Source/API Bindings/Models/STPFile.swift +++ b/StripePayments/StripePayments/Source/API Bindings/Models/STPFile.swift @@ -12,7 +12,7 @@ import Foundation /// The purpose of the uploaded file. /// - seealso: https://stripe.com/docs/file-upload @objc -public enum STPFilePurpose: Int { +@frozen public enum STPFilePurpose: Int { // NOTE: If adding cases here, also add to `StripeFile.Purpose` or they will // not be encoded/decoded to/from the server. diff --git a/StripePayments/StripePayments/Source/API Bindings/Models/STPToken.swift b/StripePayments/StripePayments/Source/API Bindings/Models/STPToken.swift index b34454b319d0..784b5e3f662f 100644 --- a/StripePayments/StripePayments/Source/API Bindings/Models/STPToken.swift +++ b/StripePayments/StripePayments/Source/API Bindings/Models/STPToken.swift @@ -10,7 +10,7 @@ import Foundation /// Possible Token types @objc -public enum STPTokenType: Int { +@frozen public enum STPTokenType: Int { /// Account token type case account = 0 /// Bank account token type diff --git a/StripePayments/StripePayments/Source/API Bindings/Models/SetupIntents/STPSetupIntentEnums.swift b/StripePayments/StripePayments/Source/API Bindings/Models/SetupIntents/STPSetupIntentEnums.swift index 012fd065bdb8..0c6a745a1993 100644 --- a/StripePayments/StripePayments/Source/API Bindings/Models/SetupIntents/STPSetupIntentEnums.swift +++ b/StripePayments/StripePayments/Source/API Bindings/Models/SetupIntents/STPSetupIntentEnums.swift @@ -9,7 +9,7 @@ import Foundation /// Status types for an STPSetupIntent -@objc public enum STPSetupIntentStatus: Int { +@objc @frozen public enum STPSetupIntentStatus: Int { /// Unknown status case unknown /// This SetupIntent requires a PaymentMethod @@ -29,7 +29,7 @@ import Foundation /// Indicates how the payment method is intended to be used in the future. /// - seealso: https://stripe.com/docs/api/setup_intents/create#create_setup_intent-usage -@objc public enum STPSetupIntentUsage: Int { +@objc @frozen public enum STPSetupIntentUsage: Int { /// Unknown value. Update your SDK, or use `allResponseFields` for custom handling. case unknown /// No value was provided. diff --git a/StripePayments/StripePayments/Source/API Bindings/Models/Sources/STPSourceEnums.swift b/StripePayments/StripePayments/Source/API Bindings/Models/Sources/STPSourceEnums.swift index 3726eb4215fd..620f1c95eabe 100644 --- a/StripePayments/StripePayments/Source/API Bindings/Models/Sources/STPSourceEnums.swift +++ b/StripePayments/StripePayments/Source/API Bindings/Models/Sources/STPSourceEnums.swift @@ -9,7 +9,7 @@ import Foundation /// Usage types for a Source -@objc public enum STPSourceUsage: Int { +@objc @frozen public enum STPSourceUsage: Int { /// The source can be reused. case reusable /// The source can only be used once. @@ -19,7 +19,7 @@ import Foundation } /// Status types for a Source -@objc public enum STPSourceStatus: Int { +@objc @frozen public enum STPSourceStatus: Int { /// The source has been created and is awaiting customer action. case pending /// The source is ready to use. The customer action has been completed or the @@ -40,7 +40,7 @@ import Foundation /// Types for a Source /// - seealso: https://stripe.com/docs/sources -@objc public enum STPSourceType: Int { +@objc @frozen public enum STPSourceType: Int { /// A card source. - seealso: https://stripe.com/docs/sources/cards case card /// An unknown type of source. diff --git a/StripePayments/StripePayments/Source/API Bindings/Models/Sources/Types/STPCard.swift b/StripePayments/StripePayments/Source/API Bindings/Models/Sources/Types/STPCard.swift index 34b96850153b..78074f703cb2 100644 --- a/StripePayments/StripePayments/Source/API Bindings/Models/Sources/Types/STPCard.swift +++ b/StripePayments/StripePayments/Source/API Bindings/Models/Sources/Types/STPCard.swift @@ -11,7 +11,7 @@ import UIKit /// The various funding sources for a payment card. @objc -public enum STPCardFundingType: Int { +@frozen public enum STPCardFundingType: Int { /// Debit card funding case debit /// Credit card funding diff --git a/StripePayments/StripePayments/Source/Internal/Categories/STPAPIClient+PaymentsCore.swift b/StripePayments/StripePayments/Source/Internal/Categories/STPAPIClient+PaymentsCore.swift index fb727c029850..48d3a7b1a147 100644 --- a/StripePayments/StripePayments/Source/Internal/Categories/STPAPIClient+PaymentsCore.swift +++ b/StripePayments/StripePayments/Source/Internal/Categories/STPAPIClient+PaymentsCore.swift @@ -31,7 +31,7 @@ extension STPAPIClient { ) var newParams = params do { - newParams["client_attribution_metadata"] = try clientAttributionMetadata.encodeJSONDictionary() + newParams["client_attribution_metadata"] = try StripeJSONEncoder().encodeJSONDictionary(clientAttributionMetadata) } catch { stpAssertionFailure("Could not encode clientAttributionMetadata to JSON: \(error)") } diff --git a/StripePayments/StripePayments/Source/PaymentHandler/STPPaymentHandler.swift b/StripePayments/StripePayments/Source/PaymentHandler/STPPaymentHandler.swift index 2f2c33cd6351..daaccd1ab411 100644 --- a/StripePayments/StripePayments/Source/PaymentHandler/STPPaymentHandler.swift +++ b/StripePayments/StripePayments/Source/PaymentHandler/STPPaymentHandler.swift @@ -17,7 +17,7 @@ import Stripe3DS2 #endif /// `STPPaymentHandlerActionStatus` represents the possible outcomes of requesting an action by `STPPaymentHandler`. An action could be confirming and/or handling the next action for a PaymentIntent. -@objc public enum STPPaymentHandlerActionStatus: Int { +@objc @frozen public enum STPPaymentHandlerActionStatus: Int { /// The action succeeded. case succeeded /// The action was cancelled by the cardholder/user. @@ -27,7 +27,7 @@ import Stripe3DS2 } /// Error codes generated by `STPPaymentHandler` -@objc public enum STPPaymentHandlerErrorCode: Int { +@objc @frozen public enum STPPaymentHandlerErrorCode: Int { /// Indicates that the action requires an authentication method not recognized or supported by the SDK. @objc(STPPaymentHandlerUnsupportedAuthenticationErrorCode) case unsupportedAuthenticationErrorCode