Skip to content

Commit f6a61ed

Browse files
committed
Merge branch 'develop' into feat/5368-display-jetpack-banner-for-jcp-sites
2 parents eeecbdc + 7cc6ca8 commit f6a61ed

File tree

94 files changed

+4063
-2770
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+4063
-2770
lines changed

Experiments/Experiments/DefaultFeatureFlagService.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public struct DefaultFeatureFlagService: FeatureFlagService {
2424
case .simplePaymentsPrototype:
2525
return buildConfig == .localDeveloper || buildConfig == .alpha
2626
case .orderListFilters:
27-
return buildConfig == .localDeveloper || buildConfig == .alpha
27+
return true
2828
case .jetpackConnectionPackageSupport:
2929
return buildConfig == .localDeveloper || buildConfig == .alpha
3030
case .orderCreation:

Fakes/Fakes/Networking.generated.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,3 +1547,19 @@ extension WCPayPaymentIntentStatusEnum {
15471547
.requiresPaymentMethod
15481548
}
15491549
}
1550+
extension WordPressMedia {
1551+
/// Returns a "ready to use" type filled with fake values.
1552+
///
1553+
public static func fake() -> WordPressMedia {
1554+
.init(
1555+
mediaID: .fake(),
1556+
date: .fake(),
1557+
slug: .fake(),
1558+
mimeType: .fake(),
1559+
src: .fake(),
1560+
alt: .fake(),
1561+
details: .fake(),
1562+
title: .fake()
1563+
)
1564+
}
1565+
}

Hardware/Hardware.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
/* Begin PBXBuildFile section */
1010
030338102705F7D400764131 /* ReceiptTotalLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0303380F2705F7D400764131 /* ReceiptTotalLine.swift */; };
1111
311889EB2653286B0080AEA2 /* PaymentIntentMetadataTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 311889EA2653286B0080AEA2 /* PaymentIntentMetadataTests.swift */; };
12+
317975C0274EB1F9004357B1 /* DeclineReason.swift in Sources */ = {isa = PBXBuildFile; fileRef = 317975BF274EB1F9004357B1 /* DeclineReason.swift */; };
13+
317975C2274EBC1F004357B1 /* DeclineReason+Stripe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 317975C1274EBC1F004357B1 /* DeclineReason+Stripe.swift */; };
14+
317975C4274ED591004357B1 /* DeclineReasonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 317975C3274ED591004357B1 /* DeclineReasonTests.swift */; };
1215
55CD4BB4273E617C007686D3 /* ReceiptRendererTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55CD4BB3273E617C007686D3 /* ReceiptRendererTest.swift */; };
1316
5A747BE9FA06EC8752A35752 /* Pods_HardwareTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B1DC5B6141B8184FAC29B0A4 /* Pods_HardwareTests.framework */; };
1417
8FFAA245E257B9EB98E2FCBD /* Pods_SampleReceiptPrinter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2AFA997D6786C67B0A061854 /* Pods_SampleReceiptPrinter.framework */; };
@@ -133,6 +136,9 @@
133136
1CC96A71F2937BCB7432766F /* Pods-HardwareTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HardwareTests.debug.xcconfig"; path = "Target Support Files/Pods-HardwareTests/Pods-HardwareTests.debug.xcconfig"; sourceTree = "<group>"; };
134137
2AFA997D6786C67B0A061854 /* Pods_SampleReceiptPrinter.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SampleReceiptPrinter.framework; sourceTree = BUILT_PRODUCTS_DIR; };
135138
311889EA2653286B0080AEA2 /* PaymentIntentMetadataTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentIntentMetadataTests.swift; sourceTree = "<group>"; };
139+
317975BF274EB1F9004357B1 /* DeclineReason.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeclineReason.swift; sourceTree = "<group>"; };
140+
317975C1274EBC1F004357B1 /* DeclineReason+Stripe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DeclineReason+Stripe.swift"; sourceTree = "<group>"; };
141+
317975C3274ED591004357B1 /* DeclineReasonTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeclineReasonTests.swift; sourceTree = "<group>"; };
136142
3CF9348BADD5E0518080A61A /* Pods-Hardware.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Hardware.debug.xcconfig"; path = "Target Support Files/Pods-Hardware/Pods-Hardware.debug.xcconfig"; sourceTree = "<group>"; };
137143
47BDD50287B7B0CF8D769BFC /* Pods-PrinterPlayground.release-alpha.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PrinterPlayground.release-alpha.xcconfig"; path = "Target Support Files/Pods-PrinterPlayground/Pods-PrinterPlayground.release-alpha.xcconfig"; sourceTree = "<group>"; };
138144
55CD4BB3273E617C007686D3 /* ReceiptRendererTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReceiptRendererTest.swift; sourceTree = "<group>"; };
@@ -374,6 +380,7 @@
374380
D80B4651260E19590092EDC0 /* PaymentIntentParametersTests.swift */,
375381
D845BDFE262DDA6A00A3E40F /* ReceiptDetailsTests.swift */,
376382
D845BE02262DDBF500A3E40F /* CardBrandTests.swift */,
383+
317975C3274ED591004357B1 /* DeclineReasonTests.swift */,
377384
);
378385
path = HardwareTests;
379386
sourceTree = "<group>";
@@ -407,6 +414,7 @@
407414
E1E125AB26EB582B0068A9B0 /* CardReaderSoftwareUpdateState.swift */,
408415
D845BDC1262D98C400A3E40F /* CardBrand.swift */,
409416
D845BDD9262DAADB00A3E40F /* PaymentMethod.swift */,
417+
317975BF274EB1F9004357B1 /* DeclineReason.swift */,
410418
);
411419
path = CardReader;
412420
sourceTree = "<group>";
@@ -432,6 +440,7 @@
432440
D845BDCF262D9C6C00A3E40F /* ReceiptDetails+Stripe.swift */,
433441
D845BDDD262DAB8300A3E40F /* PaymentMethod+Stripe.swift */,
434442
E1E125AF26EB66EA0068A9B0 /* Cancelable+Stripe.swift */,
443+
317975C1274EBC1F004357B1 /* DeclineReason+Stripe.swift */,
435444
);
436445
path = StripeCardReader;
437446
sourceTree = "<group>";
@@ -744,6 +753,7 @@
744753
buildActionMask = 2147483647;
745754
files = (
746755
D845BE59262ED84000A3E40F /* AirPrintReceiptPrinterService.swift in Sources */,
756+
317975C2274EBC1F004357B1 /* DeclineReason+Stripe.swift in Sources */,
747757
D845BDB8262D97B300A3E40F /* ReceiptDetails.swift in Sources */,
748758
D88FDB2D25DD21B000CB0DBD /* PaymentIntentParameters.swift in Sources */,
749759
D89B8F0825DDC8F60001C726 /* Charge.swift in Sources */,
@@ -763,6 +773,7 @@
763773
E1E125B026EB66EA0068A9B0 /* Cancelable+Stripe.swift in Sources */,
764774
D80B4656260E1B290092EDC0 /* CurrencyCode.swift in Sources */,
765775
D81AE86425E6B77F00D9CFD3 /* CardReaderServiceError.swift in Sources */,
776+
317975C0274EB1F9004357B1 /* DeclineReason.swift in Sources */,
766777
D8DF5F4E25DD9F91008AFE25 /* CardReaderType+Stripe.swift in Sources */,
767778
D89B8F1225DDCBCD0001C726 /* Charge+Stripe.swift in Sources */,
768779
E1E4FA2F2653CFD5007B9D4F /* PrintingResult.swift in Sources */,
@@ -814,6 +825,7 @@
814825
D88303DB25E450E700C877F9 /* PaymentIntentTests.swift in Sources */,
815826
D845BE03262DDBF500A3E40F /* CardBrandTests.swift in Sources */,
816827
311889EB2653286B0080AEA2 /* PaymentIntentMetadataTests.swift in Sources */,
828+
317975C4274ED591004357B1 /* DeclineReasonTests.swift in Sources */,
817829
D845BDFB262DD97E00A3E40F /* MockStripeReceiptDetails.swift in Sources */,
818830
D845BDF5262DD67E00A3E40F /* MockStripeCardPresentDetails.swift in Sources */,
819831
D88303D125E44B2500C877F9 /* ChargeTests.swift in Sources */,

Hardware/Hardware/CardReader/CardReaderServiceError.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ extension CardReaderServiceError: LocalizedError {
6565

6666
/// Underlying error. Models the specific error that made a given
6767
/// interaction with the SDK fail.
68-
public enum UnderlyingError: Error {
68+
public enum UnderlyingError: Error, Equatable {
6969
/// The service is busy executing another command. The service can only execute a single command at a time.
7070
case busy
7171

@@ -171,7 +171,7 @@ public enum UnderlyingError: Error {
171171
case unexpectedSDKError
172172

173173
/// The Stripe API declined the payment
174-
case paymentDeclinedByPaymentProcessorAPI
174+
case paymentDeclinedByPaymentProcessorAPI(declineReason: DeclineReason)
175175

176176
/// The reader declined the payment. Try another card.
177177
case paymentDeclinedByCardReader
@@ -311,6 +311,9 @@ updating the application or using a different reader
311311
return NSLocalizedString("The system experienced an unexpected software error",
312312
comment: "Error message when the card reader service experiences an unexpected software error.")
313313
case .paymentDeclinedByPaymentProcessorAPI:
314+
if case let .paymentDeclinedByPaymentProcessorAPI(declineReason) = self {
315+
return declineReason.localizedDescription
316+
}
314317
return NSLocalizedString("The card was declined by the payment processor - please try another means of payment",
315318
comment: "Error message when the card processor declines the payment.")
316319
case .paymentDeclinedByCardReader:
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/// Defines the distint high level decline reasons we want to handle. Do NOT put
2+
/// processor specific codes in this file. Use an extension to map
3+
/// processor specific decline codes to these reasons.
4+
///
5+
6+
import Foundation
7+
8+
public enum DeclineReason {
9+
/// A possibly temporary error caused the decline (e.g. the issuing
10+
/// bank's servers could not be contacted.) Tell the user this and prompt
11+
/// them to try again with the same (or another) payment method.
12+
///
13+
case temporary
14+
15+
/// The card has been reported lost or stolen. Don't reveal this
16+
/// to the user. Treat it like you would a generic decline.
17+
///
18+
case fraud
19+
20+
/// The payment was declined for an unspecified reason. Ask
21+
/// the user to try another payment method.
22+
///
23+
case generic
24+
25+
/// The card, or the account it connects to, is not valid. Ask
26+
/// the user to try another payment method.
27+
///
28+
case invalidAccount
29+
30+
/// The card presented is not supported. Tell the user this and
31+
/// ask them to try another payment method.
32+
///
33+
case cardNotSupported
34+
35+
/// The currency is not supported by the card presented. Tell the
36+
/// user this and ask them to try another payment method.
37+
///
38+
case currencyNotSupported
39+
40+
/// An identical transaction was just completed for the card presented.
41+
/// Tell the user this and ask them to try another payment method if they
42+
/// really want to do this.
43+
///
44+
case duplicateTransaction
45+
46+
/// The card presented has expired. Tell the user this and ask them
47+
/// to try another payment method.
48+
///
49+
case expiredCard
50+
51+
/// The card presented has a different ZIP/postal code than was
52+
/// used to place the order. Tell the user this and ask them
53+
/// to try another payment method (or correct the order.)
54+
///
55+
case incorrectPostalCode
56+
57+
/// The card presented has insufficient funds for the purchase.
58+
/// Tell the user this and ask them to try another payment method.
59+
///
60+
case insufficientFunds
61+
62+
/// The card presented does not allow purchases of the amount
63+
/// given. Tell the user this and ask them to try another payment method.
64+
///
65+
case invalidAmount
66+
67+
/// The card presented requires a PIN and the device doesn't support
68+
/// PIN entry. Tell the user this and ask them to try another payment method.
69+
///
70+
case pinRequired
71+
72+
/// The card presented has had an incorrect PIN entered too many times.
73+
/// Tell the user this and ask them to try another payment method.
74+
///
75+
case tooManyPinTries
76+
77+
/// The card presented is a system test card and cannot be used to
78+
/// process a payment. Tell the user this and ask them to try another
79+
/// payment method.
80+
///
81+
case testCard
82+
83+
/// The card presented is a live card, but the store/account is in test
84+
/// mode. Tell the user this and ask them to use a system test card instead.
85+
///
86+
case testModeLiveCard
87+
88+
/// The card was declined for an unknown reason. Tell the user this and
89+
/// ask them to try another payment method.
90+
///
91+
case unknown
92+
}
93+
94+
extension DeclineReason {
95+
public var localizedDescription: String? {
96+
switch self {
97+
case .temporary:
98+
return NSLocalizedString("Trying again may succeed, or try another means of payment",
99+
comment: "Message when a card is declined due to a potentially temporary problem.")
100+
case .fraud:
101+
return NSLocalizedString("Try another means of payment",
102+
comment: "Message when a lost or stolen card is presented for payment. Do NOT disclose fraud.")
103+
case .generic:
104+
return NSLocalizedString("Payment was declined for an unspecified reason. Try another means of payment",
105+
comment: "Message when payment is declined for a non specific reason.")
106+
case .invalidAccount:
107+
return NSLocalizedString("The card or card account is invalid. Try another means of payment",
108+
comment: "Message when payment is declined for a non specific reason.")
109+
110+
case .cardNotSupported:
111+
return NSLocalizedString("The card does not support this type of purchase. Try another means of payment",
112+
comment: "Message when the card presented does not allow this type of purchase.")
113+
case .currencyNotSupported:
114+
return NSLocalizedString("The card does not support this currency. Try another means of payment",
115+
comment: "Message when the card presented does not support the order currency.")
116+
case .duplicateTransaction:
117+
return NSLocalizedString("An identical transaction was submitted recently. If you wish to continue, try another means of payment",
118+
comment: "Message when it looks like a duplicate transaction is being attempted.")
119+
case .expiredCard:
120+
return NSLocalizedString("The card has expired. Try another means of payment",
121+
comment: "Message when the presented card is past its expiration date.")
122+
case .incorrectPostalCode:
123+
return NSLocalizedString("The transaction postal code and card postal code do not match. Try another means of payment",
124+
comment: "Message when the presented card postal code doesn't match the order postal code.")
125+
case .insufficientFunds:
126+
return NSLocalizedString("Payment declined due to insufficient funds. Try another means of payment",
127+
comment: "Message when the presented card remaining credit or balance is insufficient for the purchase.")
128+
case .invalidAmount:
129+
return NSLocalizedString("The payment amount is not allowed for the card presented. Try another means of payment.",
130+
comment: "Message when the presented card does not allow the purchase amount.")
131+
case .pinRequired:
132+
return NSLocalizedString("This card requires a PIN code and thus cannot be processed. Try another means of payment",
133+
comment: "Message when a card requires a PIN code and we have no means of entering such a code.")
134+
case .tooManyPinTries:
135+
return NSLocalizedString("An incorrect PIN has been entered too many times. Try another means of payment",
136+
comment: "Message when an incorrect PIN has been entered too many times.")
137+
case .testCard:
138+
return NSLocalizedString("System test cards are not permitted for payment. Try another means of payment",
139+
comment: "Message when attempting to pay for a live transaction with a test card.")
140+
case .testModeLiveCard:
141+
return NSLocalizedString("A live card was used on a site in test mode. Use a test card instead.",
142+
comment: "Message when attempting to pay for a test transaction with a live card.")
143+
case .unknown:
144+
return NSLocalizedString("Payment was declined for an unknown reason. Try another means of payment",
145+
comment: "Message when we don't know exactly why the payment was declined.")
146+
}
147+
}
148+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/// Maps Stripes many decline codes to our decline reasons
2+
/// See `https://stripe.com/docs/declines/codes`
3+
///
4+
5+
import Foundation
6+
import StripeTerminal
7+
8+
extension DeclineReason {
9+
init(with stripeDeclineCode: String) {
10+
let stripeDeclineCodeDictionary: Dictionary<DeclineReason, [String]> =
11+
[
12+
.temporary: [
13+
"approve_with_id",
14+
"issuer_not_available",
15+
"processing_error",
16+
"reenter_transaction",
17+
"try_again_later",
18+
],
19+
.fraud: [
20+
"call_issuer",
21+
"card_velocity_exceeded",
22+
"do_not_honor",
23+
"do_not_try_again",
24+
"fraudulent",
25+
"lost_card",
26+
"merchant_blacklist",
27+
"pickup_card",
28+
"restricted_card",
29+
"revocation_of_all_authorizations",
30+
"revocation_of_authorization",
31+
"security_violation",
32+
"stolen_card",
33+
"stop_payment_order",
34+
],
35+
.generic: [
36+
"generic_decline",
37+
"no_action_taken",
38+
"not_permitted",
39+
"service_not_allowed",
40+
"transaction_not_allowed"
41+
],
42+
.invalidAccount: [
43+
"invalid_account",
44+
"new_account_information_available",
45+
],
46+
.cardNotSupported: [
47+
"card_not_supported",
48+
],
49+
.currencyNotSupported: [
50+
"currency_not_supported",
51+
],
52+
.duplicateTransaction: [
53+
"duplicate_transaction",
54+
],
55+
.expiredCard: [
56+
"expired_card",
57+
],
58+
.incorrectPostalCode: [
59+
"incorrect_zip",
60+
],
61+
.insufficientFunds: [
62+
"insufficient_funds",
63+
"withdrawal_count_limit_exceeded",
64+
],
65+
.invalidAmount: [
66+
"invalid_amount",
67+
],
68+
.pinRequired: [
69+
"invalid_pin",
70+
"offline_pin_required",
71+
"online_or_offline_pin_required",
72+
],
73+
.tooManyPinTries: [
74+
"pin_try_exceeded",
75+
],
76+
.testCard: [
77+
"testmode_decline",
78+
],
79+
.testModeLiveCard: [
80+
"test_mode_live_card"
81+
]
82+
]
83+
84+
self = stripeDeclineCodeDictionary.first(
85+
where: { pair in
86+
pair.value.contains(stripeDeclineCode)
87+
}
88+
)?.key ?? .unknown
89+
}
90+
}

Hardware/Hardware/CardReader/StripeCardReader/UnderlyingError+Stripe.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ extension UnderlyingError {
7070
case ErrorCode.Code.unexpectedSdkError.rawValue:
7171
self = .unexpectedSDKError
7272
case ErrorCode.Code.declinedByStripeAPI.rawValue:
73-
self = .paymentDeclinedByPaymentProcessorAPI
73+
let processPaymentError = error as? ProcessPaymentError
74+
let declineReason = DeclineReason(with: processPaymentError?.declineCode ?? "")
75+
self = .paymentDeclinedByPaymentProcessorAPI(declineReason: declineReason)
7476
case ErrorCode.Code.declinedByReader.rawValue:
7577
self = .paymentDeclinedByCardReader
7678
case ErrorCode.Code.notConnectedToInternet.rawValue:

0 commit comments

Comments
 (0)