-
Notifications
You must be signed in to change notification settings - Fork 115
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Shipping labels] Add networking support for address validation endpo…
…int (#14933)
- Loading branch information
Showing
11 changed files
with
459 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
Networking/Networking/Mapper/WooShippingAddressValidationSuccessMapper.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import Foundation | ||
|
||
|
||
/// Mapper: Shipping Label Address Validation Response from WooCommerce Shipping extension | ||
/// | ||
struct WooShippingAddressValidationSuccessMapper: Mapper { | ||
/// (Attempts) to convert a dictionary into WooShippingAddressValidationResponse. | ||
/// | ||
func map(response: Data) throws -> WooShippingAddressValidationSuccess { | ||
let decoder = JSONDecoder() | ||
let data: WooShippingAddressValidationResponse = try { | ||
if hasDataEnvelope(in: response) { | ||
return try decoder.decode(WooShippingAddressValidationResponseEnvelope.self, from: response).data | ||
} else { | ||
return try decoder.decode(WooShippingAddressValidationResponse.self, from: response) | ||
} | ||
}() | ||
return try data.result.get() | ||
} | ||
} | ||
|
||
/// WooShippingAddressValidationResponseEnvelope Disposable Entity: | ||
/// `Normalize Address` endpoint returns the shipping label address document in the `data` key. | ||
/// This entity allows us to do parse all the things with JSONDecoder. | ||
/// | ||
private struct WooShippingAddressValidationResponseEnvelope: Decodable { | ||
let data: WooShippingAddressValidationResponse | ||
|
||
private enum CodingKeys: String, CodingKey { | ||
case data = "data" | ||
} | ||
} |
121 changes: 121 additions & 0 deletions
121
Networking/Networking/Model/ShippingLabel/WooShippingAddress.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
import Foundation | ||
import Codegen | ||
|
||
/// Represents an address for the WooCommerce Shipping extension. | ||
/// | ||
public struct WooShippingAddress: Equatable { | ||
/// The name of the company at the address. | ||
public let company: String | ||
|
||
/// The name of the sender/receiver at the address. | ||
public let name: String | ||
|
||
/// The contact phone number at the address. | ||
public let phone: String | ||
|
||
/// The country the address is in (ISO code). | ||
public let country: String | ||
|
||
/// The state the address is in (ISO code). | ||
public let state: String | ||
|
||
/// The first line of address (street, number, floor, etc.). | ||
public let address1: String | ||
|
||
/// The second line of address, empty if the address is only one line. | ||
public let address2: String | ||
|
||
/// The city the address is in. | ||
public let city: String | ||
|
||
/// Postal code of the address. | ||
public let postcode: String | ||
|
||
public init(company: String, | ||
name: String, | ||
phone: String, | ||
country: String, | ||
state: String, | ||
address1: String, | ||
address2: String, | ||
city: String, | ||
postcode: String) { | ||
self.company = company | ||
self.name = name | ||
self.phone = phone | ||
self.country = country | ||
self.state = state | ||
self.address1 = address1 | ||
self.address2 = address2 | ||
self.city = city | ||
self.postcode = postcode | ||
} | ||
} | ||
|
||
// MARK: Codable | ||
extension WooShippingAddress: Codable { | ||
public init(from decoder: Decoder) throws { | ||
let container = try decoder.container(keyedBy: CodingKeys.self) | ||
// If no name is sent to validation address request, no name will be received in response. | ||
// So make sure to decode it only if it's present. | ||
let name = try container.decodeIfPresent(String.self, forKey: .name) ?? "" | ||
let company = try container.decode(String.self, forKey: .company) | ||
let phone = try container.decode(String.self, forKey: .phone) | ||
let country = try container.decode(String.self, forKey: .country) | ||
let state = try container.decode(String.self, forKey: .state) | ||
let address1 = try container.decodeIfPresent(String.self, forKey: .address1) ?? container.decode(String.self, forKey: .alternateAddress1) | ||
let address2 = try container.decode(String.self, forKey: .address2) | ||
let city = try container.decode(String.self, forKey: .city) | ||
let postcode = try container.decode(String.self, forKey: .postcode) | ||
|
||
self.init(company: company, | ||
name: name, | ||
phone: phone, | ||
country: country, | ||
state: state, | ||
address1: address1, | ||
address2: address2, | ||
city: city, | ||
postcode: postcode) | ||
} | ||
|
||
public func encode(to encoder: Encoder) throws { | ||
var container = encoder.container(keyedBy: CodingKeys.self) | ||
|
||
try container.encode(company, forKey: .company) | ||
// Make sure to only send address name if it's not empty, | ||
// otherwise requests to fetch rates and purchase label will fail. | ||
// Reference: https://git.io/JVQzC | ||
if !name.isEmpty { | ||
try container.encode(name, forKey: .name) | ||
} | ||
try container.encode(phone, forKey: .phone) | ||
try container.encode(country, forKey: .country) | ||
try container.encode(state, forKey: .state) | ||
try container.encode(address1, forKey: .address1) | ||
try container.encode(address2, forKey: .address2) | ||
try container.encode(city, forKey: .city) | ||
try container.encode(postcode, forKey: .postcode) | ||
} | ||
|
||
private enum CodingKeys: String, CodingKey { | ||
case company | ||
case name | ||
case phone | ||
case country | ||
case state | ||
case address1 = "address" | ||
case alternateAddress1 = "address_1" | ||
case address2 = "address_2" | ||
case city | ||
case postcode | ||
} | ||
} | ||
|
||
extension WooShippingAddress { | ||
/// This empty initializer is used when parsing the API response for shipping labels, because the origin/destination addresses are not available in each | ||
/// shipping label response and we have to manually populate them later. | ||
init() { | ||
self.init(company: "", name: "", phone: "", country: "", state: "", address1: "", address2: "", city: "", postcode: "") | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
Networking/Networking/Model/ShippingLabel/WooShippingAddressValidationError.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import Foundation | ||
import Codegen | ||
|
||
/// Represents Shipping Label Address Validation Error from the WooCommerce Shipping extension. | ||
/// | ||
public struct WooShippingAddressValidationError: Error, Equatable { | ||
public let addressError: String? | ||
public let generalError: String? | ||
public let nameError: String? | ||
|
||
public init(addressError: String?, generalError: String?, nameError: String?) { | ||
self.addressError = addressError | ||
self.generalError = generalError | ||
self.nameError = nameError | ||
} | ||
} | ||
|
||
extension WooShippingAddressValidationError: Decodable { | ||
public init(from decoder: Decoder) throws { | ||
let container = try decoder.container(keyedBy: CodingKeys.self) | ||
let addressError = try container.decodeIfPresent(String.self, forKey: .address) | ||
let generalError = try container.decodeIfPresent(String.self, forKey: .general) | ||
let nameError = try container.decodeIfPresent(String.self, forKey: .name) | ||
self.init(addressError: addressError, generalError: generalError, nameError: nameError) | ||
} | ||
} | ||
|
||
/// Defines all of the WooShippingAddressValidationError CodingKeys | ||
/// | ||
private extension WooShippingAddressValidationError { | ||
enum CodingKeys: String, CodingKey { | ||
case general | ||
case address | ||
case name | ||
} | ||
} |
Oops, something went wrong.