Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: stripe/stripe-ios
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: f7fdc5893e6a24c56b40fc7792cd5d62cecc138a
Choose a base ref
..
head repository: stripe/stripe-ios
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3cdcaf07488fd355ab8ebab4d604497bf51d453f
Choose a head ref
Showing with 2,952 additions and 1,303 deletions.
  1. +1 −1 BuildConfigurations/Version.xcconfig
  2. +21 −0 CHANGELOG.md
  3. +11 −1 Example/Non-Card Payment Examples/Non-Card Payment Examples/BrowseExamplesViewController.m
  4. +12 −9 Example/PaymentSheet Example/PaymentSheet Example/CustomerSheetTestPlaygroundController.swift
  5. +1 −5 Example/PaymentSheet Example/PaymentSheet Example/ExampleCheckoutDeferredViewController.swift
  6. +1 −5 Example/PaymentSheet Example/PaymentSheet Example/ExampleCustomDeferredCheckoutViewController.swift
  7. +194 −0 Example/PaymentSheet Example/PaymentSheet Example/ExampleLinkPaymentCheckoutViewController.swift
  8. +2 −1 Example/PaymentSheet Example/PaymentSheet Example/PaymentSheetTestPlaygroundSettings.swift
  9. +2 −2 Example/PaymentSheet Example/PaymentSheet Example/PlaygroundController.swift
  10. +391 −2 Example/PaymentSheet Example/PaymentSheet Example/Resources/Base.lproj/Main.storyboard
  11. +2 −2 Example/PaymentSheet Example/PaymentSheetUITest/CustomerSheetSnapshotTests.swift
  12. +172 −7 Example/PaymentSheet Example/PaymentSheetUITest/CustomerSheetUITest.swift
  13. +8 −8 Example/PaymentSheet Example/PaymentSheetUITest/PaymentSheet+AddressTests.swift
  14. +13 −3 Example/PaymentSheet Example/PaymentSheetUITest/PaymentSheetSnapshotTests.swift
  15. +0 −1 Example/PaymentSheet Example/PaymentSheetUITest/PaymentSheetUITest.swift
  16. +1 −1 README.md
  17. +1 −1 Stripe.podspec
  18. +1 −1 Stripe/StripeiOSTests/Error+PaymentSheetTests.swift
  19. +9 −1 Stripe/StripeiOSTests/PayWithLinkButtonSnapshotTests.swift
  20. +11 −208 Stripe/StripeiOSTests/PaymentSheet+APITest.swift
  21. +8 −8 Stripe/StripeiOSTests/PaymentSheetDeferredValidatorTests.swift
  22. +170 −0 Stripe/StripeiOSTests/PaymentSheetLoaderTest.swift
  23. +1 −1 Stripe/StripeiOSTests/STPAPIClient+LinkAccountSessionTest.swift
  24. +7 −1 Stripe/StripeiOSTests/STPAnalyticsClientPaymentSheetTest.swift
  25. +1 −1 Stripe/StripeiOSTests/STPAnalyticsClientPaymentsTest.swift
  26. +1 −1 Stripe/StripeiOSTests/STPApplePayFunctionalTest.swift
  27. +1 −0 Stripe/StripeiOSTests/STPElementsSessionTest.swift
  28. +83 −102 Stripe/StripeiOSTests/STPIntentWithPreferencesTest.swift
  29. +1 −0 Stripe/StripeiOSTests/STPPaymentHandlerTests.swift
  30. +42 −4 Stripe/StripeiOSTests/STPSourceFunctionalTest.m
  31. +78 −0 Stripe/StripeiOSTests/STPTestingAPIClient+Swift.swift
  32. +2 −0 Stripe/StripeiOSTests/WalletHeaderViewSnapshotTests.swift
  33. +1 −1 StripeApplePay.podspec
  34. +4 −3 StripeApplePay/StripeApplePay/Source/PaymentsCore/API/Models/Token.swift
  35. +3 −2 StripeApplePay/StripeApplePay/Source/PaymentsCore/API/Token+API.swift
  36. +1 −1 StripeCameraCore.podspec
  37. +1 −1 StripeCardScan.podspec
  38. +1 −1 StripeCore.podspec
  39. +1 −1 StripeCore/StripeCore/Source/API Bindings/StripeAPIConfiguration+Version.swift
  40. +54 −0 StripeCore/StripeCore/Source/Analytics/NetworkDetector.swift
  41. +7 −6 StripeCore/StripeCore/Source/Analytics/STPAnalyticEvent.swift
  42. +9 −3 StripeCore/StripeCore/Source/Analytics/STPAnalyticsClient.swift
  43. +1 −1 StripeFinancialConnections.podspec
  44. +1 −1 StripeIdentity.podspec
  45. +1 −1 StripeLinkCore.podspec
  46. +1 −1 StripePaymentSheet.podspec
  47. BIN StripePaymentSheet/StripePaymentSheet/Resources/Images/Link/link_arrow@3x.png
  48. +1 −0 StripePaymentSheet/StripePaymentSheet/Source/Analytics/AnalyticsHelper.swift
  49. +1 −0 StripePaymentSheet/StripePaymentSheet/Source/Helpers/Images.swift
  50. +24 −85 StripePaymentSheet/StripePaymentSheet/Source/Helpers/PaymentSheetLinkAccount.swift
  51. +0 −32 StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/ConsumerSession.swift
  52. +0 −1 ...ymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/CookieStore/LinkCookieStore.swift
  53. +18 −60 StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/STPAPIClient+Link.swift
  54. +19 −76 StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/STPAPIClient+PaymentSheet.swift
  55. +7 −0 StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/STPElementsSession.swift
  56. +179 −0 ...tripePaymentSheet/Source/Internal/Link/ACH/InstantDebitsOnlyFinancialConnectionsAuthManager.swift
  57. +60 −18 ...pePaymentSheet/StripePaymentSheet/Source/Internal/Link/Controllers/PayWithLinkWebController.swift
  58. +24 −0 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/Intent+Link.swift
  59. +37 −13 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/STPAnalyticsClient+Link.swift
  60. +5 −0 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/UIColor+Link.swift
  61. +41 −2 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Services/LinkAccountService.swift
  62. +1 −0 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Utils/LinkPopupURLParser.swift
  63. +11 −7 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Utils/LinkURLGenerator.swift
  64. +2 −1 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkCookieKey.swift
  65. +2 −2 StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerAdapter/CustomerAdapter.swift
  66. +26 −1 ...Sheet/Source/PaymentSheet/CustomerSheet/CustomerSavedPaymentMethodsCollectionViewController.swift
  67. +37 −46 ...ipePaymentSheet/Source/PaymentSheet/CustomerSheet/CustomerSavedPaymentMethodsViewController.swift
  68. +10 −6 StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerSheet/CustomerSheet.swift
  69. +6 −18 ...aymentSheet/StripePaymentSheet/Source/PaymentSheet/CustomerSheet/CustomerSheetConfiguration.swift
  70. +233 −73 StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Link/LinkPaymentController.swift
  71. +2 −7 ...pePaymentSheet/Source/PaymentSheet/New Payment Method Screen/AddPaymentMethodViewController.swift
  72. +2 −7 StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentMethodType.swift
  73. +22 −279 StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet+API.swift
  74. +8 −5 StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet+DeferredAPI.swift
  75. +0 −2 ...ePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet+PaymentMethodAvailability.swift
  76. +4 −8 StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet.swift
  77. +7 −7 StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetDeferredValidator.swift
  78. +102 −8 StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetError.swift
  79. +10 −11 StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetFlowController.swift
  80. +3 −1 ...heet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetFormFactory/PaymentSheetFormFactory.swift
  81. +1 −2 StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetIntentConfiguration.swift
  82. +204 −0 StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetLoader.swift
  83. +10 −4 StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/STPAnalyticsClient+PaymentSheet.swift
  84. +7 −7 ...pePaymentSheet/Source/PaymentSheet/ViewControllers/PaymentSheetFlowControllerViewController.swift
  85. +1 −0 ...mentSheet/StripePaymentSheet/Source/PaymentSheet/ViewControllers/PaymentSheetViewController.swift
  86. +295 −54 StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Views/PayWithLinkButton.swift
  87. +53 −0 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/FlowControllerStateTests.swift
  88. +1 −1 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkPopupURLParserTests.swift
  89. +1 −1 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkURLGeneratorTests.swift
  90. +1 −1 StripePayments.podspec
  91. +8 −0 StripePayments/StripePayments/Source/API Bindings/Models/PaymentIntents/STPPaymentIntent.swift
  92. +1 −1 StripePayments/StripePayments/Source/API Bindings/Models/PaymentMethods/STPPaymentMethod.swift
  93. +8 −0 StripePayments/StripePayments/Source/API Bindings/Models/SetupIntents/STPSetupIntent.swift
  94. +1 −1 ...Payments/StripePayments/Source/API Bindings/Models/SetupIntents/STPSetupIntentConfirmParams.swift
  95. +11 −0 StripePayments/StripePayments/Source/API Bindings/Models/Shared/LinkSettings.swift
  96. +21 −11 StripePayments/StripePayments/Source/API Bindings/STPAPIClient+LinkAccountSession.swift
  97. +40 −8 StripePayments/StripePayments/Source/API Bindings/STPAPIClient+Payments.swift
  98. +34 −32 StripePayments/StripePayments/Source/Internal/API Bindings/APIRequest.swift
  99. +1 −1 StripePaymentsUI.podspec
  100. +1 −1 StripeUICore.podspec
  101. BIN ...s/ReferenceImages_64/PaymentSheetUITest.PaymentSheetSnapshotTests/testPaymentSheetWithLink@3x.png
  102. BIN ...eImages_64/PaymentSheetUITest.PaymentSheetSnapshotTests/testPaymentSheetWithLinkAppearance@3x.png
  103. BIN ...nceImages_64/PaymentSheetUITest.PaymentSheetSnapshotTests/testPaymentSheetWithLinkDarkMode@3x.png
  104. BIN ...ages_64/PaymentSheetUITest.PaymentSheetSnapshotTests/testPaymentSheetWithLinkHiddenBorders@3x.png
  105. BIN ...es_64/PaymentSheetUITest.PaymentSheetSnapshotTests/testPaymentSheetWithLink_deferredIntent@3x.png
  106. BIN ...enceImages_64/PaymentSheetUITest.PaymentSheetSnapshotTests/testPaymentSheet_deferredIntent@3x.png
  107. BIN Tests/ReferenceImages_64/StripeiOS_Tests.PayWithLinkButtonSnapshotTests/testDefault@3x.png
  108. BIN .../ReferenceImages_64/StripeiOS_Tests.PayWithLinkButtonSnapshotTests/testDefault_Highlighted@3x.png
  109. BIN Tests/ReferenceImages_64/StripeiOS_Tests.PayWithLinkButtonSnapshotTests/testDefault_rounded@3x.png
  110. BIN Tests/ReferenceImages_64/StripeiOS_Tests.PayWithLinkButtonSnapshotTests/testDisabled@3x.png
  111. BIN Tests/ReferenceImages_64/StripeiOS_Tests.PayWithLinkButtonSnapshotTests/testRegistered@3x.png
  112. BIN ...s/ReferenceImages_64/StripeiOS_Tests.PayWithLinkButtonSnapshotTests/testRegistered_rounded@3x.png
  113. BIN Tests/ReferenceImages_64/StripeiOS_Tests.PayWithLinkButtonSnapshotTests/testRegistered_square@3x.png
  114. BIN ...erenceImages_64/StripeiOS_Tests.PayWithLinkButtonSnapshotTests/testRegistered_withCardInfo@3x.png
  115. BIN ...ages_64/StripeiOS_Tests.PayWithLinkButtonSnapshotTests/testRegistered_withLongEmailAddress@3x.png
  116. BIN ...ripeiOS_Tests.WalletHeaderViewSnapshotTests/testAdaptiveElementsWithCustomApplePayCta_Dark@3x.png
  117. BIN ...ipeiOS_Tests.WalletHeaderViewSnapshotTests/testAdaptiveElementsWithCustomApplePayCta_Light@3x.png
  118. BIN ...ReferenceImages_64/StripeiOS_Tests.WalletHeaderViewSnapshotTests/testAdaptiveElements_Dark@3x.png
  119. BIN ...eferenceImages_64/StripeiOS_Tests.WalletHeaderViewSnapshotTests/testAdaptiveElements_Light@3x.png
  120. BIN Tests/ReferenceImages_64/StripeiOS_Tests.WalletHeaderViewSnapshotTests/testAllButtons@3x.png
  121. BIN ...mages_64/StripeiOS_Tests.WalletHeaderViewSnapshotTests/testAllButtonsWithCustomApplePayCta@3x.png
  122. BIN ...tripeiOS_Tests.WalletHeaderViewSnapshotTests/testAllButtonsWithCustomApplePayCta_Card_only@3x.png
  123. BIN .../ReferenceImages_64/StripeiOS_Tests.WalletHeaderViewSnapshotTests/testAllButtons_Card_only@3x.png
  124. BIN Tests/ReferenceImages_64/StripeiOS_Tests.WalletHeaderViewSnapshotTests/testApplePayButton@3x.png
  125. BIN ...nceImages_64/StripeiOS_Tests.WalletHeaderViewSnapshotTests/testApplePayButtonWithCustomCta@3x.png
  126. BIN Tests/ReferenceImages_64/StripeiOS_Tests.WalletHeaderViewSnapshotTests/testCustomCornerRadius@3x.png
  127. BIN ...renceImages_64/StripeiOS_Tests.WalletHeaderViewSnapshotTests/testCustomFontAndReturnError_@3x.png
  128. BIN ...mages_64/StripeiOS_Tests.WalletHeaderViewSnapshotTests/testCustomFontScalesAndReturnError_@3x.png
  129. BIN Tests/ReferenceImages_64/StripeiOS_Tests.WalletHeaderViewSnapshotTests/testLinkButton@3x.png
  130. +1 −1 VERSION
  131. +11 −0 bitrise.yml
  132. +1 −1 ci_scripts/create_release.rb
2 changes: 1 addition & 1 deletion BuildConfigurations/Version.xcconfig
Original file line number Diff line number Diff line change
@@ -6,4 +6,4 @@
// Instead, edit the `VERSION` file and run `ci_scripts/update_version.sh`
//

CURRENT_PROJECT_VERSION=23.9.2
CURRENT_PROJECT_VERSION=23.10.0
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
## 23.11.0 2023-07-17
### CustomerSheet
* [Changed] Breaking interface change for `CustomerSheetResult`. `CustomerSheetResult.canceled` now has a nullable associated value signifying that there is no selected payment method. Please use both `.canceled(StripeOptionSelection?)` and `.selected(PaymentOptionSelection?)` to update your UI to show the latest selected payment method.

## 23.10.0 2023-07-10
### Payments
* [Fixed] A bug where `mandate_data` was not being properly attached to PayPal SetupIntent's.
### PaymentSheet
* [Added] You can now collect payment details before creating a PaymentIntent or SetupIntent. See [our docs](https://stripe.com/docs/payments/accept-a-payment-deferred) for more info. This integration also allows you to [confirm the Intent on the server](https://stripe.com/docs/payments/finalize-payments-on-the-server).

## 23.9.4 2023-07-05
### PaymentSheet
* [Added] US bank accounts are now supported when initializing with an IntentConfiguration.

## 23.9.3 2023-06-26
### PaymentSheet
* [Fixed] Affirm no longer requires shipping details.

### CustomerSheet
* [Added] Added `billingDetailsCollectionConfiguration` to configure how you want to collect billing details (private beta).

## 23.9.2 2023-06-20
### Payments
* [Fixed] Fixed a bug causing Cash App Pay SetupIntents to incorrectly state they were canceled when they succeeded.
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@
#import "SofortExampleViewController.h"
#import "WeChatPayExampleViewController.h"
#import "EPSExampleViewController.h"
#import "PayPalExampleViewController.h"

/**
This view controller presents different examples, each of which demonstrates creating a payment using a different payment method or integration.
@@ -46,7 +47,7 @@ - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 25;
return 26;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
@@ -127,6 +128,9 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
case 24:
cell.textLabel.text = @"BLIK";
break;
case 25:
cell.textLabel.text = @"PayPal";
break;
}
return cell;
}
@@ -291,6 +295,12 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
viewController = exampleVC;
break;
}
case 25: {
PayPalExampleViewController *exampleVC = [PayPalExampleViewController new];
exampleVC.delegate = self;
viewController = exampleVC;
break;
}
}
[self.navigationController pushViewController:viewController animated:YES];
}
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ import Combine
import SwiftUI

class CustomerSheetTestPlaygroundController: ObservableObject {
static let defaultEndpoint = "https://stp-mobile-ci-test-backend-v7.stripedemos.com"
static let defaultEndpoint = "https://stp-mobile-playground-backend-v7.stripedemos.com"

@Published var settings: CustomerSheetTestPlaygroundSettings
@Published var currentlyRenderedSettings: CustomerSheetTestPlaygroundSettings
@@ -69,20 +69,23 @@ class CustomerSheetTestPlaygroundController: ObservableObject {
func presentCustomerSheet() {
customerSheet?.present(from: rootViewController, completion: { result in
switch result {
case .canceled:
let alertController = self.makeAlertController()
alertController.message = "Canceled"
self.rootViewController.present(alertController, animated: true)
case .selected(let paymentOptionSelection):
case .selected(let paymentOptionSelection), .canceled(let paymentOptionSelection):
self.paymentOptionSelection = paymentOptionSelection

var status = "canceled"
if case .selected = result {
status = "selected"
}

let alertController = self.makeAlertController()
if let paymentOptionSelection = paymentOptionSelection {
alertController.message = "Success: \(paymentOptionSelection.displayData().label)"
if let selection = paymentOptionSelection {
alertController.message = "Success: \(selection.displayData().label), \(status)"
} else {
alertController.message = "Success: payment method unset"
alertController.message = "Success: payment method not set, \(status)"
}

self.rootViewController.present(alertController, animated: true)

case .error(let error):
print("Something went wrong: \(error)")
}
Original file line number Diff line number Diff line change
@@ -5,12 +5,8 @@
// Created by Yuki Tokuhiro on 3/31/23.
//
// This is an example of an integration using PaymentSheet where you collect payment details before creating an Intent.
// ⚠️🏗 This integration is in private beta. Please email us at mobile-deferred-intents-beta@stripe.com if you're interested in participating!

// Note: Do not import Stripe using `@_spi(ExperimentalPaymentSheetDecouplingAPI)` in production.
// This exposes internal functionality which may cause unexpected behavior if used directly.
// TODO(porter) Remove ExperimentalPaymentSheetDecouplingAPI usage before GA
@_spi (ExperimentalPaymentSheetDecouplingAPI) import StripePaymentSheet
import StripePaymentSheet
import UIKit

// View the backend code here: https://glitch.com/edit/#!/stripe-mobile-payment-sheet-custom-deferred
Original file line number Diff line number Diff line change
@@ -5,12 +5,8 @@
// Created by Nick Porter on 3/27/23.
//
// This is an example of an integration using PaymentSheet.FlowController where you collect payment details before creating an Intent.
// ⚠️🏗 This integration is in private beta. Please email us at mobile-deferred-intents-beta@stripe.com if you're interested in participating!

// Note: Do not import Stripe using `@_spi(ExperimentalPaymentSheetDecouplingAPI)` in production.
// This exposes internal functionality which may cause unexpected behavior if used directly.
// TODO(porter) Remove ExperimentalPaymentSheetDecouplingAPI usage before GA
@_spi (ExperimentalPaymentSheetDecouplingAPI) import StripePaymentSheet
import StripePaymentSheet
import UIKit

// View the backend code here: https://glitch.com/edit/#!/stripe-mobile-payment-sheet-custom-deferred
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
//
// ExampleLinkPaymentCheckoutViewController.swift
// PaymentSheet Example
//
// Created by Vardges Avetisyan on 6/27/23.
//

import Foundation
@_spi(LinkOnly) import StripePaymentSheet
import UIKit

class ExampleLinkPaymentCheckoutViewController: UIViewController {
@IBOutlet weak var buyButton: UIButton!
@IBOutlet weak var paymentMethodButton: UIButton!
@IBOutlet weak var paymentMethodImage: UIImageView!
@IBOutlet weak var deferredSwitch: UISwitch!
var linkPaymentController: LinkPaymentController!
let backendCheckoutUrl = "https://abundant-elderly-universe.glitch.me/checkout" // An example backend endpoint
let confirmEndpoint = "https://abundant-elderly-universe.glitch.me/confirm_intent"
private var token = 0

private func loadBackend() {
token += 1
let thisToken = token
makeRequest(with: backendCheckoutUrl, body: ["mode": "payment"]) {
[weak self] (data, _, _) in
guard let data = data,
let json = try? JSONSerialization.jsonObject(with: data, options: [])
as? [String: Any],
let paymentIntentClientSecret = json["intentClientSecret"] as? String,
let publishableKey = json["publishableKey"] as? String,
let self = self,
self.token == thisToken
else {
// Handle error
return
}
// MARK: Set your Stripe publishable key - this allows the SDK to make requests to Stripe for your account
STPAPIClient.shared.publishableKey = publishableKey
let returnURL = "payments-example://stripe-redirect"
DispatchQueue.main.async {
if self.deferredSwitch.isOn {
let intentConfiguration = PaymentSheet
.IntentConfiguration(
mode: .payment(amount: 100, currency: "usd"),
paymentMethodTypes: ["link"]) { [weak self] _, _, intentCreationCallback in
self?.handleDeferredIntent(intentCreationCallback: intentCreationCallback)
}

self.linkPaymentController = LinkPaymentController(intentConfiguration: intentConfiguration, returnURL: returnURL)
} else {
self.linkPaymentController = LinkPaymentController(paymentIntentClientSecret: paymentIntentClientSecret, returnURL: returnURL)
}

self.updateButtons()
}
}
}

override func viewDidLoad() {
super.viewDidLoad()

buyButton.addTarget(self, action: #selector(didTapCheckoutButton), for: .touchUpInside)
buyButton.isEnabled = false

paymentMethodButton.addTarget(self, action: #selector(didTapPaymentMethodButton), for: .touchUpInside)
paymentMethodButton.isEnabled = false

loadBackend()
}

// MARK: - Button handlers

@objc
func didTapPaymentMethodButton() {
buyButton.isEnabled = false
linkPaymentController.present(from: self) { [weak self] result in
switch result {
case .success:
self?.updateButtons()
case .failure(let error):
print(error as Any)
self?.updateButtons()
}
}
}

@objc
func didTapCheckoutButton() {
linkPaymentController.confirm(from: self) { paymentResult in
switch paymentResult {
case .completed:
self.displayAlert("Your order is confirmed!")
case .canceled:
print("Canceled!")
case .failed(let error):
print(error)
self.displayAlert("Payment failed: \n\(error.localizedDescription)")
}
}
}

@IBAction func deferredSwitchDidChangeValue(_ sender: Any) {
loadBackend()
}

// MARK: - Helper methods

func updateButtons() {
// MARK: Update the payment method and buy buttons
if let paymentOption = linkPaymentController.paymentOption {
paymentMethodButton.setTitle(paymentOption.label, for: .normal)
paymentMethodButton.setTitleColor(.black, for: .normal)
paymentMethodImage.image = paymentOption.image
buyButton.isEnabled = true
} else {
paymentMethodButton.setTitle("Select", for: .normal)
paymentMethodButton.setTitleColor(.systemBlue, for: .normal)
paymentMethodImage.image = nil
buyButton.isEnabled = false
paymentMethodButton.isEnabled = true
}
}

func displayAlert(_ message: String) {
let alertController = UIAlertController(title: "", message: message, preferredStyle: .alert)
let OKAction = UIAlertAction(title: "OK", style: .default) { (_) in
alertController.dismiss(animated: true) {
self.navigationController?.popViewController(animated: true)
}
}
alertController.addAction(OKAction)
present(alertController, animated: true, completion: nil)
}

func handleDeferredIntent(intentCreationCallback: @escaping ((Result<String, Error>) -> Void) ) {
enum ConfirmHandlerError: Error, LocalizedError {
case clientSecretNotFound
case confirmError(String)
case unknown

public var errorDescription: String? {
switch self {
case .clientSecretNotFound:
return "Client secret not found in response from server."
case .confirmError(let errorMesssage):
return errorMesssage
case .unknown:
return "An unknown error occurred."
}
}
}
makeRequest(with: confirmEndpoint, body: ["mode": "payment"], completionHandler: { data, response, error in
guard
error == nil,
let data = data,
let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
else {
if let data = data,
(response as? HTTPURLResponse)?.statusCode == 400,
let errorMessage = String(data: data, encoding: .utf8){
// read the error message
intentCreationCallback(.failure(ConfirmHandlerError.confirmError(errorMessage)))
} else {
intentCreationCallback(.failure(error ?? ConfirmHandlerError.unknown))
}
return
}

guard let clientSecret = json["client_secret"] as? String else {
intentCreationCallback(.failure(ConfirmHandlerError.clientSecretNotFound))
return
}

intentCreationCallback(.success(clientSecret))
})
}

func makeRequest(with url: String, body: [String: Any], completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) {
let session = URLSession.shared
let url = URL(string: url)!

let json = try! JSONSerialization.data(withJSONObject: body, options: [])
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
urlRequest.httpBody = json
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-type")
let task = session.dataTask(with: urlRequest) { data, response, error in
completionHandler(data, response, error)
}

task.resume()
}
}
Original file line number Diff line number Diff line change
@@ -80,6 +80,7 @@ struct PaymentSheetTestPlaygroundSettings: Codable, Equatable {
case aud
case gbp
case inr
case pln
}

enum MerchantCountry: String, PickerEnum {
@@ -238,7 +239,7 @@ struct PaymentSheetTestPlaygroundSettings: Codable, Equatable {

static let nsUserDefaultsKey = "PaymentSheetTestPlaygroundSettings"

static let baseEndpoint = "https://stp-mobile-ci-test-backend-v7.stripedemos.com"
static let baseEndpoint = "https://stp-mobile-playground-backend-v7.stripedemos.com"
static var endpointSelectorEndpoint: String {
return "\(baseEndpoint)/endpoints"
}
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
import Combine
import Contacts
import PassKit
@_spi(STP) @_spi(ExperimentalPaymentSheetDecouplingAPI) @_spi(PaymentSheetSkipConfirmation) import StripePaymentSheet
@_spi(STP) @_spi(PaymentSheetSkipConfirmation) import StripePaymentSheet
import SwiftUI
import UIKit

@@ -214,7 +214,6 @@ class PlaygroundController: ObservableObject {
init(settings: PaymentSheetTestPlaygroundSettings) {
// Enable experimental payment methods.
// PaymentSheet.supportedPaymentMethods += [.link]
PaymentSheet.enableACHV2InDeferredFlow = true // TODO(https://jira.corp.stripe.com/browse/BANKCON-6731) Remove this.

// Hack to ensure we don't force the native flow unless we're in a UI test
if ProcessInfo.processInfo.environment["UITesting"] == nil {
@@ -266,6 +265,7 @@ class PlaygroundController: ObservableObject {

func didTapResetConfig() {
self.settings = PaymentSheetTestPlaygroundSettings.defaultValues()
PaymentSheet.resetCustomer()
}

func appearanceButtonTapped() {
Loading