diff --git a/Sources/StripeKit/Core Resources/Customer Session/Components.swift b/Sources/StripeKit/Core Resources/Customer Session/Components.swift new file mode 100644 index 0000000..3b5d13c --- /dev/null +++ b/Sources/StripeKit/Core Resources/Customer Session/Components.swift @@ -0,0 +1,87 @@ +// +// Component.swift +// stripe-kit +// +// Created by Anatol Mayen on 11.11.24. +// + +/// This hash defines which component is enabled and the features it supports. +public struct Components: Codable { + + public enum ComponentsType { + case buyButton + case payementElement + case pricingTable + } + + /// Configuration for buy button. + public var buyButton: ComponentEnabled + + /// Configuration for the Payment Element. + public var paymentElement: PaymentComponentEnabled + + /// Configuration for the pricing table. + public var pricingTable: ComponentEnabled + + init(enable type: ComponentsType) { + + self.buyButton = ComponentEnabled(type == .buyButton) + self.paymentElement = PaymentComponentEnabled(type == .payementElement) + self.pricingTable = ComponentEnabled(type == .pricingTable) + } +} + +public struct ComponentEnabled: Codable { + + public var enabled: Bool + + init(_ enabled: Bool) { + self.enabled = enabled + } +} + +/// Configuration for the Payment Element. +public struct PaymentComponentEnabled: Codable { + + /// Whether the Payment Element is enabled. + public var enabled: Bool + + /// This hash defines whether the Payment Element supports certain features. + public var features: PaymentFeatures? + + init(_ enabled: Bool, features: PaymentFeatures? = nil) { + self.enabled = enabled + self.features = features + } +} + +/// This hash defines whether the Payment Element supports certain features. +public struct PaymentFeatures: Codable { + + /// A list of allow_redisplay values that controls which saved payment methods the Payment Element displays by filtering to only show payment methods with an allow_redisplay value that is present in this list. + /// If not specified, defaults to [“always”]. In order to display all saved payment methods, specify [“always”, “limited”, “unspecified”]. + /// Possible values are: `always`, `limited` and `unspecified` + public var paymentMethodAllowRedisplayFilters: [String] + + /// Controls whether or not the Payment Element shows saved payment methods. This parameter defaults to disabled. + /// Possible values are: `disabled` and `enabled` + public var paymentMethodRedisplay: String + + /// Determines the max number of saved payment methods for the Payment Element to display. This parameter defaults to `3`. + public var paymentMethodRedisplayLimit: Int? + + /// Controls whether the Payment Element displays the option to remove a saved payment method. This parameter defaults to `disabled`. + /// Allowing buyers to remove their saved payment methods impacts subscriptions that depend on that payment method. Removing the payment method detaches the `customer` [object](https://docs.stripe.com/api/payment_methods/object#payment_method_object-customer) from that [PaymentMethod](https://docs.stripe.com/api/payment_methods). + /// Possible values: `enabled` and `disabled` + public var paymentMethodRemove: String + + /// Controls whether the Payment Element displays a checkbox offering to save a new payment method. This parameter defaults to `disabled`. + /// If a customer checks the box, the `allow_redisplay` value on the PaymentMethod is set to `always` at confirmation time. For PaymentIntents, the `setup_future_usage` value is also set to the value defined in `payment_method_save_usage`. + /// Possible values: `enabled` and `disabled` + public var paymentMethodSave: String + + /// When using PaymentIntents and the customer checks the save checkbox, this field determines the `setup_future_usage` value used to confirm the PaymentIntent. + /// When using SetupIntents, directly configure the usage value on SetupIntent creation. + /// Possible values: `off_session` and `on_session` + public var paymentMethodSaveUsage: String? +} diff --git a/Sources/StripeKit/Core Resources/Customer Session/CustomerSession.swift b/Sources/StripeKit/Core Resources/Customer Session/CustomerSession.swift new file mode 100644 index 0000000..407227f --- /dev/null +++ b/Sources/StripeKit/Core Resources/Customer Session/CustomerSession.swift @@ -0,0 +1,46 @@ +// +// CustomerSession.swift +// stripe-kit +// +// Created by Anatol Mayen on 11.11.24. +// + +import Foundation + +/// The [Customer Session Object](https://docs.stripe.com/api/customer_sessions/object) +public struct CustomerSession: Codable { + + /// The client secret of this Customer Session. Used on the client to set up secure access to the given customer. + /// The client secret can be used to provide access to customer from your frontend. It should not be stored, logged, or exposed to anyone other than the relevant customer. + /// Make sure that you have TLS enabled on any page that includes the client secret. + public var clientSecret: String + + /// This hash defines which component is enabled and the features it supports. + public var components: Components + + /// The Customer the Customer Session was created for. + @Expandable public var customer: String? + + /// The timestamp at which this Customer Session will expire. + public var expiresAt: Date? + + /// String representing the object’s type. Objects of the same type share the same value. + public var object: String + + /// Time at which the object was created. Measured in seconds since the Unix epoch. + public var created: Date + + /// Has the value `true` if the object exists in live mode or the value `false` if the object exists in test mode. + public var livemode: Bool + + + init(clientSecret: String, components: Components, customer: String? = nil, expiresAt: Date? = nil, object: String, created: Date, livemode: Bool) { + self.clientSecret = clientSecret + self.components = components + self._customer = Expandable(id: customer) + self.expiresAt = expiresAt + self.object = object + self.created = created + self.livemode = livemode + } +} diff --git a/Sources/StripeKit/Core Resources/Customer Session/CustomerSessionRoutes.swift b/Sources/StripeKit/Core Resources/Customer Session/CustomerSessionRoutes.swift new file mode 100644 index 0000000..44610d7 --- /dev/null +++ b/Sources/StripeKit/Core Resources/Customer Session/CustomerSessionRoutes.swift @@ -0,0 +1,44 @@ +// +// CustomerSessionRoutes.swift +// stripe-kit +// +// Created by Anatol Mayen on 11.11.24. +// + + +import NIO +import NIOHTTP1 + +public protocol CustomerSessionRoutes: StripeAPIRoute { + + func create(enable type: Components.ComponentsType, customer: String, expand: [String]?) async throws -> CustomerSession +} + +public struct StripeCustomerSessionRoutes: CustomerSessionRoutes { + + public var headers: HTTPHeaders = [:] + + private let apiHandler: StripeAPIHandler + private let customerSessions = APIBase + APIVersion + "customer_sessions" + + init(apiHandler: StripeAPIHandler) { + self.apiHandler = apiHandler + } + + public func create(enable type: Components.ComponentsType, customer: String, expand: [String]? = nil) async throws -> CustomerSession { + + var body = [String: Any]() + let components = Components(enable: type) + + body["customer"] = customer + body["components[buy_button][enabled]"] = components.buyButton.enabled + body["components[payment_element][enabled]"] = components.paymentElement.enabled + body["components[pricing_table][enabled]"] = components.pricingTable.enabled + + if let expand { + body["expand"] = expand + } + + return try await apiHandler.send(method: .POST, path: customerSessions, body: .string(body.queryParameters), headers: headers) + } +} diff --git a/Sources/StripeKit/StripeClient.swift b/Sources/StripeKit/StripeClient.swift index e71c3d7..f47edbe 100644 --- a/Sources/StripeKit/StripeClient.swift +++ b/Sources/StripeKit/StripeClient.swift @@ -14,6 +14,7 @@ public final class StripeClient { public var balanceTransactions: BalanceTransactionRoutes public var charges: ChargeRoutes public var customers: CustomerRoutes + public var customerSessions: CustomerSessionRoutes public var disputes: DisputeRoutes public var events: EventRoutes public var files: FileRoutes @@ -132,6 +133,7 @@ public final class StripeClient { balanceTransactions = StripeBalanceTransactionRoutes(apiHandler: handler) charges = StripeChargeRoutes(apiHandler: handler) customers = StripeCustomerRoutes(apiHandler: handler) + customerSessions = StripeCustomerSessionRoutes(apiHandler: handler) disputes = StripeDisputeRoutes(apiHandler: handler) events = StripeEventRoutes(apiHandler: handler) files = StripeFileRoutes(apiHandler: handler)