Skip to content

Commit 2266c70

Browse files
authored
Merge pull request #8031 from woocommerce/issue/8030-dotcom-error-v2-parser
Add support for WP-API error parsing
2 parents 48eacad + 0ae120c commit 2266c70

File tree

15 files changed

+482
-92
lines changed

15 files changed

+482
-92
lines changed

Networking/Networking.xcodeproj/project.pbxproj

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,8 @@
696696
DEC51AFB2769C66B009F3DF4 /* SystemStatusMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEC51AFA2769C66B009F3DF4 /* SystemStatusMapperTests.swift */; };
697697
DEC51B02276AFB35009F3DF4 /* SystemStatus+DropinMustUsePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEC51B01276AFB34009F3DF4 /* SystemStatus+DropinMustUsePlugin.swift */; };
698698
E12552C526385B05001CEE70 /* ShippingLabelAddressValidationSuccess.swift in Sources */ = {isa = PBXBuildFile; fileRef = E12552C426385B05001CEE70 /* ShippingLabelAddressValidationSuccess.swift */; };
699+
E137619929151C7400FD098F /* error-wp-rest-forbidden.json in Resources */ = {isa = PBXBuildFile; fileRef = E137619829151C7400FD098F /* error-wp-rest-forbidden.json */; };
700+
E137619B2915222100FD098F /* WordPressApiValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E137619A2915222100FD098F /* WordPressApiValidatorTests.swift */; };
699701
E13BAD5328F8625600217769 /* InAppPurchasesRemoteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E13BAD5228F8625600217769 /* InAppPurchasesRemoteTests.swift */; };
700702
E16C59B528F8640B007D55BB /* InAppPurchaseOrderResultMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = E16C59B428F8640B007D55BB /* InAppPurchaseOrderResultMapper.swift */; };
701703
E16C59B728F92782007D55BB /* iap-sample-receipt.json in Resources */ = {isa = PBXBuildFile; fileRef = E16C59B628F92782007D55BB /* iap-sample-receipt.json */; };
@@ -705,6 +707,10 @@
705707
E18152C228F85E0A0011A0EC /* iap-products.json in Resources */ = {isa = PBXBuildFile; fileRef = E18152C128F85E0A0011A0EC /* iap-products.json */; };
706708
E18152C428F85E5C0011A0EC /* InAppPurchasesProductsMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E18152C328F85E5C0011A0EC /* InAppPurchasesProductsMapperTests.swift */; };
707709
E1A5C27228F93ED900081046 /* InAppPurchaseOrderResultMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A5C27128F93ED900081046 /* InAppPurchaseOrderResultMapperTests.swift */; };
710+
E1BAB2C12913F99500C3982B /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1BAB2C02913F99500C3982B /* Request.swift */; };
711+
E1BAB2C32913FA6400C3982B /* ResponseDataValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1BAB2C22913FA6400C3982B /* ResponseDataValidator.swift */; };
712+
E1BAB2C52913FB1800C3982B /* WordPressApiValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1BAB2C42913FB1800C3982B /* WordPressApiValidator.swift */; };
713+
E1BAB2C72913FB5800C3982B /* WordPressApiError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1BAB2C62913FB5800C3982B /* WordPressApiError.swift */; };
708714
EE8A86F1286C5226003E8AA4 /* media-update-product-id-in-wordpress-site.json in Resources */ = {isa = PBXBuildFile; fileRef = EE8A86F0286C5226003E8AA4 /* media-update-product-id-in-wordpress-site.json */; };
709715
EECB7EE8286555180028C888 /* media-update-product-id.json in Resources */ = {isa = PBXBuildFile; fileRef = EECB7EE7286555180028C888 /* media-update-product-id.json */; };
710716
FE28F6E226840DED004465C7 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE28F6E126840DED004465C7 /* User.swift */; };
@@ -1433,6 +1439,8 @@
14331439
DEC51AFA2769C66B009F3DF4 /* SystemStatusMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemStatusMapperTests.swift; sourceTree = "<group>"; };
14341440
DEC51B01276AFB34009F3DF4 /* SystemStatus+DropinMustUsePlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SystemStatus+DropinMustUsePlugin.swift"; sourceTree = "<group>"; };
14351441
E12552C426385B05001CEE70 /* ShippingLabelAddressValidationSuccess.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelAddressValidationSuccess.swift; sourceTree = "<group>"; };
1442+
E137619829151C7400FD098F /* error-wp-rest-forbidden.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "error-wp-rest-forbidden.json"; sourceTree = "<group>"; };
1443+
E137619A2915222100FD098F /* WordPressApiValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordPressApiValidatorTests.swift; sourceTree = "<group>"; };
14361444
E13BAD5228F8625600217769 /* InAppPurchasesRemoteTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppPurchasesRemoteTests.swift; sourceTree = "<group>"; };
14371445
E16C59B428F8640B007D55BB /* InAppPurchaseOrderResultMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppPurchaseOrderResultMapper.swift; sourceTree = "<group>"; };
14381446
E16C59B628F92782007D55BB /* iap-sample-receipt.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "iap-sample-receipt.json"; sourceTree = "<group>"; };
@@ -1442,6 +1450,10 @@
14421450
E18152C128F85E0A0011A0EC /* iap-products.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "iap-products.json"; sourceTree = "<group>"; };
14431451
E18152C328F85E5C0011A0EC /* InAppPurchasesProductsMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppPurchasesProductsMapperTests.swift; sourceTree = "<group>"; };
14441452
E1A5C27128F93ED900081046 /* InAppPurchaseOrderResultMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppPurchaseOrderResultMapperTests.swift; sourceTree = "<group>"; };
1453+
E1BAB2C02913F99500C3982B /* Request.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = "<group>"; };
1454+
E1BAB2C22913FA6400C3982B /* ResponseDataValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResponseDataValidator.swift; sourceTree = "<group>"; };
1455+
E1BAB2C42913FB1800C3982B /* WordPressApiValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordPressApiValidator.swift; sourceTree = "<group>"; };
1456+
E1BAB2C62913FB5800C3982B /* WordPressApiError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordPressApiError.swift; sourceTree = "<group>"; };
14451457
EE8A86F0286C5226003E8AA4 /* media-update-product-id-in-wordpress-site.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "media-update-product-id-in-wordpress-site.json"; sourceTree = "<group>"; };
14461458
EECB7EE7286555180028C888 /* media-update-product-id.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "media-update-product-id.json"; sourceTree = "<group>"; };
14471459
F3F25DC15EC1D7C631169CB5 /* Pods_Networking.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Networking.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -1732,6 +1744,8 @@
17321744
isa = PBXGroup;
17331745
children = (
17341746
B53EF5332180F646003E146F /* DotcomValidator.swift */,
1747+
E1BAB2C42913FB1800C3982B /* WordPressApiValidator.swift */,
1748+
E1BAB2C22913FA6400C3982B /* ResponseDataValidator.swift */,
17351749
);
17361750
path = Validators;
17371751
sourceTree = "<group>";
@@ -1848,6 +1862,7 @@
18481862
isa = PBXGroup;
18491863
children = (
18501864
B567AF2420A0CCA300AB6C62 /* AuthenticatedRequest.swift */,
1865+
E1BAB2C02913F99500C3982B /* Request.swift */,
18511866
B557DA0E20975E07005962F4 /* DotcomRequest.swift */,
18521867
B557D9FF209754FF005962F4 /* JetpackRequest.swift */,
18531868
DE34051228BDCA5100CF0D97 /* WordPressOrgRequest.swift */,
@@ -1950,6 +1965,7 @@
19501965
3105470B262E27F000C5C02B /* WCPayPaymentIntentStatusEnum.swift */,
19511966
0359EA0E27AAC6410048DE2D /* WCPayPaymentMethodDetails.swift */,
19521967
0359EA1027AAC6740048DE2D /* WCPayPaymentMethodType.swift */,
1968+
E1BAB2C62913FB5800C3982B /* WordPressApiError.swift */,
19531969
);
19541970
path = Model;
19551971
sourceTree = "<group>";
@@ -2203,6 +2219,7 @@
22032219
68F48B1228E3E5750045C15B /* wc-analytics-customers.json */,
22042220
688908AD28FF920C0081A07E /* customer-2.json */,
22052221
03EB99952907F03000F06A39 /* empty-data-array.json */,
2222+
E137619829151C7400FD098F /* error-wp-rest-forbidden.json */,
22062223
);
22072224
path = Responses;
22082225
sourceTree = "<group>";
@@ -2319,6 +2336,7 @@
23192336
isa = PBXGroup;
23202337
children = (
23212338
B57B1E6921C925280046E764 /* DotcomValidatorTests.swift */,
2339+
E137619A2915222100FD098F /* WordPressApiValidatorTests.swift */,
23222340
);
23232341
path = Validators;
23242342
sourceTree = "<group>";
@@ -2650,6 +2668,7 @@
26502668
B5A24179217F98F600595DEF /* notifications-load-all.json in Resources */,
26512669
314EDF2927C02CC100A56B6F /* stripe-account-complete-empty-descriptor.json in Resources */,
26522670
028CB71F2902589E00331C09 /* create-account-error-invalid-email.json in Resources */,
2671+
E137619929151C7400FD098F /* error-wp-rest-forbidden.json in Resources */,
26532672
31A451CE27863A2E00FE81AA /* stripe-account-wrong-json.json in Resources */,
26542673
028CB718290223CB00331C09 /* account-username-suggestions.json in Resources */,
26552674
0282DD91233A120A006A5FDB /* products-search-photo.json in Resources */,
@@ -3070,6 +3089,7 @@
30703089
743057B5218B6ACD00441A76 /* Queue.swift in Sources */,
30713090
DE2095BD27956D7900171F1C /* CouponReport.swift in Sources */,
30723091
74A1D26821189A7100931DFA /* SiteVisitStats.swift in Sources */,
3092+
E1BAB2C12913F99500C3982B /* Request.swift in Sources */,
30733093
02C254B0256378D000A04423 /* ShippingLabelRefundStatus.swift in Sources */,
30743094
4568E2242459D3230007E478 /* Post.swift in Sources */,
30753095
4513382427A951B300AE5E78 /* InboxNoteMapper.swift in Sources */,
@@ -3172,6 +3192,7 @@
31723192
DE34051728BDEB6D00CF0D97 /* JetpackConnectionRemote.swift in Sources */,
31733193
B505F6EC20BEFDC200BB1B69 /* Loader.swift in Sources */,
31743194
74D3BD142114FE6900A6E85E /* MIContainer.swift in Sources */,
3195+
E1BAB2C72913FB5800C3982B /* WordPressApiError.swift in Sources */,
31753196
314703082670222500EF253A /* PaymentGatewayAccount.swift in Sources */,
31763197
CCF48B282628A4EB0034EA83 /* ShippingLabelAccountSettingsMapper.swift in Sources */,
31773198
B5BB1D1220A255EC00112D92 /* OrderStatusEnum.swift in Sources */,
@@ -3188,6 +3209,7 @@
31883209
74C8F06820EEB7BD00B6EDC9 /* OrderNotesMapper.swift in Sources */,
31893210
24F98C582502EA8800F49B68 /* FeatureFlagMapper.swift in Sources */,
31903211
451A9832260B9D2D0059D135 /* ShippingLabelPackagesMapper.swift in Sources */,
3212+
E1BAB2C32913FA6400C3982B /* ResponseDataValidator.swift in Sources */,
31913213
4501068F2399B19500E24722 /* TaxClassRemote.swift in Sources */,
31923214
B53EF5342180F646003E146F /* DotcomValidator.swift in Sources */,
31933215
CCF434642906BD7200B4475A /* ProductIDMapper.swift in Sources */,
@@ -3218,6 +3240,7 @@
32183240
740211E321939C84002248DA /* CommentResultMapper.swift in Sources */,
32193241
CC9A24F42642CF37005DE56E /* ShippingLabelCreationEligibilityMapper.swift in Sources */,
32203242
45E3EEBB237009CF00A826AC /* ShippingLine.swift in Sources */,
3243+
E1BAB2C52913FB1800C3982B /* WordPressApiValidator.swift in Sources */,
32213244
CE6BFEEA2236E191005C79FB /* ProductType.swift in Sources */,
32223245
CE6D666C2379E19D007835A1 /* Array+Woo.swift in Sources */,
32233246
CCF48B1E26288FEC0034EA83 /* ShippingLabelPaymentMethod.swift in Sources */,
@@ -3343,6 +3366,7 @@
33433366
74C8F06E20EEC1E800B6EDC9 /* OrderNotesMapperTests.swift in Sources */,
33443367
45ED4F10239E8A54004F1BE3 /* TaxClassListMapperTest.swift in Sources */,
33453368
FE28F6EA26842E49004465C7 /* UserMapperTests.swift in Sources */,
3369+
E137619B2915222100FD098F /* WordPressApiValidatorTests.swift in Sources */,
33463370
020C907F24C7D359001E2BEB /* ProductVariationMapperTests.swift in Sources */,
33473371
74ABA1D5213F26B300FFAD30 /* TopEarnerStatsMapperTests.swift in Sources */,
33483372
74AB5B5121AF426D00859C12 /* SiteAPIRemoteTests.swift in Sources */,
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import Foundation
2+
3+
/// WordPress API Request Error
4+
///
5+
public enum WordPressApiError: Error, Decodable, Equatable {
6+
7+
/// Unknown: Represents an unmapped remote error.
8+
///
9+
case unknown(code: String, message: String)
10+
11+
/// Decodable Initializer.
12+
///
13+
public init(from decoder: Decoder) throws {
14+
let container = try decoder.container(keyedBy: CodingKeys.self)
15+
let code = try container.decode(String.self, forKey: .code)
16+
let message = try container.decode(String.self, forKey: .message)
17+
18+
switch code {
19+
default:
20+
self = .unknown(code: code, message: message)
21+
}
22+
}
23+
24+
25+
/// Constants for Possible Error Identifiers
26+
///
27+
private enum Constants {
28+
}
29+
30+
/// Coding Keys
31+
///
32+
private enum CodingKeys: String, CodingKey {
33+
case code
34+
case message
35+
}
36+
37+
/// Possible Error Messages
38+
///
39+
private enum ErrorMessages {
40+
static let statsModuleDisabled = "This blog does not have the Stats module enabled"
41+
static let noStatsPermission = "user cannot view stats"
42+
static let resourceDoesNotExist = "Resource does not exist."
43+
}
44+
}
45+
46+
47+
// MARK: - CustomStringConvertible Conformance
48+
//
49+
extension WordPressApiError: CustomStringConvertible {
50+
51+
public var description: String {
52+
switch self {
53+
case .unknown(let code, let message):
54+
let messageFormat = NSLocalizedString(
55+
"WordPress API Error: [%1$@] %2$@",
56+
comment: "WordPress API (unmapped!) error. Parameters: %1$@ - code, %2$@ - message"
57+
)
58+
return String.localizedStringWithFormat(messageFormat, code, message)
59+
}
60+
}
61+
}

Networking/Networking/Remote/InAppPurchasesRemote.swift

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ public class InAppPurchasesRemote: Remote {
1010
/// - completion: Closure to be executed upon completion
1111
///
1212
public func loadProducts(completion: @escaping (Swift.Result<[String], Error>) -> Void) {
13-
let dotComRequest = DotcomRequest(wordpressApiVersion: .wpcomMark2, method: .get, path: Constants.productsPath)
14-
let request = augmentedRequestWithAppId(dotComRequest)
13+
let request = DotcomRequest(wordpressApiVersion: .wpcomMark2, method: .get, path: Constants.productsPath, headers: headersWithAppId)
1514
let mapper = InAppPurchasesProductMapper()
1615
enqueue(request, mapper: mapper, completion: completion)
1716
}
@@ -39,8 +38,13 @@ public class InAppPurchasesRemote: Remote {
3938
Constants.appStoreCountryCodeKey: appStoreCountryCode,
4039
Constants.receiptDataKey: receiptData.base64EncodedString()
4140
]
42-
let dotComRequest = DotcomRequest(wordpressApiVersion: .wpcomMark2, method: .post, path: Constants.ordersPath, parameters: parameters)
43-
let request = augmentedRequestWithAppId(dotComRequest)
41+
let request = DotcomRequest(
42+
wordpressApiVersion: .wpcomMark2,
43+
method: .post,
44+
path: Constants.ordersPath,
45+
parameters: parameters,
46+
headers: headersWithAppId
47+
)
4448
let mapper = InAppPurchaseOrderResultMapper()
4549
enqueue(request, mapper: mapper, completion: completion)
4650
}
@@ -93,15 +97,14 @@ public extension InAppPurchasesRemote {
9397
}
9498

9599
private extension InAppPurchasesRemote {
96-
func augmentedRequestWithAppId(_ request: URLRequestConvertible) -> URLRequestConvertible {
97-
guard let bundleIdentifier = Bundle.main.bundleIdentifier,
98-
var augmented = try? request.asURLRequest() else {
99-
return request
100+
var headersWithAppId: [String: String]? {
101+
guard let bundleIdentifier = Bundle.main.bundleIdentifier else {
102+
return nil
100103
}
101104

102-
augmented.setValue(bundleIdentifier, forHTTPHeaderField: "X-APP-ID")
103-
104-
return augmented
105+
return [
106+
"X-APP-ID": bundleIdentifier
107+
]
105108
}
106109
}
107110

0 commit comments

Comments
 (0)