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

Add validation to catch blank ephemeral keys in CustomerConfiguration #2517

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
### Payments
* [Fixed] STPPaymentHandler.handleNextAction allows payment methods that are delayed or require further customer action like like SEPA Debit or OXXO.

### PaymentSheet
* [Added] Improved validation for ephemeral keys.

## 23.7.0 2023-04-24
### PaymentSheet
* [Fixed] Fixed disabled text color, using a lower opacity version of the original color instead of the previous `.tertiaryLabel`.
Expand Down
4 changes: 2 additions & 2 deletions Stripe/StripeiOSTests/PaymentSheet+APITest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ class PaymentSheetAPITest: XCTestCase {
paymentIntentParams.paymentMethodOptions?.setSetupFutureUsageIfNecessary(
true,
paymentMethodType: PaymentSheet.PaymentMethodType.card,
customer: .init(id: "", ephemeralKeySecret: "")
customer: .init(id: "", ephemeralKeySecret: "foo")
)

let params = STPFormEncoder.dictionary(forObject: paymentIntentParams)
Expand All @@ -564,7 +564,7 @@ class PaymentSheetAPITest: XCTestCase {
paymentIntentParams.paymentMethodOptions?.setSetupFutureUsageIfNecessary(
false,
paymentMethodType: PaymentSheet.PaymentMethodType.card,
customer: .init(id: "", ephemeralKeySecret: "")
customer: .init(id: "", ephemeralKeySecret: "foo")
)

let params = STPFormEncoder.dictionary(forObject: paymentIntentParams)
Expand Down
2 changes: 1 addition & 1 deletion StripePaymentSheet/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ let project = Project.stripeFramework(
.project(target: "StripePayments", path: "//StripePayments"),
.project(target: "StripePaymentsUI", path: "//StripePaymentsUI"),
],
unitTestOptions: .testOptions()
unitTestOptions: .testOptions(usesPreconditionTesting: true)
)
Original file line number Diff line number Diff line change
Expand Up @@ -172,11 +172,13 @@ extension PaymentSheet {
/// See https://stripe.com/docs/api/customers/object#customer_object-id
public let id: String

/// A short-lived token that allows the SDK to access a Customer's payment methods
/// A short-lived token that allows the SDK to access a Customer's payment methods. Cannot be empty.
public let ephemeralKeySecret: String

/// Initializes a CustomerConfiguration
public init(id: String, ephemeralKeySecret: String) {
assert(!ephemeralKeySecret.isEmpty, "Ephemeral key secret cannot be empty")

self.id = id
self.ephemeralKeySecret = ephemeralKeySecret
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// PaymentSheetConfigurationTests.swift
// StripePaymentSheetTests
//
// Copyright © 2023 Stripe, Inc. All rights reserved.
//

import CwlPreconditionTesting
import StripePaymentSheet
import XCTest

final class PaymentSheetConfigurationTests: XCTestCase {

func test_customerConfigurationInit_assertsWhenEphemeralKeyIsBlank() {
let exception = catchBadInstruction {
_ = PaymentSheet.CustomerConfiguration(id: "foo", ephemeralKeySecret: "")
}

XCTAssertNotNil(exception)
}
}
28 changes: 26 additions & 2 deletions Tuist/ProjectDescriptionHelpers/Tuist+Stripe.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ extension Project {
public var includesSnapshots: Bool = false
public var usesMocks: Bool = false
public var usesStubs: Bool = false
public var usesPreconditionTesting: Bool = false

/// Creates a `TestOptions` instance.
///
Expand All @@ -28,6 +29,8 @@ extension Project {
/// If `true`, the OCMock package will be linked.
/// - usesStubs: Whether the tests in this target use stubs.
/// If `true`, the OHHTTPStubs package will be linked.
/// - usesPreconditionTesting: Whether the tests in this target use precondition, assert, and/or fatal error testing.
/// If `true`, the CwlPreconditionTesting package will be linked.
/// - Returns: A `TestOptions` instance.
public static func testOptions(
resources: ResourceFileElements? = nil,
Expand All @@ -37,15 +40,17 @@ extension Project {
),
includesSnapshots: Bool = false,
usesMocks: Bool = false,
usesStubs: Bool = false
usesStubs: Bool = false,
usesPreconditionTesting: Bool = false
) -> TestOptions {
return TestOptions(
resources: resources,
dependencies: dependencies,
settings: settings,
includesSnapshots: includesSnapshots,
usesMocks: usesMocks,
usesStubs: usesStubs
usesStubs: usesStubs,
usesPreconditionTesting: usesPreconditionTesting
)
}
}
Expand Down Expand Up @@ -160,6 +165,7 @@ extension Project {
)
)
}

if testUtilsOptions?.usesMocks ?? false
|| unitTestOptions?.usesMocks ?? false
|| uiTestOptions?.usesMocks ?? false
Expand All @@ -168,6 +174,7 @@ extension Project {
.remote(url: "https://github.com/erikdoe/ocmock", requirement: .branch("master"))
)
}

if testUtilsOptions?.usesStubs ?? false
|| unitTestOptions?.usesStubs ?? false
|| uiTestOptions?.usesStubs ?? false
Expand All @@ -179,6 +186,19 @@ extension Project {
)
)
}

if testUtilsOptions?.usesPreconditionTesting ?? false
|| unitTestOptions?.usesPreconditionTesting ?? false
|| uiTestOptions?.usesPreconditionTesting ?? false
{
packages.append(
.remote(
url: "https://github.com/mattgallagher/CwlPreconditionTesting",
requirement: .upToNextMajor(from: "2.1.2")
)
)
}

return packages
}

Expand Down Expand Up @@ -301,6 +321,10 @@ extension Project {
.package(product: "OHHTTPStubsSwift"),
]
}
if testOptions.usesPreconditionTesting {
dependencies.append(.package(product: "CwlPreconditionTesting"))
}

return dependencies + testOptions.dependencies
}

Expand Down