Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make STPSource conform to STPPaymentMethod, exposing labels & images #976

Merged
merged 9 commits into from
Aug 3, 2018
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## XX.Y.Z
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is just a placeholder for when we make the next release?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. I think it's better for us to update the CHANGELOG during the release process, to avoid conflicts while merging PRs, but sometimes we do it during the PR.

* Adds `STPPaymentMethod` protocol implementation for `STPSource`. You can now call `image`/`templatedImage`/`label` on a source. [#976](https://github.com/stripe/stripe-ios/pull/976)

## 13.1.0 2018-07-13
* Adds `STPPaymentIntent` to support PaymentIntents. [#985](https://github.com/stripe/stripe-ios/pull/985), [#986](https://github.com/stripe/stripe-ios/pull/986), [#987](https://github.com/stripe/stripe-ios/pull/987), [#988](https://github.com/stripe/stripe-ios/pull/988)
* Reduce `NSURLSession` memory footprint. [#969](https://github.com/stripe/stripe-ios/pull/969)
Expand Down
28 changes: 26 additions & 2 deletions Stripe.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,12 @@
04F94DD41D22A242004FC826 /* NSBundle+Stripe_AppName.m in Sources */ = {isa = PBXBuildFile; fileRef = 049A3F981CC76A2400F57DE7 /* NSBundle+Stripe_AppName.m */; };
04FCFA191BD59A8C00297732 /* STPCategoryLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 04FCFA171BD59A8C00297732 /* STPCategoryLoader.h */; };
8B013C891F1E784A00DD831B /* STPPaymentConfigurationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B013C881F1E784A00DD831B /* STPPaymentConfigurationTest.m */; };
8B39128220E2F99600098401 /* EPSSource.json in Resources */ = {isa = PBXBuildFile; fileRef = 8B39128120E2F99600098401 /* EPSSource.json */; };
8B39128320E2F9A100098401 /* BancontactSource.json in Resources */ = {isa = PBXBuildFile; fileRef = 8B39127F20E2F6A500098401 /* BancontactSource.json */; };
8B39128520E2F9C400098401 /* GiropaySource.json in Resources */ = {isa = PBXBuildFile; fileRef = 8B39128420E2F9C400098401 /* GiropaySource.json */; };
8B39128720E2F9D300098401 /* MultibancoSource.json in Resources */ = {isa = PBXBuildFile; fileRef = 8B39128620E2F9D300098401 /* MultibancoSource.json */; };
8B39128920E2F9E000098401 /* P24Source.json in Resources */ = {isa = PBXBuildFile; fileRef = 8B39128820E2F9E000098401 /* P24Source.json */; };
8B39128B20E2F9F500098401 /* SOFORTSource.json in Resources */ = {isa = PBXBuildFile; fileRef = 8B39128A20E2F9F500098401 /* SOFORTSource.json */; };
8B429AD81EF9D4B400F95F34 /* STPBankAccountParams+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B429AD71EF9D4A300F95F34 /* STPBankAccountParams+Private.h */; };
8B429AD91EF9D4B500F95F34 /* STPBankAccountParams+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B429AD71EF9D4A300F95F34 /* STPBankAccountParams+Private.h */; };
8B429ADE1EF9EFF900F95F34 /* STPFile+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B429ADD1EF9EFF600F95F34 /* STPFile+Private.h */; };
Expand Down Expand Up @@ -1039,6 +1045,12 @@
4A0D74F918F6106100966D7B /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
7E0B1132203572FB00271AD3 /* fi */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = fi; path = Localizations/fi.lproj/Localizable.strings; sourceTree = "<group>"; };
8B013C881F1E784A00DD831B /* STPPaymentConfigurationTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STPPaymentConfigurationTest.m; sourceTree = "<group>"; };
8B39127F20E2F6A500098401 /* BancontactSource.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = BancontactSource.json; sourceTree = "<group>"; };
8B39128120E2F99600098401 /* EPSSource.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = EPSSource.json; sourceTree = "<group>"; };
8B39128420E2F9C400098401 /* GiropaySource.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = GiropaySource.json; sourceTree = "<group>"; };
8B39128620E2F9D300098401 /* MultibancoSource.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = MultibancoSource.json; sourceTree = "<group>"; };
8B39128820E2F9E000098401 /* P24Source.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = P24Source.json; sourceTree = "<group>"; };
8B39128A20E2F9F500098401 /* SOFORTSource.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = SOFORTSource.json; sourceTree = "<group>"; };
8B429AD71EF9D4A300F95F34 /* STPBankAccountParams+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "STPBankAccountParams+Private.h"; sourceTree = "<group>"; };
8B429ADD1EF9EFF600F95F34 /* STPFile+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "STPFile+Private.h"; sourceTree = "<group>"; };
8B5B4B431EFDD925005CF475 /* STPSourceOwnerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STPSourceOwnerTest.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1584,11 +1596,17 @@
isa = PBXGroup;
children = (
F1BA241F1E57BEC600E4A1CF /* 3DSSource.json */,
F16AA26D1F5A05A100207FFF /* AlipaySource.json */,
8B39127F20E2F6A500098401 /* BancontactSource.json */,
F1BA241C1E57BE5700E4A1CF /* CardSource.json */,
8B39128120E2F99600098401 /* EPSSource.json */,
8B39128420E2F9C400098401 /* GiropaySource.json */,
F152322E1EA9344000D65C67 /* iDEALSource.json */,
8B39128620E2F9D300098401 /* MultibancoSource.json */,
B3BDCADE20F0142C0034F7F5 /* PaymentIntent.json */,
8B39128820E2F9E000098401 /* P24Source.json */,
8BD2133D1F045D31007F6FD1 /* SEPADebitSource.json */,
F16AA26D1F5A05A100207FFF /* AlipaySource.json */,
8B39128A20E2F9F500098401 /* SOFORTSource.json */,
);
name = Source;
sourceTree = "<group>";
Expand All @@ -1597,10 +1615,10 @@
isa = PBXGroup;
children = (
F156753F1DB544D3004468E3 /* STPAddCardViewControllerLocalizationTests.m */,
C1054F901FE197AE0033C87E /* STPPaymentContextSnapshotTests.m */,
F1B980931DB550E60075332E /* STPPaymentMethodsViewControllerLocalizationTests.m */,
C1EF04491DD2396200FBF452 /* STPShippingAddressViewControllerLocalizationTests.m */,
C1EF044A1DD2396200FBF452 /* STPShippingMethodsViewControllerLocalizationTests.m */,
C1054F901FE197AE0033C87E /* STPPaymentContextSnapshotTests.m */,
);
name = Snapshot;
sourceTree = "<group>";
Expand Down Expand Up @@ -2573,11 +2591,17 @@
C1C02CCC1ECCD0ED00DF5643 /* EphemeralKey.json in Resources */,
F1BA24211E57BECA00E4A1CF /* 3DSSource.json in Resources */,
F1BA241E1E57BE5E00E4A1CF /* CardSource.json in Resources */,
8B39128520E2F9C400098401 /* GiropaySource.json in Resources */,
F1343BE91D652CAB00F102D8 /* Card.json in Resources */,
8B39128720E2F9D300098401 /* MultibancoSource.json in Resources */,
8BD213391F0457A1007F6FD1 /* FileUpload.json in Resources */,
C1CFCB7A1ED5F88D00BE45DF /* stp_test_upload_image.jpeg in Resources */,
F152322F1EA9344600D65C67 /* iDEALSource.json in Resources */,
F16AA26F1F5A0F1700207FFF /* AlipaySource.json in Resources */,
8B39128920E2F9E000098401 /* P24Source.json in Resources */,
8B39128220E2F99600098401 /* EPSSource.json in Resources */,
8B39128320E2F9A100098401 /* BancontactSource.json in Resources */,
8B39128B20E2F9F500098401 /* SOFORTSource.json in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
7 changes: 5 additions & 2 deletions Stripe/PublicHeaders/STPPaymentMethod.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,12 @@ typedef NS_OPTIONS(NSUInteger, STPPaymentMethodType) {
/**
This protocol represents a payment method that a user can select and use to
pay. Currently the only classes that conform to it are `STPCard`, which
represents that the user wants to pay with a specific card, and
represents that the user wants to pay with a specific card,
`STPApplePayPaymentMethod`, which represents that the user wants to pay with
Apple Pay.
Apple Pay, and `STPSource`. Only `STPSource.type == STPSourceTypeCard` payment
methods are supported by `STPPaymentContext` and `STPPaymentMethodViewController`,
but the other types do have basic support for this protocol for use in a custom
integration.
*/
@protocol STPPaymentMethod <NSObject>

Expand Down
2 changes: 1 addition & 1 deletion Stripe/PublicHeaders/STPSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Representation of a customer's payment instrument created with the Stripe API. @see https://stripe.com/docs/api#sources
*/
@interface STPSource : NSObject<STPAPIResponseDecodable, STPSourceProtocol>
@interface STPSource : NSObject<STPAPIResponseDecodable, STPSourceProtocol, STPPaymentMethod>

/**
You cannot directly instantiate an `STPSource`. You should only use one that
Expand Down
35 changes: 34 additions & 1 deletion Stripe/Resources/Localizations/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/* {card brand} ending in {last4} */
"%@ Ending In %@" = "%1$@ Ending In %2$@";

/* Source type brand name */
"3D Secure" = "3D Secure";

/* Title for Add a Card view */
"Add a Card" = "Add a Card";

Expand All @@ -10,12 +13,18 @@
/* Caption for Address field on address form */
"Address" = "Address";

/* Source type brand name */
"Alipay" = "Alipay";

/* Text for Apple Pay payment method */
"Apple Pay" = "Apple Pay";

/* Caption for Apartment/Address line 2 field on address form */
"Apt." = "Apt.";

/* Source type brand name */
"Bancontact" = "Bancontact";

/* Title for billing address entry section */
"Billing Address" = "Billing Address";

Expand Down Expand Up @@ -46,27 +55,42 @@
/* Caption for Email field on address form */
"Email" = "Email";

/* Source type brand name */
"EPS" = "EPS";

/* accessibility label for text field */
"expiration date" = "expiration date";

/* Label for free shipping method */
"Free" = "Free";

/* Source type brand name */
"Giropay" = "Giropay";

/* Source type brand name */
"iDEAL" = "iDEAL";

/* Shipping form error message */
"Invalid Shipping Address" = "Invalid Shipping Address";

/* Title for screen when data is still loading from the network. */
"Loading…" = "Loading…";

/* Source type brand name */
"Multibanco" = "Multibanco";

/* Caption for Name field on address form */
"Name" = "Name";

/* Button to move to the next text entry field */
"Next" = "Next";

/* No comment provided by engineer. */
/* ok button */
"OK" = "OK";

/* Source type brand name */
"P24" = "P24";

/* Title for Payment Method screen */
"Payment Method" = "Payment Method";

Expand All @@ -85,6 +109,9 @@
/* Text for button to scan a credit card */
"Scan Card" = "Scan Card";

/* Source type brand name */
"SEPA Direct Debit" = "SEPA Direct Debit";

/* Title for shipping info form */
"Shipping" = "Shipping";

Expand All @@ -94,6 +121,9 @@
/* Label for shipping method form */
"Shipping Method" = "Shipping Method";

/* Source type brand name */
"SOFORT" = "SOFORT";

/* Caption for State field on address form (only countries that use state , like United States) */
"State" = "State";

Expand All @@ -106,6 +136,9 @@
/* Unexpected error, such as a 500 from Stripe or a JSON parse error */
"There was an unexpected error -- try again in a few seconds" = "There was an unexpected error -- try again in a few seconds";

/* Default missing source type label */
"Unknown" = "Unknown";

/* Button to fill shipping address from billing address. */
"Use Billing" = "Use Billing";

Expand Down
2 changes: 1 addition & 1 deletion Stripe/STPSource+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

NS_ASSUME_NONNULL_BEGIN

@interface STPSource () <STPInternalAPIResponseDecodable, STPPaymentMethod>
@interface STPSource () <STPInternalAPIResponseDecodable>

+ (STPSourceType)typeFromString:(NSString *)string;
+ (nullable NSString *)stringFromType:(STPSourceType)type;
Expand Down
45 changes: 33 additions & 12 deletions Stripe/STPSource.m
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,7 @@ + (instancetype)decodedObjectFromAPIResponse:(NSDictionary *)response {
#pragma mark - STPPaymentMethod

- (UIImage *)image {
if (self.type == STPSourceTypeCard
&& self.cardDetails != nil) {
if (self.type == STPSourceTypeCard && self.cardDetails != nil) {
return [STPImageLibrary brandImageForCardBrand:self.cardDetails.brand];
}
else {
Expand All @@ -279,8 +278,7 @@ - (UIImage *)image {
}

- (UIImage *)templateImage {
if (self.type == STPSourceTypeCard
&& self.cardDetails != nil) {
if (self.type == STPSourceTypeCard && self.cardDetails != nil) {
return [STPImageLibrary templatedBrandImageForCardBrand:self.cardDetails.brand];
}
else {
Expand All @@ -289,15 +287,38 @@ - (UIImage *)templateImage {
}

- (NSString *)label {
if (self.type == STPSourceTypeCard
&& self.cardDetails != nil) {
NSString *brand = [STPCard stringFromBrand:self.cardDetails.brand];
return [NSString stringWithFormat:@"%@ %@", brand, self.cardDetails.last4];;
}
else {
return [STPCard stringFromBrand:STPCardBrandUnknown];
switch (self.type) {
case STPSourceTypeBancontact:
return STPLocalizedString(@"Bancontact", @"Source type brand name");
case STPSourceTypeCard:
if (self.cardDetails != nil) {
NSString *brand = [STPCard stringFromBrand:self.cardDetails.brand];
return [NSString stringWithFormat:@"%@ %@", brand, self.cardDetails.last4];
}
else {
return [STPCard stringFromBrand:STPCardBrandUnknown];
}
case STPSourceTypeGiropay:
return STPLocalizedString(@"Giropay", @"Source type brand name");
case STPSourceTypeIDEAL:
return STPLocalizedString(@"iDEAL", @"Source type brand name");
case STPSourceTypeSEPADebit:
return STPLocalizedString(@"SEPA Direct Debit", @"Source type brand name");
case STPSourceTypeSofort:
return STPLocalizedString(@"SOFORT", @"Source type brand name");
case STPSourceTypeThreeDSecure:
return STPLocalizedString(@"3D Secure", @"Source type brand name");
case STPSourceTypeAlipay:
return STPLocalizedString(@"Alipay", @"Source type brand name");
case STPSourceTypeP24:
return STPLocalizedString(@"P24", @"Source type brand name");
case STPSourceTypeEPS:
return STPLocalizedString(@"EPS", @"Source type brand name");
case STPSourceTypeMultibanco:
return STPLocalizedString(@"Multibanco", @"Source type brand name");
case STPSourceTypeUnknown:
return STPLocalizedString(@"Unknown", @"Default missing source type label");
}
}


@end
23 changes: 12 additions & 11 deletions Tests/Tests/AlipaySource.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Source: https://stripe.com/docs/sources/alipay
{
"id": "src_123",
"object": "source",
Expand All @@ -8,19 +9,19 @@
"flow": "redirect",
"livemode": true,
"owner": {
"address": null,
"email": null,
"name": null,
"phone": null,
"verified_address": null,
"verified_email": null,
"verified_name": null,
"verified_phone": null,
"address": null,
"email": null,
"name": null,
"phone": null,
"verified_address": null,
"verified_email": null,
"verified_name": null,
"verified_phone": null,
},
"redirect": {
"return_url": "https://shop.foo.com/crtABC",
"status": "pending",
"url": "https://pay.stripe.com/redirect/src_123?client_secret=src_client_secret_123"
"return_url": "https://shop.foo.com/crtABC",
"status": "pending",
"url": "https://pay.stripe.com/redirect/src_123?client_secret=src_client_secret_123"
},
"statement_descriptor": null,
"status": "pending",
Expand Down
38 changes: 38 additions & 0 deletions Tests/Tests/BancontactSource.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Source: https://stripe.com/docs/sources/bancontact
{
"id": "src_16xhynE8WzK49JbAs9M21jaR",
"object": "source",
"amount": 1099,
"client_secret": "src_client_secret_UfwvW2WHpZ0s3QEn9g5x7waU",
"created": 1445277809,
"currency": "eur",
"statement_descriptor": null,
"flow": "redirect",
"livemode": true,
"owner": {
"address": null,
"email": null,
"name": "Jenny Rosen",
"phone": null,
"verified_address": null,
"verified_email": null,
"verified_name": "Jenny Rosen",
"verified_phone": null
},
"redirect": {
"return_url": "https://shop.example.com/crtA6B28E1",
"status": "pending",
"url": "https://pay.stripe.com/redirect/src_16xhynE8WzK49JbAs9M21jaR?client_secret=src_client_secret_UfwvW2WHpZ0s3QEn9g5x7waU"
},
"status": "pending",
"type": "bancontact",
"usage": "single_use",
"bancontact": {
"bank_code": null,
"bic": null,
"bank_name": null,
"iban_last4": null,
"statement_descriptor": null,
"preferred_language": null
}
}
1 change: 1 addition & 0 deletions Tests/Tests/CardSource.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Source: https://stripe.com/docs/sources/cards
{
"id": "src_123",
"object": "source",
Expand Down
34 changes: 34 additions & 0 deletions Tests/Tests/EPSSource.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Source: https://stripe.com/docs/sources/eps
{
"id": "src_16xhynE8WzK49JbAs9M21jaR",
"object": "source",
"amount": 1099,
"client_secret": "src_client_secret_UfwvW2WHpZ0s3QEn9g5x7waU",
"created": 1445277809,
"currency": "eur",
"flow": "redirect",
"livemode": true,
"owner": {
"address": null,
"email": null,
"name": "Jenny Rosen",
"phone": null,
"verified_address": null,
"verified_email": null,
"verified_name": "Jenny Rosen",
"verified_phone": null
},
"redirect": {
"return_url": "https://shop.example.com/crtA6B28E1",
"status": "pending",
"url": "https://pay.stripe.com/redirect/src_16xhynE8WzK49JbAs9M21jaR?client_secret=src_client_secret_UfwvW2WHpZ0s3QEn9g5x7waU"
},
"statement_descriptor": null,
"status": "pending",
"type": "eps",
"usage": "single_use",
"eps": {
"reference": null,
"statement_descriptor": null,
}
}
Loading