Skip to content

Commit

Permalink
Adding support for iDeal 2.0 (#1687)
Browse files Browse the repository at this point in the history
## Summary
- Changed iDeal to be an InstantPaymentMethod (ignoring the issuers)

## Release Notes
<new>
The new iDEAL payment flow where the shopper is redirected to the iDEAL
payment page to select their bank and authorize the payment.
</new>


https://github.com/Adyen/adyen-ios/assets/4838877/878a70a3-8c06-4e8b-9945-9ac4e70b5dca

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: goergisn <[email protected]>
  • Loading branch information
3 people authored May 24, 2024
1 parent cde7eb6 commit 32cb481
Show file tree
Hide file tree
Showing 24 changed files with 39 additions and 30 deletions.
2 changes: 0 additions & 2 deletions Adyen.docc/API Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,6 @@ The Adyen DropIn/Components SDK API Reference.
### Issuer List Component

- ``IssuerListComponent``
- ``IdealComponent``
- ``OnlineBankingPolandComponent``
- ``MOLPayComponent``
- ``DotpayComponent``
Expand All @@ -228,7 +227,6 @@ The Adyen DropIn/Components SDK API Reference.
- ``EPSDetails``
- ``DotpayDetails``
- ``MOLPayDetails``
- ``IdealDetails``
- ``OnlineBankingPolandDetails``
- ``IssuerListDetails``

Expand Down
17 changes: 11 additions & 6 deletions Adyen/Core/Payment Methods/Abstract/AnyPaymentMethodDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ private struct PaymentMethodField: Decodable {
}

internal enum AnyPaymentMethodDecoder {

private static var decoders: [PaymentMethodType: PaymentMethodDecoder] = [

// Unsupported payment methods
Expand All @@ -46,7 +47,6 @@ internal enum AnyPaymentMethodDecoder {
// Supported payment methods
.card: CardPaymentMethodDecoder(),
.scheme: CardPaymentMethodDecoder(),
.ideal: IssuerListPaymentMethodDecoder(),
.entercash: IssuerListPaymentMethodDecoder(),
.eps: IssuerListPaymentMethodDecoder(),
.dotpay: IssuerListPaymentMethodDecoder(),
Expand Down Expand Up @@ -91,15 +91,20 @@ internal enum AnyPaymentMethodDecoder {
internal static func decode(from decoder: Decoder) -> AnyPaymentMethod {
do {
let container = try decoder.container(keyedBy: AnyPaymentMethod.CodingKeys.self)
let type = try container.decode(String.self, forKey: .type)
let type = try PaymentMethodType(rawValue: container.decode(String.self, forKey: .type))
let isStored = decoder.codingPath.contains { $0.stringValue == PaymentMethods.CodingKeys.stored.stringValue }
let brand = try? container.decode(String.self, forKey: .brand)
let isIssuersList = try container.containsValue(.issuers)


if type == .ideal {
return try InstantPaymentMethodDecoder().decode(from: decoder, isStored: isStored)
}

if isIssuersList {
if type == "onlineBanking_CZ" || type == "onlineBanking_SK" {
if type == .onlineBankingCZ || type == .onlineBankingSK {
return try OnlineBankingPaymentMethodDecoder().decode(from: decoder, isStored: isStored)
}

return try IssuerListPaymentMethodDecoder().decode(from: decoder, isStored: isStored)
}

Expand All @@ -111,11 +116,11 @@ internal enum AnyPaymentMethodDecoder {
// That includes brand, type, isStored, and requiresDetails,
// This matching struct will be used as the key to the decoders
// dictionary.
if isStored, brand == "bcmc", type == "scheme" {
if isStored, brand == "bcmc", type == .scheme {
return try decoders[.bcmc, default: defaultDecoder].decode(from: decoder, isStored: true)
}

let paymentDecoder = PaymentMethodType(rawValue: type).map { decoders[$0, default: defaultDecoder] } ?? defaultDecoder
let paymentDecoder = type.map { decoders[$0, default: defaultDecoder] } ?? defaultDecoder
return try paymentDecoder.decode(from: decoder, isStored: isStored)
} catch {
return .none
Expand Down
2 changes: 1 addition & 1 deletion Adyen/Core/Payment Methods/IssuerListPaymentMethod.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import Foundation

/// An issuer list payment method, such as iDEAL or Open Banking.
/// An issuer list payment method, such as Open Banking.
public struct IssuerListPaymentMethod: PaymentMethod {

public let type: PaymentMethodType
Expand Down
5 changes: 1 addition & 4 deletions AdyenComponents/Issuer List/IssuerListComponent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation
import UIKit

/// A generic component for "issuer-based" payment methods, such as iDEAL and MOLPay.
/// A generic component for "issuer-based" payment methods, such as MOLPay.
/// This component will provide a list in which the user can select their issuer.
public final class IssuerListComponent: PaymentComponent, PaymentAware, PresentableComponent, LoadingComponent {

Expand Down Expand Up @@ -183,9 +183,6 @@ extension IssuerListComponent {
}
}

/// Provides an issuer selection list for iDEAL payments.
public typealias IdealComponent = IssuerListComponent

/// Provides an issuer selection list for MOLPay payments.
public typealias MOLPayComponent = IssuerListComponent

Expand Down
3 changes: 0 additions & 3 deletions AdyenComponents/Issuer List/IssuerListDetails.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ public struct IssuerListDetails: PaymentMethodDetails {

}

/// Contains the details supplied by the IDEAL component.
public typealias IdealDetails = IssuerListDetails

/// Contains the details supplied by the MOLPay component.
public typealias MOLPayDetails = IssuerListDetails

Expand Down
4 changes: 2 additions & 2 deletions Demo/Common/Assets/payment_methods_response.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@
"type" : "select"
}
],
"name" : "iDEAL",
"supportsRecurring" : true,
"type" : "ideal"
"type": "onlineBanking_PL",
"name": "Online Banking"
},
{
"brands" : [
Expand Down
2 changes: 1 addition & 1 deletion Demo/SwiftUI/ComponentsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ internal final class ComponentsViewModel: ObservableObject, Identifiable {
ComponentsItem(title: "Card", selectionHandler: presentCardComponent),
ComponentsItem(
title: "Issuer List",
subtitle: "e.g. Ideal, Open Banking, ...",
subtitle: "e.g. Open Banking, ...",
selectionHandler: presentIssuerListComponent
),
ComponentsItem(
Expand Down
2 changes: 1 addition & 1 deletion Demo/UIKit/ComponentsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ internal final class ComponentsViewController: UIViewController {
ComponentsItem(title: "Card", selectionHandler: presentCardComponent),
ComponentsItem(
title: "Issuer List",
subtitle: "e.g. Ideal, Open Banking, ...",
subtitle: "e.g. Open Banking, ...",
selectionHandler: presentIssuerListComponent
),
ComponentsItem(
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,6 @@ In order to have more flexibility over the checkout flow, you can use our Compon
- [3D Secure 2 Component][reference.threeDS2Component]
- [Apple Pay Component][reference.applePayComponent]
- [BCMC Component][reference.bcmcComponent]
- [iDEAL Component][reference.issuerListComponent]
- [SEPA Direct Debit Component][reference.sepaDirectDebitComponent]
- [MOLPay Component][reference.issuerListComponent]
- [Dotpay Component][reference.issuerListComponent]
Expand Down
4 changes: 2 additions & 2 deletions Tests/IntegrationTests/DropIn Tests/DropInTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ class DropInTests: XCTestCase {
"type" : "select"
}
],
"name" : "iDEAL",
"name" : "Online Banking",
"supportsRecurring" : true,
"type" : "ideal"
"type" : "onlineBanking_PL"
},
{
"brands" : [ "mc", "visa" ],
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 13 additions & 5 deletions Tests/UnitTests/Core/PaymentMethodTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ class PaymentMethodTests: XCTestCase {
affirm,
atome,
upi,
cashAppPay
cashAppPay,
idealDictionary
]
]
}
Expand Down Expand Up @@ -170,16 +171,19 @@ class PaymentMethodTests: XCTestCase {

// Regular payment methods

XCTAssertEqual(paymentMethods.regular.count, 31)
XCTAssertEqual(paymentMethods.regular.count, 32)

let creditCardPaymentMethod = try XCTUnwrap(paymentMethods.regular[0] as? CardPaymentMethod)
XCTAssertEqual(creditCardPaymentMethod.fundingSource, .credit)

XCTAssertTrue(paymentMethods.regular[1] is IssuerListPaymentMethod)
XCTAssertEqual(paymentMethods.regular[1].type.rawValue, "onlineBanking_PL")
XCTAssertEqual(paymentMethods.regular[1].name, "Online Banking")

XCTAssertTrue(paymentMethods.regular[2] is SEPADirectDebitPaymentMethod)
XCTAssertTrue(paymentMethods.regular[3] is InstantPaymentMethod)

// Unknown redirect
XCTAssertTrue(paymentMethods.regular[3] is InstantPaymentMethod)
XCTAssertEqual(paymentMethods.regular[3].type.rawValue, "unknown")
XCTAssertEqual(paymentMethods.regular[3].name, "Redirect Payment Method")

Expand Down Expand Up @@ -306,6 +310,10 @@ class PaymentMethodTests: XCTestCase {
XCTAssertEqual(cashAppPay.type.rawValue, "cashapp")
XCTAssertEqual(cashAppPay.clientId, "testClient")
XCTAssertEqual(cashAppPay.scopeId, "testScope")

XCTAssertTrue(paymentMethods.regular[31] is InstantPaymentMethod)
XCTAssertEqual(paymentMethods.regular[31].type.rawValue, "ideal")
XCTAssertEqual(paymentMethods.regular[31].name, "iDeal")
}

// MARK: - Display Information Override
Expand Down Expand Up @@ -745,8 +753,8 @@ class PaymentMethodTests: XCTestCase {

func testDecodingIssuerListPaymentMethod() throws {
let paymentMethod = try AdyenCoder.decode(issuerListDictionary) as IssuerListPaymentMethod
XCTAssertEqual(paymentMethod.type.rawValue, "ideal")
XCTAssertEqual(paymentMethod.name, "iDEAL")
XCTAssertEqual(paymentMethod.type.rawValue, "onlineBanking_PL")
XCTAssertEqual(paymentMethod.name, "Online Banking")

XCTAssertEqual(paymentMethod.issuers.count, 3)
XCTAssertEqual(paymentMethod.issuers[0].identifier, "xxxx")
Expand Down
9 changes: 7 additions & 2 deletions Tests/UnitTests/Mocks/DummyData/DummyPaymentMethods.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ let applePayDictionary = [
"type": "applepay"
] as [String: Any]

let idealDictionary = [
"type": "ideal",
"name": "iDeal"
] as [String: Any]

let bcmcCardDictionary = [
"name": "Bancontact card",
"supportsRecurring": true,
Expand All @@ -96,8 +101,8 @@ let storedBcmcDictionary = [
] as [String: Any]

let issuerListDictionary = [
"type": "ideal",
"name": "iDEAL",
"type": "onlineBanking_PL",
"name": "Online Banking",
"details": [
[
"items": [
Expand Down

0 comments on commit 32cb481

Please sign in to comment.