diff --git a/Braintree.xcodeproj/project.pbxproj b/Braintree.xcodeproj/project.pbxproj index b48912fe5b..05189c9654 100644 --- a/Braintree.xcodeproj/project.pbxproj +++ b/Braintree.xcodeproj/project.pbxproj @@ -86,6 +86,10 @@ 8053F05929FB2F700076F988 /* URL+IsPayPal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8053F05829FB2F700076F988 /* URL+IsPayPal.swift */; }; 80581A8C25531D0A00006F53 /* BTConfiguration+ThreeDSecure_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80581A8B25531D0A00006F53 /* BTConfiguration+ThreeDSecure_Tests.swift */; }; 80581B1D2553319C00006F53 /* BTGraphQLHTTP_SSLPinning_IntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80581B1C2553319C00006F53 /* BTGraphQLHTTP_SSLPinning_IntegrationTests.swift */; }; + 8064F38F2B1E492F0059C4CB /* BTShopperInsightsClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8064F38E2B1E492F0059C4CB /* BTShopperInsightsClient.swift */; }; + 8064F3912B1E49E10059C4CB /* BTShopperInsightsResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8064F3902B1E49E10059C4CB /* BTShopperInsightsResult.swift */; }; + 8064F3952B1E4FEB0059C4CB /* BTShopperInsightsClient_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8064F3942B1E4FEB0059C4CB /* BTShopperInsightsClient_Tests.swift */; }; + 8064F3972B1E63800059C4CB /* BTShopperInsightsRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8064F3962B1E63800059C4CB /* BTShopperInsightsRequest.swift */; }; 80BA64AC29D788E000E15264 /* BTLocalPaymentResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80BA64AB29D788E000E15264 /* BTLocalPaymentResult.swift */; }; 80BA64B229D7937E00E15264 /* BTLocalPaymentRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80BA64B129D7937E00E15264 /* BTLocalPaymentRequest.swift */; }; 80BA64B429D795D000E15264 /* BTLocalPaymentRequestDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80BA64B329D795D000E15264 /* BTLocalPaymentRequestDelegate.swift */; }; @@ -699,6 +703,10 @@ 80581A8B25531D0A00006F53 /* BTConfiguration+ThreeDSecure_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BTConfiguration+ThreeDSecure_Tests.swift"; sourceTree = ""; }; 80581B1C2553319C00006F53 /* BTGraphQLHTTP_SSLPinning_IntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTGraphQLHTTP_SSLPinning_IntegrationTests.swift; sourceTree = ""; }; 805FD35B2331780F0000B514 /* BTPostalAddress_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTPostalAddress_Tests.swift; sourceTree = ""; }; + 8064F38E2B1E492F0059C4CB /* BTShopperInsightsClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTShopperInsightsClient.swift; sourceTree = ""; }; + 8064F3902B1E49E10059C4CB /* BTShopperInsightsResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTShopperInsightsResult.swift; sourceTree = ""; }; + 8064F3942B1E4FEB0059C4CB /* BTShopperInsightsClient_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTShopperInsightsClient_Tests.swift; sourceTree = ""; }; + 8064F3962B1E63800059C4CB /* BTShopperInsightsRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTShopperInsightsRequest.swift; sourceTree = ""; }; 80A1EE3D2236AAC600F6218B /* BTThreeDSecureAdditionalInformation_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTThreeDSecureAdditionalInformation_Tests.swift; sourceTree = ""; }; 80B6190C28C9535F00FB5022 /* PayPalCheckout.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = PayPalCheckout.xcframework; path = Frameworks/XCFrameworks/PayPalCheckout.xcframework; sourceTree = ""; }; 80BA64AB29D788E000E15264 /* BTLocalPaymentResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTLocalPaymentResult.swift; sourceTree = ""; }; @@ -1184,6 +1192,9 @@ 5708E0A728809BC6007946B9 /* BTJSONError.swift */, 570B93D82853C6180041BAFE /* BTLogLevel.swift */, 570B93D62853C29A0041BAFE /* BTLogLevelDescription.swift */, + 8064F38E2B1E492F0059C4CB /* BTShopperInsightsClient.swift */, + 8064F3962B1E63800059C4CB /* BTShopperInsightsRequest.swift */, + 8064F3902B1E49E10059C4CB /* BTShopperInsightsResult.swift */, BE9FB82A2898324C00D6FE2F /* BTPaymentMethodNonce.swift */, BE9FB82C28984ADE00D6FE2F /* BTPaymentMethodNonceParser.swift */, BE63A3A6288F3026001936DA /* BTPostalAddress.swift */, @@ -1657,6 +1668,7 @@ BEBC6F272937BD1F004E25A0 /* BTGraphQLHTTP_Tests.swift */, BE54C0322912B68E009C6CEE /* BTHTTP_Tests.swift */, 16CD2E9E1B4077FC00E68495 /* BTJSON_Tests.swift */, + 8064F3942B1E4FEB0059C4CB /* BTShopperInsightsClient_Tests.swift */, 4149C91C1BA218830090665E /* BTPaymentMethodNonceParser_Tests.swift */, 805FD35B2331780F0000B514 /* BTPostalAddress_Tests.swift */, A7E93E571B601EE900957223 /* BTURLUtils_Tests.swift */, @@ -2735,12 +2747,14 @@ BEC3F11328A4401E0074DF0F /* BTHTTPError.swift in Sources */, 574891EB286F7E4F0020DA36 /* BTClientMetadataIntegration.swift in Sources */, BE698EA428AD2C10001D9B10 /* BTCoreConstants.swift in Sources */, + 8064F3912B1E49E10059C4CB /* BTShopperInsightsResult.swift in Sources */, BE24C67528E7491E0067B11A /* BTAPIClientAuthorization.swift in Sources */, BE32ACBC2907744400A61FED /* BTCardNetwork.swift in Sources */, 570B93D92853C6180041BAFE /* BTLogLevel.swift in Sources */, 579DAEC5286E04A700FCE87F /* BTAppContextSwitcher.swift in Sources */, 570B93D72853C29A0041BAFE /* BTLogLevelDescription.swift in Sources */, 57CBBCE828B033760037F4EE /* BTGraphQLHTTP.swift in Sources */, + 8064F38F2B1E492F0059C4CB /* BTShopperInsightsClient.swift in Sources */, BE63A3A7288F3026001936DA /* BTPostalAddress.swift in Sources */, BE2F98D028A2BCCD008EF189 /* BTConfiguration.swift in Sources */, BED00CB228A57AD400D74AEC /* BTClientTokenError.swift in Sources */, @@ -2753,6 +2767,7 @@ BE698EA028AA8DCB001D9B10 /* BTHTTP.swift in Sources */, BC17F9B428D23C5C004B18CC /* BTGraphQLMultiErrorNode.swift in Sources */, 5708E0A828809BC6007946B9 /* BTJSONError.swift in Sources */, + 8064F3972B1E63800059C4CB /* BTShopperInsightsRequest.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3035,6 +3050,7 @@ A908436324FD82C0004134CA /* BTBinData_Tests.swift in Sources */, A908436224FD82A9004134CA /* BTAppContextSwitcher_Tests.swift in Sources */, BEBC6F282937BD1F004E25A0 /* BTGraphQLHTTP_Tests.swift in Sources */, + 8064F3952B1E4FEB0059C4CB /* BTShopperInsightsClient_Tests.swift in Sources */, BE54C0352912B6BC009C6CEE /* BTHTTPTestProtocol.swift in Sources */, BEDA91A028EDDE64007441D9 /* FakeAnalyticsService.swift in Sources */, ); diff --git a/Sources/BraintreeCore/BTShopperInsightsClient.swift b/Sources/BraintreeCore/BTShopperInsightsClient.swift new file mode 100644 index 0000000000..0926b8a7ee --- /dev/null +++ b/Sources/BraintreeCore/BTShopperInsightsClient.swift @@ -0,0 +1,27 @@ +import Foundation + +/// Use `BTShopperInsightsClient` to optimize your checkout experience by prioritizing the customer’s preferred payment methods in your UI. +/// By customizing each customer’s checkout experience, you can improve conversion, increase sales/repeat buys and boost user retention/loyalty. +/// - Note: This feature is in beta. It's public API may change or be removed in future releases. +public class BTShopperInsightsClient { + + private let apiClient: BTAPIClient + + /// Creates a `BTShopperInsightsClient` + /// - Parameter apiClient: A `BTAPIClient` instance. + /// - Note: This features only works with a client token. + public init(apiClient: BTAPIClient) { + self.apiClient = apiClient + } + + /// This method confirms if the customer is a user of PayPal services using their email and phone number. + /// - Parameters: + /// - request: A `BTShopperInsightsRequest` containing the buyer's user information + /// - Returns: A `BTShopperInsightsResult` instance + /// - Note: This feature is in beta. It's public API may change or be removed in future releases. + public func getRecommendedPaymentMethods(request: BTShopperInsightsRequest) async throws -> BTShopperInsightsResult { + // TODO: - Add isAppInstalled checks for PP & Venmo. DTBTSDK-3176 + // TODO: - Make API call to PaymentReadyAPI. DTBTSDK-3176 + return BTShopperInsightsResult() + } +} diff --git a/Sources/BraintreeCore/BTShopperInsightsRequest.swift b/Sources/BraintreeCore/BTShopperInsightsRequest.swift new file mode 100644 index 0000000000..702e7e75ce --- /dev/null +++ b/Sources/BraintreeCore/BTShopperInsightsRequest.swift @@ -0,0 +1,28 @@ +import Foundation + +/// Buyer data required to use the Shopper Insights feature. +/// - Note: This feature is in beta. It's public API may change or be removed in future releases. +public struct BTShopperInsightsRequest { + + /// The buyer's email address. + private let email: String + + /// The buyer's country code prefix to the national telephone number. An identifier for a specific country. + /// Must not contain special characters. + private let phoneCountryCode: String + + /// The buyer's national phone number. Must not contain special characters. + private let phoneNationalNumber: String + + /// Initialize a `BTShopperInsightsRequest` + /// - Parameters: + /// - email: The buyer's email address. + /// - phoneCountryCode: The buyer's country code prefix to the national telephone number. An identifier for a specific country. Must not contain special characters. + /// - phoneNationalNumber: The buyer's national phone number. Must not contain special characters. + /// - Note: This feature is in beta. It's public API may change or be removed in future releases. + public init(email: String, phoneCountryCode: String, phoneNationalNumber: String) { + self.email = email + self.phoneCountryCode = phoneCountryCode + self.phoneNationalNumber = phoneNationalNumber + } +} diff --git a/Sources/BraintreeCore/BTShopperInsightsResult.swift b/Sources/BraintreeCore/BTShopperInsightsResult.swift new file mode 100644 index 0000000000..7700177b54 --- /dev/null +++ b/Sources/BraintreeCore/BTShopperInsightsResult.swift @@ -0,0 +1,12 @@ +import Foundation + +/// A summary of the buyer's recommended payment methods. +/// - Note: This feature is in beta. It's public API may change or be removed in future releases. +public struct BTShopperInsightsResult { + + /// If true, display the PayPal button with high priority. + public var isPayPalRecommended = false + + /// If true, dislpay the Venmo button with high priority. + public var isVenmoRecommended = false +} diff --git a/UnitTests/BraintreeCoreTests/BTShopperInsightsClient_Tests.swift b/UnitTests/BraintreeCoreTests/BTShopperInsightsClient_Tests.swift new file mode 100644 index 0000000000..d1d48a08ed --- /dev/null +++ b/UnitTests/BraintreeCoreTests/BTShopperInsightsClient_Tests.swift @@ -0,0 +1,27 @@ +import Foundation +import XCTest +@testable import BraintreeCore +@testable import BraintreeTestShared + +class BTShopperInsightsClient_Tests: XCTestCase { + + var mockAPIClient = MockAPIClient(authorization: "development_client_key")! + var sut: BTShopperInsightsClient! + + override func setUp() { + super.setUp() + sut = BTShopperInsightsClient(apiClient: mockAPIClient) + } + + func testGetRecommendedPaymentMethods_returnsDefaultRecommendations() async { + let request = BTShopperInsightsRequest( + email: "fake-email", + phoneCountryCode: "fake-country-code", + phoneNationalNumber: "fake-national-phone" + ) + let result = try? await sut.getRecommendedPaymentMethods(request: request) + + XCTAssertNotNil(result!.isPayPalRecommended) + XCTAssertNotNil(result!.isVenmoRecommended) + } +}