-
Notifications
You must be signed in to change notification settings - Fork 997
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add initial embedded API and change spi private beta name
- Loading branch information
1 parent
00c3032
commit af5268f
Showing
9 changed files
with
305 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
107 changes: 107 additions & 0 deletions
107
...PaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElement.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
// | ||
// EmbeddedPaymentElement.swift | ||
// StripePaymentSheet | ||
// | ||
// Created by Yuki Tokuhiro on 9/25/24. | ||
// | ||
|
||
@_spi(STP) import StripeCore | ||
@_spi(STP) import StripePaymentsUI | ||
@_spi(STP) import StripeUICore | ||
import UIKit | ||
|
||
/// An object that manages a view that displays payment methods and completes a checkout. | ||
@_spi(EmbeddedPaymentElementPrivateBeta) | ||
public class EmbeddedPaymentElement { | ||
|
||
/// A view that displays payment methods. It can present a sheet to collect more details or display saved payment methods. | ||
public let view: UIView | ||
|
||
/// A view controller to present on. | ||
public var presentingViewController: UIViewController? | ||
|
||
/// See `EmbeddedPaymentElementDelegate`. | ||
public weak var delegate: EmbeddedPaymentElementDelegate? | ||
|
||
public struct PaymentOptionDisplayData { | ||
/// An image representing a payment method; e.g. the Apple Pay logo or a VISA logo | ||
public let image: UIImage | ||
/// A user facing string representing the payment method; e.g. "Apple Pay" or "····4242" for a card | ||
public let label: String | ||
/// The billing details associated with the customer's desired payment method | ||
public let billingDetails: PaymentSheet.BillingDetails? | ||
/// A string representation of the customer's desired payment method | ||
/// - If this is a Stripe payment method, see https://stripe.com/docs/api/payment_methods/object#payment_method_object-type for possible values. | ||
/// - If this is an external payment method, see https://stripe.com/docs/payments/external-payment-methods?platform=ios#available-external-payment-methods for possible values. | ||
/// - If this is Apple Pay, the value is "apple_pay" | ||
public let paymentMethodType: String | ||
/// If you set `configuration.hidesMandateText = true`, this text must be displayed to the customer near your “Buy” button to comply with regulations. | ||
public let mandateText: NSAttributedString | ||
} | ||
|
||
/// The customer's currently selected payment option. | ||
public var paymentOption: PaymentOptionDisplayData? { return nil /* computed */ } | ||
|
||
/// An asynchronous failable initializer | ||
/// This loads the Customer's payment methods, their default payment method, etc. | ||
/// - Parameter intentConfiguration: Information about the PaymentIntent or SetupIntent you will create later to complete the checkout. | ||
/// - Parameter configuration: Configuration for the PaymentSheet. e.g. your business name, customer details, etc. | ||
/// - Returns: A valid EmbeddedPaymentElement instance | ||
/// - Throws: An error if loading failed. | ||
public static func create( | ||
intentConfiguration: IntentConfiguration, | ||
configuration: Configuration | ||
) async throws -> EmbeddedPaymentElement { | ||
let dummyView = await EmbeddedPaymentMethodsView( | ||
savedPaymentMethod: nil, | ||
appearance: .default, | ||
shouldShowApplePay: true, | ||
shouldShowLink: true | ||
) | ||
return .init(view: dummyView) | ||
} | ||
|
||
public enum UpdateResult { | ||
case succeeded | ||
case canceled | ||
case failed(error: Error) | ||
} | ||
/// Call this method when the IntentConfiguration values you used to initialize `EmbeddedPaymentElement` (amount, currency, etc.) change. | ||
/// This ensures the appropriate payment methods are displayed, collect the right fields, etc. | ||
/// - Parameter intentConfiguration: An updated IntentConfiguration. | ||
/// - Returns: The result of the update. Any calls made to `update` before this call that are still in progress will return a `.canceled` result. | ||
/// - Note: Upon completion, `paymentOption` may become nil if it's no longer available. | ||
public func update( | ||
intentConfiguration: IntentConfiguration | ||
) async -> UpdateResult { | ||
return .canceled | ||
} | ||
|
||
/// - Returns: The result of the payment after any presented view controllers are dismissed. | ||
public func confirm() async -> EmbeddedPaymentElementResult { | ||
return .canceled | ||
} | ||
|
||
// MARK: - Internal | ||
|
||
private init(view: UIView, delegate: EmbeddedPaymentElementDelegate? = nil) { | ||
self.view = view | ||
self.delegate = delegate | ||
} | ||
} | ||
|
||
// MARK: - Typealiases | ||
|
||
@_spi(STP) public typealias EmbeddedPaymentElementResult = PaymentSheetResult | ||
extension EmbeddedPaymentElement { | ||
public typealias IntentConfiguration = PaymentSheet.IntentConfiguration | ||
public typealias UserInterfaceStyle = PaymentSheet.UserInterfaceStyle | ||
public typealias SavePaymentMethodOptInBehavior = PaymentSheet.SavePaymentMethodOptInBehavior | ||
public typealias ApplePayConfiguration = PaymentSheet.ApplePayConfiguration | ||
public typealias CustomerConfiguration = PaymentSheet.CustomerConfiguration | ||
public typealias BillingDetails = PaymentSheet.BillingDetails | ||
public typealias Address = PaymentSheet.Address | ||
public typealias BillingDetailsCollectionConfiguration = PaymentSheet.BillingDetailsCollectionConfiguration | ||
public typealias ExternalPaymentMethodConfiguration = PaymentSheet.ExternalPaymentMethodConfiguration | ||
} | ||
|
150 changes: 150 additions & 0 deletions
150
...StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
// | ||
// EmbeddedPaymentElementConfiguration.swift | ||
// StripePaymentSheet | ||
// | ||
// Created by Yuki Tokuhiro on 9/25/24. | ||
// | ||
|
||
import UIKit | ||
@_spi(STP) import StripeCore | ||
|
||
extension EmbeddedPaymentElement { | ||
public struct Configuration { | ||
/// If true, allows payment methods that do not move money at the end of the checkout. Defaults to false. | ||
/// - Description: Some payment methods can't guarantee you will receive funds from your customer at the end of the checkout because they take time to settle (eg. most bank debits, like SEPA or ACH) or require customer action to complete (e.g. OXXO, Konbini, Boleto). If this is set to true, make sure your integration listens to webhooks for notifications on whether a payment has succeeded or not. | ||
/// - Seealso: https://stripe.com/docs/payments/payment-methods#payment-notification | ||
public var allowsDelayedPaymentMethods: Bool = false | ||
|
||
/// If `true`, allows payment methods that require a shipping address, like Afterpay and Affirm. Defaults to `false`. | ||
/// Set this to `true` if you collect shipping addresses and set `Configuration.shippingDetails` or set `shipping` details directly on the PaymentIntent. | ||
/// - Note: PaymentSheet considers this property `true` and allows payment methods that require a shipping address if `shipping` details are present on the PaymentIntent when PaymentSheet loads. | ||
public var allowsPaymentMethodsRequiringShippingAddress: Bool = false | ||
|
||
/// The APIClient instance used to make requests to Stripe | ||
public var apiClient: STPAPIClient = STPAPIClient.shared | ||
|
||
/// Configuration related to Apple Pay | ||
/// If set, PaymentSheet displays Apple Pay as a payment option | ||
public var applePay: ApplePayConfiguration? | ||
|
||
/// The color of the Buy or Add button. Defaults to `.systemBlue` when `nil`. | ||
public var primaryButtonColor: UIColor? { | ||
get { | ||
return appearance.primaryButton.backgroundColor | ||
} | ||
|
||
set { | ||
appearance.primaryButton.backgroundColor = newValue | ||
} | ||
} | ||
|
||
/// The label to use for the primary button. | ||
/// | ||
/// If not set, Payment Sheet will display suitable default labels | ||
/// for payment and setup intents. | ||
public var primaryButtonLabel: String? | ||
|
||
private var styleRawValue: Int = 0 // SheetStyle.automatic.rawValue | ||
/// The color styling to use for PaymentSheet UI | ||
/// Default value is SheetStyle.automatic | ||
/// @see SheetStyle | ||
public var style: UserInterfaceStyle { // stored properties can't be marked @available which is why this uses the styleRawValue private var | ||
get { | ||
return UserInterfaceStyle(rawValue: styleRawValue)! | ||
} | ||
set { | ||
styleRawValue = newValue.rawValue | ||
} | ||
} | ||
|
||
/// Configuration related to the Stripe Customer | ||
/// If set, the customer can select a previously saved payment method within PaymentSheet | ||
public var customer: CustomerConfiguration? | ||
|
||
/// Your customer-facing business name. | ||
/// The default value is the name of your app, using CFBundleDisplayName or CFBundleName | ||
public var merchantDisplayName: String = Bundle.displayName ?? "" | ||
|
||
/// A URL that redirects back to your app that PaymentSheet can use to auto-dismiss | ||
/// web views used for additional authentication, e.g. 3DS2 | ||
public var returnURL: String? | ||
|
||
/// PaymentSheet pre-populates fields with the values provided. | ||
/// If `billingDetailsCollectionConfiguration.attachDefaultsToPaymentMethod` is `true`, these values will | ||
/// be attached to the payment method even if they are not collected by the PaymentSheet UI. | ||
public var defaultBillingDetails: BillingDetails = BillingDetails() | ||
|
||
/// PaymentSheet offers users an option to save some payment methods for later use. | ||
/// Default value is .automatic | ||
/// @see SavePaymentMethodOptInBehavior | ||
public var savePaymentMethodOptInBehavior: SavePaymentMethodOptInBehavior = .automatic | ||
|
||
/// Describes the appearance of PaymentSheet | ||
public var appearance = PaymentSheet.Appearance.default | ||
|
||
/// A closure that returns the customer's shipping details. | ||
/// This is used to display a "Billing address is same as shipping" checkbox if `defaultBillingDetails` is not provided | ||
/// If `name` and `line1` are populated, it's also [attached to the PaymentIntent](https://stripe.com/docs/api/payment_intents/object#payment_intent_object-shipping) during payment. | ||
public var shippingDetails: () -> AddressViewController.AddressDetails? = { return nil } | ||
|
||
/// The list of preferred networks that should be used to process payments made with a co-branded card. | ||
/// This value will only be used if your user hasn't selected a network themselves. | ||
public var preferredNetworks: [STPCardBrand]? { | ||
didSet { | ||
guard let preferredNetworks = preferredNetworks else { return } | ||
assert(Set<STPCardBrand>(preferredNetworks).count == preferredNetworks.count, | ||
"preferredNetworks must not contain any duplicate card brands") | ||
} | ||
} | ||
|
||
/// Override country for test purposes | ||
@_spi(STP) public var userOverrideCountry: String? | ||
|
||
/// Describes how billing details should be collected. | ||
/// All values default to `automatic`. | ||
/// If `never` is used for a required field for the Payment Method used during checkout, | ||
/// you **must** provide an appropriate value as part of `defaultBillingDetails`. | ||
public var billingDetailsCollectionConfiguration = BillingDetailsCollectionConfiguration() | ||
|
||
/// Optional configuration to display a custom message when a saved payment method is removed. | ||
public var removeSavedPaymentMethodMessage: String? | ||
|
||
/// Configuration for external payment methods. | ||
public var externalPaymentMethodConfiguration: ExternalPaymentMethodConfiguration? | ||
|
||
/// By default, PaymentSheet will use a dynamic ordering that optimizes payment method display for the customer. | ||
/// You can override the default order in which payment methods are displayed in PaymentSheet with a list of payment method types. | ||
/// See https://stripe.com/docs/api/payment_methods/object#payment_method_object-type for the list of valid types. You may also pass external payment methods. | ||
/// - Example: ["card", "external_paypal", "klarna"] | ||
/// - Note: If you omit payment methods from this list, they’ll be automatically ordered by Stripe after the ones you provide. Invalid payment methods are ignored. | ||
public var paymentMethodOrder: [String]? | ||
|
||
/// This is an experimental feature that may be removed at any time. | ||
/// If true (the default), the customer can delete all saved payment methods. | ||
/// If false, the customer can't delete if they only have one saved payment method remaining. | ||
@_spi(ExperimentalAllowsRemovalOfLastSavedPaymentMethodAPI) public var allowsRemovalOfLastSavedPaymentMethod = true | ||
|
||
/// The view can display payment methods like “Card” that, when tapped, open a form sheet where customers enter their payment method details. The sheet has a button at the bottom. `FormSheetAction` enumerates the actions the button can perform. | ||
public enum FormSheetAction { | ||
/// The button says “Pay” or “Setup”. When tapped, we confirm the payment or setup in the form sheet. | ||
/// - Parameter completion: Called with the result of the payment or setup. | ||
case confirm( | ||
completion: (EmbeddedPaymentElementResult) -> Void | ||
) | ||
|
||
/// The button says “Continue”. When tapped, the form sheet closes. | ||
case `continue` | ||
} | ||
|
||
/// The view can display payment methods like “Card” that, when tapped, open a sheet where customers enter their payment method details. The sheet has a button at the bottom. `formSheetAction` controls the action the button performs. | ||
public var formSheetAction: FormSheetAction | ||
|
||
/// Controls whether the view displays mandate text at the bottom for payment methods that require it. If set to `true`, your integration must display `PaymentOptionDisplayData.mandateText` to the customer near your “Buy” button to comply with regulations. | ||
public var hidesMandateText: Bool = false | ||
|
||
/// Initializes a Configuration with default values | ||
public init(formSheetAction: FormSheetAction) { | ||
self.formSheetAction = formSheetAction | ||
} | ||
} | ||
} |
Oops, something went wrong.