Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 4.1.0 #335

Merged
merged 1 commit into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ If you are using CocoaPods, update your Podfile:
```
pod 'StripeTerminal', '~> 4.0'
```
# 4.1.0 2024-11-18
* Built with Xcode 16.0 Swift version 6.0.
* Update: Added field `dynamicCurrencyConversion` to [`SCPCardPresentDetails`](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPCardPresentDetails.html).
* If you are interested in joining this preview, please email [stripe-terminal-betas@stripe.com](mailto:stripe-terminal-betas@stripe.com).
* New: Affirm support for smart readers is now available in private preview.
* If you are interested in joining this preview, please email [stripe-terminal-betas@stripe.com](mailto:stripe-terminal-betas@stripe.com).
* New: Added an `returnUrl` parameter to [`SCPConfirmConfiguration`](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPConfirmConfiguration.html) to specify desired return_url to redirect to upon completion of a Redirect Payment Method.


# 4.0.0 2024-10-31
4.0.0 includes breaking changes in both symbols and behavior. See the [migration guide](https://stripe.com/docs/terminal/references/sdk-migration-guide) for more details.
Expand Down
70 changes: 37 additions & 33 deletions Example/Example.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions Example/Example/APIClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,12 @@ class APIClient: NSObject, ConnectionTokenProvider {
}
}

func capturePaymentIntent(_ paymentIntentId: String, completion: @escaping ErrorCompletionBlock) {
func capturePaymentIntent(_ paymentIntentId: String, stripeAccount: String? = nil, additionalParams: [String: Any]? = nil, completion: @escaping ErrorCompletionBlock) {
let url = self.baseURL.appendingPathComponent("capture_payment_intent")
var params = additionalParams ?? [:]
params["payment_intent_id"] = paymentIntentId
AF.request(url, method: .post,
parameters: ["payment_intent_id": paymentIntentId])
parameters: params)
.validate(statusCode: 200..<300)
.responseString { response in
switch response.result {
Expand Down
2 changes: 2 additions & 0 deletions Example/Example/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,7 @@
</array>
<key>UIUserInterfaceStyle</key>
<string>Light</string>
<key>LSMinimumSystemVersion</key>
<string>12.0</string>
</dict>
</plist>
9 changes: 7 additions & 2 deletions Example/Example/PaymentViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class PaymentViewController: EventDisplayingViewController {
private var offlineCreateConfig: CreateConfiguration?
private let isSposReader: Bool
private let skipCapture: Bool
private let onReceiptTip: UInt

init(paymentParams: PaymentIntentParameters,
collectConfig: CollectConfiguration,
Expand All @@ -30,14 +31,17 @@ class PaymentViewController: EventDisplayingViewController {
offlineTransactionLimit: Int,
offlineTotalTransactionLimit: Int,
offlineBehavior: OfflineBehavior,
skipCapture: Bool) {
skipCapture: Bool,
onReceiptTip: UInt
) {
self.paymentParams = paymentParams
self.collectConfig = collectConfig
self.confirmConfig = confirmConfig
self.declineCardBrand = declineCardBrand
self.recollectAfterCardBrandDecline = recollectAfterCardBrandDecline
self.isSposReader = isSposReader
self.skipCapture = skipCapture
self.onReceiptTip = onReceiptTip

var isOverOfflineTransactionLimit = paymentParams.amount >= offlineTransactionLimit
if let offlinePaymentTotalByCurrency = Terminal.shared.offlineStatus.sdk.paymentAmountsByCurrency[paymentParams.currency]?.intValue {
Expand Down Expand Up @@ -306,7 +310,8 @@ class PaymentViewController: EventDisplayingViewController {
// Online, capture intent.
var captureEvent = LogEvent(method: .capturePaymentIntent)
self.events.append(captureEvent)
AppDelegate.apiClient?.capturePaymentIntent(piID) { captureError in
let additionalParams = ["amount_to_capture": self.onReceiptTip + intent.amount]
AppDelegate.apiClient?.capturePaymentIntent(piID, additionalParams: additionalParams) { captureError in
if let error = captureError {
captureEvent.result = .errored
captureEvent.object = .error(error as NSError)
Expand Down
2 changes: 1 addition & 1 deletion Example/Example/ReaderViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ extension ReaderViewController: ReaderDelegate {
}
}}
reconnectionAlertController.addAction(cancelAction)
present(reconnectionAlertController, animated: true, completion: nil)
topViewController()?.present(reconnectionAlertController, animated: true, completion: nil)
}

func readerDidFailReconnect(_ reader: Reader) {
Expand Down
48 changes: 46 additions & 2 deletions Example/Example/StartPaymentViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class StartPaymentViewController: TableViewController, CancelingViewController {
.card,
.interacPresent,
.wechatPay,
.affirm,
]
private var selectedPaymentMethodTypes: [PaymentMethodType] = [.cardPresent]
private var allowRedisplay: AllowRedisplay = AllowRedisplay.always
Expand All @@ -55,6 +56,8 @@ class StartPaymentViewController: TableViewController, CancelingViewController {

private var offlineBehavior: OfflineBehavior = .preferOnline

private var onReceiptTip: UInt = 0

private lazy var offlineTransactionLimitTextField: TextFieldView = {
let textField = TextFieldView(placeholderText: "10000", keyboardType: .numberPad)
textField.textField.autocorrectionType = .no
Expand All @@ -71,6 +74,14 @@ private lazy var offlineStoredTransactionLimitTextField: TextFieldView = {
return textField
}()

private lazy var tipFields: UIStackView = {
let textFields = UIStackView()
textFields.axis = .vertical
textFields.addArrangedSubview(tipEligibleAmountTextField)
textFields.addArrangedSubview(postAuthTipAmountTextField)
return textFields
}()

private lazy var tipEligibleAmountTextField: AmountInputView = {
let textField = AmountInputView(footer: "Must have on-reader tipping configured to have any effect.", placeholderText: "Tip-eligible amount")
textField.textField.text = nil
Expand All @@ -79,6 +90,14 @@ private lazy var offlineStoredTransactionLimitTextField: TextFieldView = {
return textField
}()

private lazy var postAuthTipAmountTextField: AmountInputView = {
let textField = AmountInputView(footer: "overcapture_supported must be true for the capture to succeed.", placeholderText: "Post-auth tip amount (overcapture)")
textField.textField.text = nil
textField.textField.clearButtonMode = .whileEditing
textField.textField.keyboardType = .numbersAndPunctuation
return textField
}()

private lazy var simulatedTipAmountTextField: AmountInputView = {
let textField = AmountInputView(placeholderText: "Simulated tip amount", keyboardType: .numberPad)
textField.textField.text = nil
Expand All @@ -103,6 +122,14 @@ private lazy var offlineStoredTransactionLimitTextField: TextFieldView = {
return textField
}()

private lazy var returnUrlTextField: TextFieldView = {
let textField = TextFieldView(placeholderText: "Return URL", keyboardType: .URL)
textField.textField.autocorrectionType = .no
textField.textField.autocapitalizationType = .none
textField.textField.clearButtonMode = .whileEditing
return textField
}()

init(isSposReader: Bool) {
self.isSposReader = isSposReader
super.init(style: .grouped)
Expand Down Expand Up @@ -135,6 +162,8 @@ private lazy var offlineStoredTransactionLimitTextField: TextFieldView = {
surchargeNoticeTextField.textField.delegate = self
amountSurchargeTextField.textField.delegate = self

returnUrlTextField.textField.delegate = self

amountView.onAmountUpdated = { [unowned self] amountString in
self.startSection?.header = Section.Extremity.title(amountString)
self.updateContent()
Expand Down Expand Up @@ -242,6 +271,10 @@ private lazy var offlineStoredTransactionLimitTextField: TextFieldView = {
}
}

if let returnUrl = returnUrlTextField.textField.text {
confirmConfigBuilder.setReturnUrl(returnUrl)
}

do {
if let eligibleAmount = Int(tipEligibleAmountTextField.textField.text ?? "none") {
collectConfigBuilder.setTippingConfiguration(
Expand All @@ -250,6 +283,9 @@ private lazy var offlineStoredTransactionLimitTextField: TextFieldView = {
.build()
)
}
if let onReceiptAmount = UInt(postAuthTipAmountTextField.textField.text ?? "0") {
onReceiptTip = onReceiptAmount
}
let collectConfig = try collectConfigBuilder.build()
let confirmConfig = try confirmConfigBuilder.build()
let vc = PaymentViewController(paymentParams: try paymentParamsBuilder.build(),
Expand All @@ -261,7 +297,8 @@ private lazy var offlineStoredTransactionLimitTextField: TextFieldView = {
offlineTransactionLimit: Int(offlineTransactionLimitTextField.textField.text ?? "10000") ?? 10000,
offlineTotalTransactionLimit: Int(offlineStoredTransactionLimitTextField.textField.text ?? "50000") ?? 50000,
offlineBehavior: self.offlineBehavior,
skipCapture: self.skipCapture
skipCapture: self.skipCapture,
onReceiptTip: self.onReceiptTip
)
let navController = LargeTitleNavigationController(rootViewController: vc)
navController.presentationController?.delegate = self
Expand Down Expand Up @@ -317,7 +354,7 @@ private lazy var offlineStoredTransactionLimitTextField: TextFieldView = {
self.skipTipping.toggle()
self.updateContent()
})],
footer: .autoLayoutView(tipEligibleAmountTextField))
footer: .autoLayoutView(tipFields))
}

private func makeTransactionSection() -> Section? {
Expand Down Expand Up @@ -557,6 +594,12 @@ private lazy var offlineStoredTransactionLimitTextField: TextFieldView = {
return offlineTransactionLimitSection
}

/// Makes the "Return URL" section.
private func makeReturnUrlSection() -> Section {
let returnUrlSection = Section(header: .title("Return URL"), rows: [], footer: .autoLayoutView(returnUrlTextField))
return returnUrlSection
}

private func updateContent() {

let sections: [Section?] = [
Expand All @@ -577,6 +620,7 @@ private lazy var offlineStoredTransactionLimitTextField: TextFieldView = {
self.makeOfflineStoredTransactionLimitSection(),
self.makeOfflineBehaviorSection(),
self.makeSetupFutureUsageSection(),
self.makeReturnUrlSection(),
self.startSection
]

Expand Down
31 changes: 31 additions & 0 deletions Example/Example/UIViewController+Presentation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// UIViewController+Presentation.swift
// Example
//
// Created by Brian Cooke on 10/18/24.
// Copyright © 2024 Stripe. All rights reserved.
//

import UIKit

extension UIViewController {
func topViewController() -> UIViewController? {
guard let keyWindow = UIApplication.shared.connectedScenes
.filter({$0.activationState == .foregroundActive})
.compactMap({$0 as? UIWindowScene})
.first?.windows
.filter({$0.isKeyWindow}).first else {
return nil
}


guard var topViewController = keyWindow.rootViewController else {
return nil
}

while let presentedViewController = topViewController.presentedViewController {
topViewController = presentedViewController
}
return topViewController
}
}
2 changes: 1 addition & 1 deletion Example/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 4b74d0597959469ee954001e3536226231ca6150

COCOAPODS: 1.15.2
COCOAPODS: 1.16.2
2 changes: 1 addition & 1 deletion Example/Pods/Manifest.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading