Skip to content

Commit f471bbf

Browse files
authored
Merge pull request #7530 from woocommerce/issue/7479-parse-payment-gateway-instructions
[Mobile Payments] Parse PaymentGateway instructions
2 parents b8a3e88 + b52fcf5 commit f471bbf

File tree

16 files changed

+1238
-84
lines changed

16 files changed

+1238
-84
lines changed

Fakes/Fakes/Networking.generated.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,18 @@ extension PaymentGateway {
579579
title: .fake(),
580580
description: .fake(),
581581
enabled: .fake(),
582-
features: .fake()
582+
features: .fake(),
583+
instructions: .fake()
584+
)
585+
}
586+
}
587+
extension PaymentGateway.Setting {
588+
/// Returns a "ready to use" type filled with fake values.
589+
///
590+
public static func fake() -> PaymentGateway.Setting {
591+
.init(
592+
settingID: .fake(),
593+
value: .fake()
583594
)
584595
}
585596
}

Networking/Networking/Model/Copiable/Models+Copiable.generated.swift

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -665,22 +665,40 @@ extension PaymentGateway {
665665
title: CopiableProp<String> = .copy,
666666
description: CopiableProp<String> = .copy,
667667
enabled: CopiableProp<Bool> = .copy,
668-
features: CopiableProp<[PaymentGateway.Feature]> = .copy
668+
features: CopiableProp<[PaymentGateway.Feature]> = .copy,
669+
instructions: NullableCopiableProp<String> = .copy
669670
) -> PaymentGateway {
670671
let siteID = siteID ?? self.siteID
671672
let gatewayID = gatewayID ?? self.gatewayID
672673
let title = title ?? self.title
673674
let description = description ?? self.description
674675
let enabled = enabled ?? self.enabled
675676
let features = features ?? self.features
677+
let instructions = instructions ?? self.instructions
676678

677679
return PaymentGateway(
678680
siteID: siteID,
679681
gatewayID: gatewayID,
680682
title: title,
681683
description: description,
682684
enabled: enabled,
683-
features: features
685+
features: features,
686+
instructions: instructions
687+
)
688+
}
689+
}
690+
691+
extension PaymentGateway.Setting {
692+
public func copy(
693+
settingID: CopiableProp<String> = .copy,
694+
value: CopiableProp<String> = .copy
695+
) -> PaymentGateway.Setting {
696+
let settingID = settingID ?? self.settingID
697+
let value = value ?? self.value
698+
699+
return PaymentGateway.Setting(
700+
settingID: settingID,
701+
value: value
684702
)
685703
}
686704
}

Networking/Networking/Model/PaymentGateway.swift

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,19 @@ public struct PaymentGateway: Equatable, GeneratedFakeable, GeneratedCopiable {
1313
case custom(raw: String)
1414
}
1515

16+
/// Setting for a payment gateway
17+
///
18+
public struct Setting: Equatable, GeneratedCopiable, GeneratedFakeable {
19+
public let settingID: String
20+
public let value: String
21+
22+
public init(settingID: String,
23+
value: String) {
24+
self.settingID = settingID
25+
self.value = value
26+
}
27+
}
28+
1629
/// Site identifier.
1730
///
1831
public let siteID: Int64
@@ -37,17 +50,28 @@ public struct PaymentGateway: Equatable, GeneratedFakeable, GeneratedCopiable {
3750
///
3851
public let features: [Feature]
3952

40-
public init(siteID: Int64, gatewayID: String, title: String, description: String, enabled: Bool, features: [Feature]) {
53+
/// Instructions shown to the customer after purchase.
54+
///
55+
public let instructions: String?
56+
57+
public init(siteID: Int64,
58+
gatewayID: String,
59+
title: String,
60+
description: String,
61+
enabled: Bool,
62+
features: [Feature],
63+
instructions: String?) {
4164
self.siteID = siteID
4265
self.gatewayID = gatewayID
4366
self.title = title
4467
self.description = description
4568
self.enabled = enabled
4669
self.features = features
70+
self.instructions = instructions
4771
}
4872
}
4973

50-
// MARK: Gateway Decodable
74+
// MARK: Gateway Codable
5175
extension PaymentGateway: Codable {
5276

5377
public enum DecodingError: Error {
@@ -60,7 +84,8 @@ extension PaymentGateway: Codable {
6084
case description
6185
case enabled
6286
case features = "method_supports"
63-
87+
case instructions
88+
case settings
6489
}
6590

6691
public init(from decoder: Decoder) throws {
@@ -75,16 +100,37 @@ extension PaymentGateway: Codable {
75100
let enabled = try container.decode(Bool.self, forKey: .enabled)
76101
let features = try container.decode([Feature].self, forKey: .features)
77102

103+
// Settings can have different types for `value`, this implementation only handles `String`
104+
let settings = try? container.decodeIfPresent([String: Setting].self, forKey: .settings)
105+
let instructions = settings?[Setting.Keys.instructions]?.value
106+
78107
self.init(siteID: siteID,
79108
gatewayID: gatewayID,
80109
title: title,
81110
description: description,
82111
enabled: enabled,
83-
features: features)
112+
features: features,
113+
instructions: instructions)
114+
}
115+
116+
public func encode(to encoder: Encoder) throws {
117+
var container = encoder.container(keyedBy: CodingKeys.self)
118+
119+
try container.encode(gatewayID, forKey: .gatewayID)
120+
try container.encode(title, forKey: .title)
121+
try container.encode(description, forKey: .description)
122+
try container.encode(enabled, forKey: .enabled)
123+
try container.encode(features, forKey: .features)
124+
125+
guard let instructions = instructions else {
126+
return
127+
}
128+
let settings = [Setting.Keys.instructions: instructions]
129+
try container.encode(settings, forKey: .settings)
84130
}
85131
}
86132

87-
// MARK: Features Decodable
133+
// MARK: - Features Decodable
88134
extension PaymentGateway.Feature: RawRepresentable, Codable {
89135

90136
/// Enum containing the 'Known' Feature Keys
@@ -116,3 +162,20 @@ extension PaymentGateway.Feature: RawRepresentable, Codable {
116162
}
117163
}
118164
}
165+
166+
// MARK: - Settings Codable
167+
extension PaymentGateway.Setting: Codable {
168+
/// The known keys, which match `settingID`
169+
///
170+
fileprivate enum Keys {
171+
static let title = "title"
172+
static let instructions = "instructions"
173+
static let enableForMethods = "enable_for_methods"
174+
static let enableForVirtual = "enable_for_virtual"
175+
}
176+
177+
private enum CodingKeys: String, CodingKey {
178+
case settingID = "id"
179+
case value
180+
}
181+
}

Networking/NetworkingTests/Mapper/PaymentGatewayListMapperTests.swift

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ final class PaymentGatewayListMapperTests: XCTestCase {
1717
let gateways = try PaymentGatewayListMapper(siteID: Self.sampleSiteID).map(response: jsonData)
1818

1919
// Then
20-
XCTAssertEqual(gateways, expectedGateways)
20+
assertEqual(expectedGateways, gateways)
2121
}
2222
}
2323

@@ -31,26 +31,30 @@ private extension PaymentGatewayListMapperTests {
3131
"Please use your Order ID as the payment reference. " +
3232
"Your order will not be shipped until the funds have cleared in our account.",
3333
enabled: false,
34-
features: [.products])
34+
features: [.products],
35+
instructions: nil)
3536

3637
static let checkGateway = PaymentGateway(siteID: sampleSiteID,
3738
gatewayID: "cheque",
3839
title: "Check payments",
3940
description: "Please send a check to Store Name, Store Street, Store Town, Store State / County, Store Postcode.",
4041
enabled: false,
41-
features: [.products])
42+
features: [.products],
43+
instructions: nil)
4244

4345
static let cashGateway = PaymentGateway(siteID: sampleSiteID,
4446
gatewayID: "cod",
4547
title: "Cash on delivery",
4648
description: "Pay with cash upon delivery.",
4749
enabled: true,
48-
features: [.products])
50+
features: [.products],
51+
instructions: "Pay with cash upon delivery.")
4952

5053
static let paypalGateway = PaymentGateway(siteID: sampleSiteID,
5154
gatewayID: "paypal",
5255
title: "PayPal",
5356
description: "Pay via PayPal; you can pay with your credit card if you don't have a PayPal account.",
5457
enabled: false,
55-
features: [.products, .refunds])
58+
features: [.products, .refunds],
59+
instructions: nil)
5660
}

Networking/NetworkingTests/Mapper/PaymentGatewayMapperTests.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ final class PaymentGatewayMapperTests: XCTestCase {
3131
title: "Cash on delivery",
3232
description: "Pay with cash upon delivery.",
3333
enabled: true,
34-
features: [.products])
34+
features: [.products],
35+
instructions: "Pay with cash upon delivery.")
3536

3637
XCTAssertEqual(paymentGateway, expectedPaymentGateway)
3738
}

Networking/NetworkingTests/Remote/PaymentsGatewayRemoteTests.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,14 @@ final class PaymentsGatewayRemoteTests: XCTestCase {
8888

8989
// MARK: - Helper methods
9090

91-
extension PaymentsGatewayRemoteTests {
91+
private extension PaymentsGatewayRemoteTests {
9292
func samplePaymentGateway() -> PaymentGateway {
9393
PaymentGateway.fake().copy(siteID: sampleSiteID,
9494
gatewayID: "cod",
9595
title: "Cash on delivery",
9696
description: "Pay with cash upon delivery.",
9797
enabled: true,
98-
features: [.products])
98+
features: [.products],
99+
instructions: "Pay with cash upon delivery.")
99100
}
100101
}

Networking/NetworkingTests/Responses/payment-gateway-cod.json

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,61 @@
99
"method_description": "Have your customers pay with cash (or by other means) upon delivery.",
1010
"method_supports": [
1111
"products"
12-
]
12+
],
13+
"settings": {
14+
"title": {
15+
"id": "title",
16+
"label": "Title",
17+
"description": "Payment method description that the customer will see on your checkout.",
18+
"type": "safe_text",
19+
"value": "Cash on delivery",
20+
"default": "Cash on delivery",
21+
"tip": "Payment method description that the customer will see on your checkout.",
22+
"placeholder": ""
23+
},
24+
"instructions": {
25+
"id": "instructions",
26+
"label": "Instructions",
27+
"description": "Instructions that will be added to the thank you page.",
28+
"type": "textarea",
29+
"value": "Pay with cash upon delivery.",
30+
"default": "Pay with cash upon delivery.",
31+
"tip": "Instructions that will be added to the thank you page.",
32+
"placeholder": ""
33+
},
34+
"enable_for_methods": {
35+
"id": "enable_for_methods",
36+
"label": "Enable for shipping methods",
37+
"description": "If COD is only available for certain methods, set it up here. Leave blank to enable for all methods.",
38+
"type": "multiselect",
39+
"value": "",
40+
"default": "",
41+
"tip": "If COD is only available for certain methods, set it up here. Leave blank to enable for all methods.",
42+
"placeholder": "",
43+
"options": {
44+
"Flat rate": {
45+
"flat_rate": "Any &quot;Flat rate&quot; method",
46+
"flat_rate:1": "Other locations &ndash; Flat rate (#1)"
47+
},
48+
"Free shipping": {
49+
"free_shipping": "Any &quot;Free shipping&quot; method",
50+
"free_shipping:4": "Other locations &ndash; Free shipping (#4)"
51+
},
52+
"Local pickup": {
53+
"local_pickup": "Any &quot;Local pickup&quot; method"
54+
}
55+
}
56+
},
57+
"enable_for_virtual": {
58+
"id": "enable_for_virtual",
59+
"label": "Accept COD if the order is virtual",
60+
"description": "",
61+
"type": "checkbox",
62+
"value": "yes",
63+
"default": "yes",
64+
"tip": "",
65+
"placeholder": ""
66+
}
67+
}
1368
}
1469
}

0 commit comments

Comments
 (0)