Add more StripeApplePay telemetry (#737)

This commit is contained in:
davidme-stripe 2022-02-11 13:27:29 -08:00 committed by GitHub
parent 5fb187e8a5
commit 8dd77fadab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 268 additions and 30 deletions

View File

@ -567,7 +567,7 @@
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 15.2;
IPHONEOS_DEPLOYMENT_TARGET = 14.5;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -601,7 +601,7 @@
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 15.2;
IPHONEOS_DEPLOYMENT_TARGET = 14.5;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -625,7 +625,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.2;
IPHONEOS_DEPLOYMENT_TARGET = 14.5;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.stripe.AppClipExample.AppClipExampleClipTests;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -645,7 +645,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.2;
IPHONEOS_DEPLOYMENT_TARGET = 14.5;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.stripe.AppClipExample.AppClipExampleClipTests;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -665,7 +665,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.2;
IPHONEOS_DEPLOYMENT_TARGET = 14.5;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.stripe.AppClipExample.AppClipExampleClipUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -684,7 +684,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.2;
IPHONEOS_DEPLOYMENT_TARGET = 14.5;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.stripe.AppClipExample.AppClipExampleClipUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -733,7 +733,6 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_BITCODE = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
@ -794,7 +793,6 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_BITCODE = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
@ -884,7 +882,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.2;
IPHONEOS_DEPLOYMENT_TARGET = 14.5;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.stripe.Tests-iOS";
PRODUCT_NAME = "$(TARGET_NAME)";
@ -903,7 +901,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.2;
IPHONEOS_DEPLOYMENT_TARGET = 14.5;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.stripe.Tests-iOS";
PRODUCT_NAME = "$(TARGET_NAME)";

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1320"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "31FBFDF92789135600AB706D"
BuildableName = "AppClipExample.app"
BlueprintName = "AppClipExample (iOS)"
ReferencedContainer = "container:AppClipExample.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "NO"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "31FBFE062789135600AB706D"
BuildableName = "Tests iOS.xctest"
BlueprintName = "Tests iOS"
ReferencedContainer = "container:AppClipExample.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "31FBFDF92789135600AB706D"
BuildableName = "AppClipExample.app"
BlueprintName = "AppClipExample (iOS)"
ReferencedContainer = "container:AppClipExample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "31FBFDF92789135600AB706D"
BuildableName = "AppClipExample.app"
BlueprintName = "AppClipExample (iOS)"
ReferencedContainer = "container:AppClipExample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -30,7 +30,7 @@ class MyApplePayBackendModel : NSObject, ObservableObject, ApplePayContextDelega
let rocketRidesShipping = PKShippingMethod(label: "Rocket Rides courier", amount: NSDecimalNumber(string: "10.99"))
rocketRidesShipping.detail = "Arrives in 1-2 hours"
rocketRidesShipping.identifier = "rocketrides"
pr.shippingMethods = [
pr.shippingMethods = [
firstClassShipping,
rocketRidesShipping
]
@ -48,7 +48,7 @@ class MyApplePayBackendModel : NSObject, ObservableObject, ApplePayContextDelega
applePayContext?.presentApplePay()
}
func applePayContext(_ context: STPApplePayContext, didCreatePaymentMethod paymentMethod: StripeAPI.PaymentMethod, paymentInformation: PKPayment, completion: @escaping IntentClientSecretCompletionBlock) {
func applePayContext(_ context: STPApplePayContext, didCreatePaymentMethod paymentMethod: StripeAPI.PaymentMethod, paymentInformation: PKPayment, completion: @escaping STPIntentClientSecretCompletionBlock) {
// When the Apple Pay sheet is confirmed, create a PaymentIntent on your backend from the provided PKPayment information.
BackendModel.shared.fetchPaymentIntent() { secret in
if let clientSecret = secret {

View File

@ -49,8 +49,7 @@ class BackendModel {
let task = URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in
guard let unwrappedData = data,
let json = try? JSONSerialization.jsonObject(with: unwrappedData, options: []) as? [String : Any],
let publishableKey = json["publishableKey"] as? String else {
let json = try? JSONSerialization.jsonObject(with: unwrappedData, options: []) as? [String : Any] else {
if let data = data {
print("\(String(decoding: data, as: UTF8.self))")
} else {

View File

@ -9,10 +9,6 @@ import XCTest
class Tests_iOSLaunchTests: XCTestCase {
override class var runsForEachTargetApplicationUIConfiguration: Bool {
true
}
override func setUpWithError() throws {
continueAfterFailure = false
}

View File

@ -166,7 +166,6 @@
3137A74826FD76F2008BEF7B /* STPAPIClientNetworkBridgeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 3137A74326FD7687008BEF7B /* STPAPIClientNetworkBridgeTest.m */; };
3137A74C26FD7710008BEF7B /* STPErrorBridgeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 3137A74A26FD7710008BEF7B /* STPErrorBridgeTest.m */; };
3137A74D26FD7AF5008BEF7B /* (null) in Sources */ = {isa = PBXBuildFile; };
3137A74F26FE8754008BEF7B /* URLRequest+StripeTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3137A74E26FE8754008BEF7B /* URLRequest+StripeTest.swift */; };
3137B69727437F5A00CE7F5C /* StripeApplePay.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3137B69627437F5A00CE7F5C /* StripeApplePay.framework */; };
315E4B302639C86B00C1D955 /* STPIntentActionWeChatPayRedirectToApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 315E4B2F2639C86B00C1D955 /* STPIntentActionWeChatPayRedirectToApp.swift */; };
315E4B362639D80F00C1D955 /* STPIntentActionWeChatPayRedirectToAppTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 315E4B352639D80F00C1D955 /* STPIntentActionWeChatPayRedirectToAppTest.swift */; };
@ -1002,7 +1001,6 @@
31319EE025B11C8A00C89E30 /* PaymentSheet+SwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PaymentSheet+SwiftUI.swift"; sourceTree = "<group>"; };
3137A74326FD7687008BEF7B /* STPAPIClientNetworkBridgeTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = STPAPIClientNetworkBridgeTest.m; sourceTree = "<group>"; };
3137A74A26FD7710008BEF7B /* STPErrorBridgeTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = STPErrorBridgeTest.m; sourceTree = "<group>"; };
3137A74E26FE8754008BEF7B /* URLRequest+StripeTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URLRequest+StripeTest.swift"; sourceTree = "<group>"; };
3137B69627437F5A00CE7F5C /* StripeApplePay.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = StripeApplePay.framework; sourceTree = BUILT_PRODUCTS_DIR; };
315E4B2F2639C86B00C1D955 /* STPIntentActionWeChatPayRedirectToApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPIntentActionWeChatPayRedirectToApp.swift; sourceTree = "<group>"; };
315E4B352639D80F00C1D955 /* STPIntentActionWeChatPayRedirectToAppTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPIntentActionWeChatPayRedirectToAppTest.swift; sourceTree = "<group>"; };
@ -3120,7 +3118,6 @@
D00C2D192735C0C100E2283D /* OneTimeCodeTextFieldTests.swift */,
D05B97ED270619130068B5C0 /* UIColor+StripeTests.swift */,
F1122A7D1DFB84E000A8B1AF /* UINavigationBar+StripeTest.m */,
3137A74E26FE8754008BEF7B /* URLRequest+StripeTest.swift */,
B6E8A93D26580A6F00A48CC8 /* UserDefaults+StripeTest.swift */,
);
name = Unit;
@ -3931,7 +3928,6 @@
61A378612721C48000B949C5 /* STPPaymentMethodKlarnaTests.swift in Sources */,
3111C70F252D4B0A00207E32 /* STPSourceCardDetailsTest.swift in Sources */,
3111C62E252D3F1E00207E32 /* STPLabeledMultiFormTextFieldViewSnapshotTests.swift in Sources */,
3137A74F26FE8754008BEF7B /* URLRequest+StripeTest.swift in Sources */,
3194CF5C2314869500E1940F /* STPPaymentMethodFPXTest.m in Sources */,
B6D6C935223078840092AFC8 /* STPPaymentMethodBillingDetailsTest.m in Sources */,
3111C568252BDCF400207E32 /* STPAddCardViewControllerLocalizationTests.swift in Sources */,

View File

@ -8,8 +8,11 @@
/* Begin PBXBuildFile section */
312656FF27AC9BBF00D2F8A8 /* STPAnalyticsClient+ApplePayTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 312656FE27AC9BBF00D2F8A8 /* STPAnalyticsClient+ApplePayTest.swift */; };
3126570127B47F3100D2F8A8 /* TelemetryInjectionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3126570027B47F3100D2F8A8 /* TelemetryInjectionTest.swift */; };
3126570627B58BAE00D2F8A8 /* OHHTTPStubs.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3126570427B58BA400D2F8A8 /* OHHTTPStubs.xcframework */; };
3137B6AD2743816300CE7F5C /* StripeCore+Import.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3137B6AC2743816300CE7F5C /* StripeCore+Import.swift */; };
3137B6AF2743837400CE7F5C /* StripeCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3137B6AE2743837400CE7F5C /* StripeCore.framework */; };
313A2A8527B5EBCE00E5EA99 /* StripeCoreTestUtils.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 313A2A8427B5EBCE00E5EA99 /* StripeCoreTestUtils.framework */; };
315BDBE12788E9D8007BD11F /* STPAPIClient+ApplePay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 315BDBE02788E9D8007BD11F /* STPAPIClient+ApplePay.swift */; };
3163E4A22787BB8200956D86 /* STPApplePayContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3163E4A12787BB8200956D86 /* STPApplePayContext.swift */; };
3163E4A42787BD0E00956D86 /* Blocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3163E4A32787BD0E00956D86 /* Blocks.swift */; };
@ -69,9 +72,12 @@
/* Begin PBXFileReference section */
312656FE27AC9BBF00D2F8A8 /* STPAnalyticsClient+ApplePayTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "STPAnalyticsClient+ApplePayTest.swift"; sourceTree = "<group>"; };
3126570027B47F3100D2F8A8 /* TelemetryInjectionTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TelemetryInjectionTest.swift; sourceTree = "<group>"; };
3126570427B58BA400D2F8A8 /* OHHTTPStubs.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = OHHTTPStubs.xcframework; path = ../Carthage/Build/OHHTTPStubs.xcframework; sourceTree = "<group>"; };
3137B690274330E200CE7F5C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3137B6AC2743816300CE7F5C /* StripeCore+Import.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StripeCore+Import.swift"; sourceTree = "<group>"; };
3137B6AE2743837400CE7F5C /* StripeCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = StripeCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
313A2A8427B5EBCE00E5EA99 /* StripeCoreTestUtils.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = StripeCoreTestUtils.framework; sourceTree = BUILT_PRODUCTS_DIR; };
315BDBE02788E9D8007BD11F /* STPAPIClient+ApplePay.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "STPAPIClient+ApplePay.swift"; sourceTree = "<group>"; };
3163E4A12787BB8200956D86 /* STPApplePayContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = STPApplePayContext.swift; sourceTree = "<group>"; };
3163E4A32787BD0E00956D86 /* Blocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Blocks.swift; path = ../Blocks.swift; sourceTree = "<group>"; };
@ -133,8 +139,10 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
313A2A8527B5EBCE00E5EA99 /* StripeCoreTestUtils.framework in Frameworks */,
319E82F82743191200F202D6 /* StripeApplePayTestUtils.framework in Frameworks */,
3181D736273A00BF00525C02 /* StripeApplePay.framework in Frameworks */,
3126570627B58BAE00D2F8A8 /* OHHTTPStubs.xcframework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -196,6 +204,7 @@
children = (
31E6D9742744591A00A89B6D /* PaymentsCore */,
31E6D95B274440B900A89B6D /* STPPaymentMethodFunctionalTest.swift */,
3126570027B47F3100D2F8A8 /* TelemetryInjectionTest.swift */,
312656FE27AC9BBF00D2F8A8 /* STPAnalyticsClient+ApplePayTest.swift */,
3181D73A273A00BF00525C02 /* StripeApplePayTests.swift */,
);
@ -243,6 +252,8 @@
319E82F62743190B00F202D6 /* Frameworks */ = {
isa = PBXGroup;
children = (
313A2A8427B5EBCE00E5EA99 /* StripeCoreTestUtils.framework */,
3126570427B58BA400D2F8A8 /* OHHTTPStubs.xcframework */,
3137B6AE2743837400CE7F5C /* StripeCore.framework */,
);
name = Frameworks;
@ -526,6 +537,7 @@
buildActionMask = 2147483647;
files = (
312656FF27AC9BBF00D2F8A8 /* STPAnalyticsClient+ApplePayTest.swift in Sources */,
3126570127B47F3100D2F8A8 /* TelemetryInjectionTest.swift in Sources */,
31E6D9722744591800A89B6D /* STPTelemetryClientTest.swift in Sources */,
31E6D9732744591800A89B6D /* STPTelemetryClientFunctionalTest.swift in Sources */,
31E6D95C274440B900A89B6D /* STPPaymentMethodFunctionalTest.swift in Sources */,

View File

@ -25,6 +25,7 @@ extension StripeAPI {
/// Provide a supported `PaymentMethodParams` object, and Stripe will create a
/// PaymentMethod during PaymentIntent confirmation.
/// @note alternative to `paymentMethodId`
@IncludeUnknownFields
@_spi(STP) public var paymentMethodData: PaymentMethodParams?
/// Provide an already created PaymentMethod's id, and it will be used to confirm the PaymentIntent.

View File

@ -12,9 +12,9 @@ import Foundation
extension StripeAPI {
@_spi(STP) public struct SetupIntentConfirmParams: StripeEncodable {
/// Generated by by Editor -> Refactor -> Generate Memberwise Initializer
@_spi(STP) public init(clientSecret: String, paymentMethodParams: StripeAPI.PaymentMethodParams? = nil, paymentMethod: String? = nil, returnURL: String? = nil, useStripeSdk: Bool? = nil, _additionalParametersStorage: NonEncodableParameters? = nil) {
@_spi(STP) public init(clientSecret: String, paymentMethodData: StripeAPI.PaymentMethodParams? = nil, paymentMethod: String? = nil, returnURL: String? = nil, useStripeSdk: Bool? = nil, _additionalParametersStorage: NonEncodableParameters? = nil) {
self.clientSecret = clientSecret
self.paymentMethodParams = paymentMethodParams
self.paymentMethodData = paymentMethodData
self.paymentMethod = paymentMethod
self.returnURL = returnURL
self.useStripeSdk = useStripeSdk
@ -26,7 +26,8 @@ extension StripeAPI {
/// Provide a supported `PaymentMethodParams` object, and Stripe will create a
/// PaymentMethod during PaymentIntent confirmation.
/// @note alternative to `paymentMethodId`
@_spi(STP) public var paymentMethodParams: PaymentMethodParams?
@IncludeUnknownFields
@_spi(STP) public var paymentMethodData: PaymentMethodParams?
/// Provide an already created PaymentMethod's id, and it will be used to confirm the SetupIntent.
/// @note alternative to `paymentMethodParams`
@_spi(STP) public var paymentMethod: String?

View File

@ -51,13 +51,28 @@ extension StripeAPI.PaymentIntent {
params: StripeAPI.PaymentIntentParams,
completion: @escaping PaymentIntentCompletionBlock
) {
assert(
StripeAPI.PaymentIntentParams.isClientSecretValid(params.clientSecret),
"`paymentIntentParams.clientSecret` format does not match expected client secret formatting."
)
guard let identifier = StripeAPI.PaymentIntent.id(fromClientSecret: params.clientSecret) else {
completion(.failure(StripeError.invalidRequest))
return
}
let endpoint = "\(Resource)/\(identifier)/confirm"
apiClient.post(resource: endpoint, object: params, completion: completion)
let type = params.paymentMethodData?.type.rawValue
STPAnalyticsClient.sharedClient.logPaymentIntentConfirmationAttempt(
paymentMethodType: type)
// Add telemetry
var paramsWithTelemetry = params
if let pmAdditionalParams = paramsWithTelemetry.paymentMethodData?.additionalParameters {
paramsWithTelemetry.paymentMethodData?.additionalParameters = STPTelemetryClient.shared.paramsByAddingTelemetryFields(toParams: pmAdditionalParams)
}
apiClient.post(resource: endpoint, object: paramsWithTelemetry, completion: completion)
}
static let Resource = "payment_intents"

View File

@ -51,13 +51,28 @@ extension StripeAPI.SetupIntent {
params: StripeAPI.SetupIntentConfirmParams,
completion: @escaping SetupIntentCompletionBlock
) {
assert(
StripeAPI.SetupIntentConfirmParams.isClientSecretValid(params.clientSecret),
"`setupIntentConfirmParams.clientSecret` format does not match expected client secret formatting."
)
guard let identifier = StripeAPI.SetupIntent.id(fromClientSecret: params.clientSecret) else {
completion(.failure(StripeError.invalidRequest))
return
}
let endpoint = "\(Resource)/\(identifier)/confirm"
let type = params.paymentMethodData?.type.rawValue
STPAnalyticsClient.sharedClient.logSetupIntentConfirmationAttempt(
paymentMethodType: type)
apiClient.post(resource: endpoint, object: params, completion: completion)
// Add telemetry
var paramsWithTelemetry = params
if let pmAdditionalParams = paramsWithTelemetry.paymentMethodData?.additionalParameters {
paramsWithTelemetry.paymentMethodData?.additionalParameters = STPTelemetryClient.shared.paramsByAddingTelemetryFields(toParams: pmAdditionalParams)
}
apiClient.post(resource: endpoint, object: paramsWithTelemetry, completion: completion)
}
static let Resource = "setup_intents"

View File

@ -30,6 +30,30 @@ extension STPAnalyticsClient {
]
))
}
func logPaymentIntentConfirmationAttempt(
paymentMethodType: String?
) {
log(analytic: PaymentAPIAnalytic(
event: .paymentMethodIntentCreation,
productUsage: productUsage,
additionalParams: [
"source_type": paymentMethodType ?? "unknown"
]
))
}
func logSetupIntentConfirmationAttempt(
paymentMethodType: String?
) {
log(analytic: PaymentAPIAnalytic(
event: .setupIntentConfirmationAttempt,
productUsage: productUsage,
additionalParams: [
"source_type": paymentMethodType ?? "unknown"
]
))
}
}
struct PaymentAPIAnalytic: PaymentAnalytic {

View File

@ -0,0 +1,84 @@
//
// TelemetryInjectionTest.swift
// StripeApplePayTests
//
// Created by David Estes on 2/9/22.
//
import Foundation
import OHHTTPStubs
import StripeCoreTestUtils
@_spi(STP) @testable import StripeApplePay
@_spi(STP) @testable import StripeCore
import AVFoundation
import XCTest
class TelemetryInjectionTest: APIStubbedTestCase {
func testIntentConfirmAddsTelemetry() {
let apiClient = stubbedAPIClient()
let piTelemetryExpectation = self.expectation(description: "saw pi telemetry")
let siTelemetryExpectation = self.expectation(description: "saw si telemetry")
// As an implementation detail, OHHTTPStubs will run this block in `canInitWithRequest` in addition to
// `initWithRequest`. So it could be called more times than we expect.
// We don't have control over this behavior (CFNetwork drives it), so let's not worry
// about overfulfillment.
piTelemetryExpectation.assertForOverFulfill = false
siTelemetryExpectation.assertForOverFulfill = false
stub { urlRequest in
if urlRequest.url!.absoluteString.contains("_intent") {
let ua = urlRequest.queryItems!.first(where: { $0.name == "payment_method_data[payment_user_agent]" })!.value!
XCTAssertTrue(ua.hasPrefix("stripe-ios/"))
let muid = urlRequest.queryItems!.first(where: { $0.name == "payment_method_data[muid]" })!.value!
let guid = urlRequest.queryItems!.first(where: { $0.name == "payment_method_data[guid]" })!.value!
XCTAssertNotNil(muid)
XCTAssertNotNil(guid)
if urlRequest.url!.absoluteString.contains("payment_intent") {
piTelemetryExpectation.fulfill()
}
if urlRequest.url!.absoluteString.contains("setup_intent") {
siTelemetryExpectation.fulfill()
}
return true
}
return false
} response: { urlRequest in
// We don't care about the response
return HTTPStubsResponse()
}
let params = StripeAPI.PaymentMethodParams(type: .card)
var card = StripeAPI.PaymentMethodParams.Card()
card.number = "4242424242424242"
card.expYear = 28
card.expMonth = 12
card.cvc = "100"
// Set up telemetry data
StripeAPI.advancedFraudSignalsEnabled = true
FraudDetectionData.shared.sid = "sid"
FraudDetectionData.shared.muid = "muid"
FraudDetectionData.shared.guid = "guid"
FraudDetectionData.shared.sidCreationDate = Date()
let piExpectation = self.expectation(description: "PI Confirmed")
var pip = StripeAPI.PaymentIntentParams(clientSecret: "pi_123_secret_abc")
pip.paymentMethodData = params
StripeAPI.PaymentIntent.confirm(apiClient: apiClient, params: pip) { _ in
piExpectation.fulfill()
}
let siExpectation = self.expectation(description: "SI Confirmed")
var sip = StripeAPI.SetupIntentConfirmParams(clientSecret: "seti_123_secret_abc")
sip.paymentMethodData = params
StripeAPI.SetupIntent.confirm(apiClient: apiClient, params: sip) { _ in
siExpectation.fulfill()
}
waitForExpectations(timeout: STPTestingNetworkRequestTimeout, handler: nil)
}
}

View File

@ -8,9 +8,10 @@
/* Begin PBXBuildFile section */
310AF470271E12F6007339F4 /* Dictionary+Stripe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 310AF46F271E12F6007339F4 /* Dictionary+Stripe.swift */; };
3126570327B4852600D2F8A8 /* URLRequest+StripeTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3126570227B4852600D2F8A8 /* URLRequest+StripeTest.swift */; };
31337A4926E04B6A005C7E02 /* URLSession+Retry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31337A4826E04B6A005C7E02 /* URLSession+Retry.swift */; };
317C4FE0275FF44D003771D7 /* InstallMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 317C4FDF275FF44D003771D7 /* InstallMethod.swift */; };
315BDBDF2788E2B4007BD11F /* STPDispatchFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 315BDBDE2788E2B4007BD11F /* STPDispatchFunctions.swift */; };
317C4FE0275FF44D003771D7 /* InstallMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 317C4FDF275FF44D003771D7 /* InstallMethod.swift */; };
319E36582719EBF700460867 /* ServerErrorMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319E36572719EBF700460867 /* ServerErrorMapper.swift */; };
31A5269226C46D9600F8AB59 /* STPAppInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31A5269126C46D9500F8AB59 /* STPAppInfo.swift */; };
31A5269426C46E2C00F8AB59 /* StripeAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31A5269326C46E2C00F8AB59 /* StripeAPI.swift */; };
@ -110,9 +111,10 @@
/* Begin PBXFileReference section */
310AF46F271E12F6007339F4 /* Dictionary+Stripe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Dictionary+Stripe.swift"; sourceTree = "<group>"; };
3126570227B4852600D2F8A8 /* URLRequest+StripeTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "URLRequest+StripeTest.swift"; sourceTree = "<group>"; };
31337A4826E04B6A005C7E02 /* URLSession+Retry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URLSession+Retry.swift"; sourceTree = "<group>"; };
317C4FDF275FF44D003771D7 /* InstallMethod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstallMethod.swift; sourceTree = "<group>"; };
315BDBDE2788E2B4007BD11F /* STPDispatchFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = STPDispatchFunctions.swift; sourceTree = "<group>"; };
317C4FDF275FF44D003771D7 /* InstallMethod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstallMethod.swift; sourceTree = "<group>"; };
319E36572719EBF700460867 /* ServerErrorMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerErrorMapper.swift; sourceTree = "<group>"; };
31A5268D26C46CFE00F8AB59 /* StripeCodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StripeCodable.swift; sourceTree = "<group>"; };
31A5269126C46D9500F8AB59 /* STPAppInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = STPAppInfo.swift; sourceTree = "<group>"; };
@ -526,6 +528,7 @@
E6FB9BA9268EA7BD000FDB4F /* Mocks */,
E6FB9BBA268EA95F000FDB4F /* StripeCoreTestUtils.h */,
E6548EE52728AFB400F399B2 /* TestConstants.swift */,
3126570227B4852600D2F8A8 /* URLRequest+StripeTest.swift */,
E6548F7E27339FB100F399B2 /* XCTestCase+Stripe.swift */,
);
path = StripeCoreTestUtils;
@ -834,6 +837,7 @@
E6548EDF2728AEBE00F399B2 /* APIStubbedTestCase.swift in Sources */,
E6548F7F27339FB100F399B2 /* XCTestCase+Stripe.swift in Sources */,
D0CA3DA5279BE0CE00143B1C /* KeyPathExpectation.swift in Sources */,
3126570327B4852600D2F8A8 /* URLRequest+StripeTest.swift in Sources */,
E6548EE62728AFB400F399B2 /* TestConstants.swift in Sources */,
E6548EF22729BDD700F399B2 /* MockData.swift in Sources */,
);

View File

@ -8,7 +8,7 @@
import Foundation
extension URLRequest {
public extension URLRequest {
/// A Data representation of the response's body,
/// fetched from the body Data or body InputStream.
var httpBodyOrBodyStream: Data? {

View File

@ -61,6 +61,7 @@ platform :ios do
sh("./ci_scripts/test.rb --build-only --scheme 'IntegrationTester'")
sh("./ci_scripts/test.rb --build-only --scheme 'LocalizationTester'")
sh("./ci_scripts/test.rb --build-only --scheme 'PaymentSheet Example'")
sh("./ci_scripts/test.rb --build-only --scheme 'AppClipExample'")
end
end