Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/origin/COIOS-802_identify_…
Browse files Browse the repository at this point in the history
…native_redirect_flow' into COIOS-802_identify_native_redirect_flow
  • Loading branch information
nauaros committed Oct 28, 2024
2 parents d574e11 + 7efd84d commit a8f3f1c
Show file tree
Hide file tree
Showing 31 changed files with 452 additions and 67 deletions.
9 changes: 5 additions & 4 deletions .github/workflows/detect_api_changes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ jobs:
fi
cd Scripts
./public-api-diff --new "$NEW" --old "$OLD" --output "$PROJECT_FOLDER/api_comparison.md"
./public-api-diff project --new "$NEW" --old "$OLD" --output "$PROJECT_FOLDER/api_comparison.md" --log-output "$PROJECT_FOLDER/logs.txt"
cat "$PROJECT_FOLDER/logs.txt"
cat "$PROJECT_FOLDER/api_comparison.md" >> $GITHUB_STEP_SUMMARY
env:
source: '${{ github.event.inputs.new || github.head_ref }}'
Expand All @@ -57,8 +58,8 @@ jobs:

- if: ${{ github.event.pull_request.base.ref != '' }}
name: 📝 Comment on PR
uses: thollander/actions-comment-pull-request@v2
uses: thollander/actions-comment-pull-request@v3
with:
filePath: "${{ github.workspace }}/api_comparison.md"
comment_tag: api_changes
file-path: "${{ github.workspace }}/api_comparison.md"
comment-tag: api_changes
mode: recreate
25 changes: 25 additions & 0 deletions .github/workflows/stale_issues.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# This workflow warns and then closes issues that have had no activity for a specified amount of time.
#
# You can adjust the behavior by modifying this file.
# For more information, see:
# https://github.com/actions/stale
name: Manage stale issues

on:
schedule:
- cron: '0 0 * * *' # Run every day at midnight
workflow_dispatch:

jobs:
close_stale_prs:
runs-on: ubuntu-latest
steps:
- name: Close stale issues
uses: actions/stale@v9
with:
any-of-labels: 'awaiting feedback'
stale-issue-message: 'This issue is now stale because it has been open for 14 days with no activity. Please provide the requested information or the issue will be closed automatically.'
close-issue-message: 'This issue is now closed because it has been stalled for 14 days with no activity.'
days-before-issue-stale: 14
days-before-issue-close: 14
stale-issue-label: 'stale'
3 changes: 2 additions & 1 deletion .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ opt_in_rules:

excluded:
- Build
- .build
- Tests
- Internal
- Docs
Expand All @@ -26,7 +27,7 @@ line_length:
file_length:
warning: 500

variable_name:
identifier_name:
min_length:
warning: 2
max_length:
Expand Down
4 changes: 2 additions & 2 deletions Adyen.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ Pod::Spec.new do |s|
s.subspec 'CashAppPay' do |plugin|
plugin.source_files = 'AdyenCashAppPay/**/*.swift'
plugin.dependency 'Adyen/Core'
plugin.dependency 'CashAppPayKit', '0.5.1'
plugin.dependency 'CashAppPayKitUI', '0.5.1'
plugin.dependency 'CashAppPayKit', '0.6.2'
plugin.dependency 'CashAppPayKitUI', '0.6.2'
end

s.subspec 'AdyenTwint' do |plugin|
Expand Down
6 changes: 5 additions & 1 deletion Adyen.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
00FAE54E2B21CE1B0059A6F5 /* TwintDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00FAE54D2B21CE1B0059A6F5 /* TwintDetails.swift */; };
00FFD8F02A865BFB008D4A5A /* ApplePaySettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00FFD8EF2A865BFB008D4A5A /* ApplePaySettingsView.swift */; };
00FFD8F12A865BFB008D4A5A /* ApplePaySettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00FFD8EF2A865BFB008D4A5A /* ApplePaySettingsView.swift */; };
21099B0D2CB7276E0096502C /* PaymentInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21099B0C2CB7276E0096502C /* PaymentInfo.swift */; };
2159173A2A0D161B0004081E /* ThreeDS2PlusDAScreenPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 215917392A0D161B0004081E /* ThreeDS2PlusDAScreenPresenter.swift */; };
2172F8152C20B91400BE0369 /* DelegatedAuthenticationErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2172F8142C20B91400BE0369 /* DelegatedAuthenticationErrorView.swift */; };
2172F8172C20B93400BE0369 /* DAErrorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2172F8162C20B93400BE0369 /* DAErrorViewController.swift */; };
Expand Down Expand Up @@ -1545,6 +1546,7 @@
00FAE54B2B21CBAD0059A6F5 /* TwintPaymentMethod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwintPaymentMethod.swift; sourceTree = "<group>"; };
00FAE54D2B21CE1B0059A6F5 /* TwintDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwintDetails.swift; sourceTree = "<group>"; };
00FFD8EF2A865BFB008D4A5A /* ApplePaySettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplePaySettingsView.swift; sourceTree = "<group>"; };
21099B0C2CB7276E0096502C /* PaymentInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentInfo.swift; sourceTree = "<group>"; };
215917392A0D161B0004081E /* ThreeDS2PlusDAScreenPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeDS2PlusDAScreenPresenter.swift; sourceTree = "<group>"; };
2159173B2A0D2B6E0004081E /* ThreeDS2DAScreenPresenterMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeDS2DAScreenPresenterMock.swift; sourceTree = "<group>"; };
2172F8142C20B91400BE0369 /* DelegatedAuthenticationErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DelegatedAuthenticationErrorView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3654,6 +3656,7 @@
E2345C07229BDA46000F2C94 /* ThreeDS2ComponentChallengeToken.swift */,
E2345C0D229BDD2D000F2C94 /* ThreeDS2Details.swift */,
F9842C58256D72B60063CE5A /* ThreeDSResult.swift */,
21099B0C2CB7276E0096502C /* PaymentInfo.swift */,
);
path = 3DS2;
sourceTree = "<group>";
Expand Down Expand Up @@ -7545,6 +7548,7 @@
A03EE72F2760A2E300470561 /* DocumentActionViewModel.swift in Sources */,
F94F0DEB28AA3FB400C0923D /* ThreeDS2PlusDACoreActionHandler.swift in Sources */,
F9B018032608F648001F23FC /* EContextStoresVoucherAction.swift in Sources */,
21099B0D2CB7276E0096502C /* PaymentInfo.swift in Sources */,
F917613825A30B5700D653BE /* ThreeDS2ComponentFingerprint.swift in Sources */,
F970143925D139BE007E74D9 /* VoucherComponentStyle.swift in Sources */,
F917613925A30B5700D653BE /* ThreeDS2ComponentFingerprintToken.swift in Sources */,
Expand Down Expand Up @@ -9447,7 +9451,7 @@
repositoryURL = "https://github.com/cashapp/cash-app-pay-ios-sdk";
requirement = {
kind = exactVersion;
version = 0.5.1;
version = 0.6.2;
};
};
E72375CC27AAB7760020DCF9 /* XCRemoteSwiftPackageReference "adyen-wechatpay-ios" */ = {
Expand Down
4 changes: 3 additions & 1 deletion Adyen/Analytics/AnalyticsProvider/AnalyticsProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ internal final class AnalyticsProvider: AnalyticsProviderProtocol {
self.uniqueAssetAPIClient = UniqueAssetAPIClient<InitialAnalyticsResponse>(apiClient: apiClient)
self.eventDataSource = eventDataSource
self.batchInterval = batchInterval
startNextTimer()
}

deinit {
Expand Down Expand Up @@ -145,6 +144,7 @@ internal final class AnalyticsProvider: AnalyticsProviderProtocol {
switch result {
case let .success(response):
checkoutAttemptId = response.checkoutAttemptId
startNextTimer()
case .failure:
checkoutAttemptId = nil
}
Expand All @@ -160,6 +160,8 @@ internal final class AnalyticsProvider: AnalyticsProviderProtocol {
}

private func startNextTimer() {
guard configuration.isEnabled else { return }

batchTimer?.invalidate()
batchTimer = Timer.scheduledTimer(withTimeInterval: batchInterval, repeats: true) { [weak self] _ in
self?.sendEventsIfNeeded()
Expand Down
1 change: 1 addition & 0 deletions Adyen/Analytics/Models/AnalyticsEventLog.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public struct AnalyticsEventLog: AnalyticsEvent {
case submit = "Submit"
case redirect = "Redirect"
case threeDS2 = "ThreeDS2"
case closed = "Closed"
}

public enum LogSubType: String, Encodable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -492,9 +492,9 @@ private struct TwintPaymentMethodDecoder: PaymentMethodDecoder {
func decode(from decoder: Decoder, isStored: Bool) throws -> AnyPaymentMethod {
#if canImport(TwintSDK)
if isStored {
try .storedTwint(StoredTwintPaymentMethod(from: decoder))
return try .storedTwint(StoredTwintPaymentMethod(from: decoder))
} else {
try .twint(TwintPaymentMethod(from: decoder))
return try .twint(TwintPaymentMethod(from: decoder))
}
#else
return AnyPaymentMethod(InstantPaymentMethod(type: .twint, name: "Twint"))
Expand Down
4 changes: 2 additions & 2 deletions Adyen/UI/Form/Items/Text/FormTextItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,15 @@ open class FormTextItem: FormValidatableValueItem<String>, InputViewRequiringFor
textDidChange(value: value)
}

@_spi(AdyenInternal)
@discardableResult
internal func textDidChange(value: String) -> String {
public func textDidChange(value: String) -> String {
let sanitizedValue = formatter?.sanitizedValue(for: value) ?? value

publisher.wrappedValue = sanitizedValue
formattedValue = formatter?.formattedValue(for: value) ?? value
return formattedValue
}

}

@_spi(AdyenInternal)
Expand Down
11 changes: 9 additions & 2 deletions Adyen/UI/Form/Items/Text/FormTextItemView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,18 @@ open class FormTextItemView<ItemType: FormTextItem>: FormValidatableValueItemVie

// MARK: - Private

@objc private func textDidChange(textField: UITextField) {
@_spi(AdyenInternal)
@objc open func textDidChange(textField: UITextField) {
textField.text = item.textDidChange(value: textField.text ?? "")
notifyDelegateOfMaxLengthIfNeeded()
}

@_spi(AdyenInternal)
open func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// Making it available for subclassing
true
}

// MARK: - Validation

override public var isValid: Bool {
Expand Down Expand Up @@ -265,7 +272,7 @@ open class FormTextItemView<ItemType: FormTextItem>: FormValidatableValueItemVie

public func notifyDelegateOfMaxLengthIfNeeded() {
let maximumLength = item.validator?.maximumLength(for: item.value) ?? .max
if item.value.count == maximumLength {
if item.value.count >= maximumLength {
delegate?.didReachMaximumLength(in: self)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ internal typealias VoidHandler = () -> Void
event: Analytics.Event,
completionHandler: @escaping (Result<String, Error>) -> Void
) {

super.handle(fingerprintAction, event: event) { [weak self] result in
switch result {
case let .failure(error):
Expand All @@ -106,9 +105,10 @@ internal typealias VoidHandler = () -> Void
}

self.startApprovalFlow(
payloadForDA,
cardType: nil,
cardNumber: nil
payloadForDA.sdkInput,
cardType: payloadForDA.cardType,
cardNumber: payloadForDA.cardNumber,
amount: payloadForDA.amount
) { [weak self] result in
guard let self else { return }

Expand All @@ -134,12 +134,28 @@ internal typealias VoidHandler = () -> Void
}
}
}

private struct ApprovalPayload {
let sdkInput: String
let cardNumber: String?
let cardType: CardType?
let amount: Amount?
}

private func daPayload(_ fingerprintAction: ThreeDS2FingerprintAction) -> String? {
guard let token: ThreeDS2Component.FingerprintToken = try? AdyenCoder.decodeBase64(fingerprintAction.fingerprintToken) else {
private func daPayload(
_ fingerprintAction: ThreeDS2FingerprintAction
) -> ApprovalPayload? {
guard let token: ThreeDS2Component.FingerprintToken = try? AdyenCoder.decodeBase64(fingerprintAction.fingerprintToken),
let sdkInput = token.delegatedAuthenticationSDKInput else {
return nil
}
return token.delegatedAuthenticationSDKInput

return ApprovalPayload(
sdkInput: sdkInput,
cardNumber: securedCardNumber(lastFour: token.paymentInfo?.lastFour),
cardType: token.paymentInfo?.cardType,
amount: token.paymentInfo?.amount ?? context.payment?.amount
)
}

/// Adds the authenticationSDK output into the fingerprint result to approve the transaction/delete the credential in the backend.
Expand Down Expand Up @@ -167,6 +183,7 @@ internal typealias VoidHandler = () -> Void
_ delegatedAuthenticationInput: String,
cardType: CardType?,
cardNumber: String?,
amount: Amount?,
completion: @escaping (Result<(daOutput: String, delete: Bool?), ApprovalFlowError>) -> Void
) {
isDeviceRegistered(delegatedAuthenticationInput: delegatedAuthenticationInput) { [weak self] registered in
Expand All @@ -176,6 +193,7 @@ internal typealias VoidHandler = () -> Void
delegatedAuthenticationInput: delegatedAuthenticationInput,
cardType: cardType,
cardNumber: cardNumber,
amount: amount,
completion: completion
)
} else {
Expand All @@ -199,12 +217,14 @@ internal typealias VoidHandler = () -> Void
delegatedAuthenticationInput: String,
cardType: CardType?,
cardNumber: String?,
amount: Amount?,
completion: @escaping (Result<(daOutput: String, delete: Bool?), ApprovalFlowError>
) -> Void
) {
presenter.showApprovalScreen(
component: self,
cardDetails: (cardNumber, cardType),
amount: amount,
approveAuthenticationHandler: { [weak self] in
guard let self else { return }
self.userApprovedTransaction(
Expand Down Expand Up @@ -373,9 +393,9 @@ internal typealias VoidHandler = () -> Void
}

self.startRegistrationFlow(
delegatedAuthenticationInput: registrationPayload,
cardNumber: nil,
cardType: nil
delegatedAuthenticationInput: registrationPayload.sdkInput,
cardNumber: registrationPayload.cardNumber,
cardType: registrationPayload.cardType
) { result in
switch result {
case let .success(registrationSDKOutput):
Expand Down Expand Up @@ -447,11 +467,29 @@ internal typealias VoidHandler = () -> Void
}
}

private func daPayload(_ challengeAction: ThreeDS2ChallengeAction) -> String? {
guard let token: ThreeDS2Component.ChallengeToken = try? AdyenCoder.decodeBase64(challengeAction.challengeToken) else {
private struct RegistrationPayload {
let sdkInput: String
let cardNumber: String?
let cardType: CardType?
}

private func daPayload(_ challengeAction: ThreeDS2ChallengeAction) -> RegistrationPayload? {
guard let token: ThreeDS2Component.ChallengeToken = try? AdyenCoder.decodeBase64(challengeAction.challengeToken),
let sdkInput = token.delegatedAuthenticationSDKInput else {
return nil
}
return RegistrationPayload(
sdkInput: sdkInput,
cardNumber: securedCardNumber(lastFour: token.paymentInfo?.lastFour),
cardType: token.paymentInfo?.cardType
)
}

private func securedCardNumber(lastFour: String?) -> String? {
guard let lastFour else {
return nil
}
return token.delegatedAuthenticationSDKInput
return String.Adyen.securedString + lastFour
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ internal protocol ThreeDS2PlusDAScreenPresenterProtocol {
fallbackHandler: @escaping () -> Void
)

// swiftlint:disable function_parameter_count
func showApprovalScreen(
component: Component,
cardDetails: (number: String?, type: CardType?),
amount: Amount?,
approveAuthenticationHandler: @escaping () -> Void,
fallbackHandler: @escaping () -> Void,
removeCredentialsHandler: @escaping () -> Void
)
// swiftlint:enable function_parameter_count

func showAuthenticationError(component: Component, handler: @escaping () -> Void)
func showRegistrationError(component: Component, handler: @escaping () -> Void)
Expand Down Expand Up @@ -101,9 +104,9 @@ internal final class ThreeDS2PlusDAScreenPresenter: ThreeDS2PlusDAScreenPresente
fallbackHandler: @escaping () -> Void
) {
let registrationViewController = DARegistrationViewController(
context: context,
style: style,
localizationParameters: localizedParameters,
logoProvider: LogoURLProvider(environment: context.apiContext.environment),
cardNumber: cardDetails.number,
cardType: cardDetails.type,
biometricName: biometricName,
Expand All @@ -124,18 +127,21 @@ internal final class ThreeDS2PlusDAScreenPresenter: ThreeDS2PlusDAScreenPresente
presentationDelegate?.present(component: presentableComponent)
}

// swiftlint:disable function_parameter_count
internal func showApprovalScreen(
component: Component,
cardDetails: (number: String?, type: CardType?),
amount: Amount?,
approveAuthenticationHandler: @escaping () -> Void,
fallbackHandler: @escaping () -> Void,
removeCredentialsHandler: @escaping () -> Void
) {
// swiftlint:enable function_parameter_count
let approvalViewController = DAApprovalViewController(
context: context,
style: style,
localizationParameters: localizedParameters,
amount: context.payment?.amount.formatted,
logoProvider: LogoURLProvider(environment: context.apiContext.environment),
amount: amount?.formatted,
cardNumber: cardDetails.number,
cardType: cardDetails.type,
useBiometricsHandler: {
Expand Down
Loading

0 comments on commit a8f3f1c

Please sign in to comment.