Merge remote-tracking branch 'origin/master' into yuki-fix-example-names

This commit is contained in:
Yuki Tokuhiro 2019-05-22 11:46:17 -07:00
commit 8831bdc9f4
22 changed files with 507 additions and 8 deletions

View File

@ -1 +1 @@
github "Alamofire/Alamofire" "4.4.0"
github "Alamofire/Alamofire" "4.8.2"

View File

@ -10,7 +10,7 @@ import Foundation
import Stripe
import Alamofire
class MyAPIClient: NSObject, STPEphemeralKeyProvider {
class MyAPIClient: NSObject, STPCustomerEphemeralKeyProvider {
static let sharedClient = MyAPIClient()
var baseURLString: String? = nil

View File

@ -477,6 +477,8 @@
B63E42762231D78D007B5B95 /* STPPaymentMethodCardParams.m in Sources */ = {isa = PBXBuildFile; fileRef = B6027BC12230ABAE0025DB29 /* STPPaymentMethodCardParams.m */; };
B63E42772231D78D007B5B95 /* STPPaymentMethodCardParams.m in Sources */ = {isa = PBXBuildFile; fileRef = B6027BC12230ABAE0025DB29 /* STPPaymentMethodCardParams.m */; };
B63E42792231F8FE007B5B95 /* STPPaymentMethodParamsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B63E42782231F8FE007B5B95 /* STPPaymentMethodParamsTest.m */; };
B665CE47228DE4C4008B546F /* STPPaymentMethodListDeserializer.h in Headers */ = {isa = PBXBuildFile; fileRef = B665CE45228DE4C4008B546F /* STPPaymentMethodListDeserializer.h */; };
B665CE48228DE4C4008B546F /* STPPaymentMethodListDeserializer.m in Sources */ = {isa = PBXBuildFile; fileRef = B665CE46228DE4C4008B546F /* STPPaymentMethodListDeserializer.m */; };
B66B39B4223044A2006D1CAD /* STPPaymentMethodTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B66B39B3223044A2006D1CAD /* STPPaymentMethodTest.m */; };
B66B39B6223045EF006D1CAD /* PaymentMethod.json in Resources */ = {isa = PBXBuildFile; fileRef = B66B39B5223045EF006D1CAD /* PaymentMethod.json */; };
B66D5021222F5611004A9210 /* STPPaymentMethodCardChecks.m in Sources */ = {isa = PBXBuildFile; fileRef = B66D5020222F5611004A9210 /* STPPaymentMethodCardChecks.m */; };
@ -484,6 +486,8 @@
B66D5024222F5A27004A9210 /* STPPaymentMethodThreeDSecureUsageTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B66D5023222F5A27004A9210 /* STPPaymentMethodThreeDSecureUsageTest.m */; };
B66D5025222F62E3004A9210 /* STPCustomerTest.m in Copy Files */ = {isa = PBXBuildFile; fileRef = C1D23FAC1D37F81F002FD83C /* STPCustomerTest.m */; };
B66D5027222F8605004A9210 /* STPPaymentMethodCardChecksTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B66D5026222F8605004A9210 /* STPPaymentMethodCardChecksTest.m */; };
B67D7D4B2294A081000FBA12 /* STPPaymentMethodListDeserializer.h in Headers */ = {isa = PBXBuildFile; fileRef = B665CE45228DE4C4008B546F /* STPPaymentMethodListDeserializer.h */; };
B67D7D4D2294A0FD000FBA12 /* STPPaymentMethodListDeserializer.m in Sources */ = {isa = PBXBuildFile; fileRef = B665CE46228DE4C4008B546F /* STPPaymentMethodListDeserializer.m */; };
B68F1C792234740B0030B438 /* STPPaymentMethodCardWalletTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B68F1C782234740B0030B438 /* STPPaymentMethodCardWalletTest.m */; };
B690DDEC222F01BF000B902D /* STPPaymentMethodBillingDetails.h in Headers */ = {isa = PBXBuildFile; fileRef = B690DDEA222F01BF000B902D /* STPPaymentMethodBillingDetails.h */; settings = {ATTRIBUTES = (Public, ); }; };
B690DDED222F01BF000B902D /* STPPaymentMethodBillingDetails.h in Headers */ = {isa = PBXBuildFile; fileRef = B690DDEA222F01BF000B902D /* STPPaymentMethodBillingDetails.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -1335,6 +1339,8 @@
B621F05E223465EE002141B7 /* STPPaymentMethodCardWalletVisaCheckout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = STPPaymentMethodCardWalletVisaCheckout.m; sourceTree = "<group>"; };
B628476122307A4100957149 /* STPPaymentMethodCardTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = STPPaymentMethodCardTest.m; sourceTree = "<group>"; };
B63E42782231F8FE007B5B95 /* STPPaymentMethodParamsTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = STPPaymentMethodParamsTest.m; sourceTree = "<group>"; };
B665CE45228DE4C4008B546F /* STPPaymentMethodListDeserializer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = STPPaymentMethodListDeserializer.h; sourceTree = "<group>"; };
B665CE46228DE4C4008B546F /* STPPaymentMethodListDeserializer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = STPPaymentMethodListDeserializer.m; sourceTree = "<group>"; };
B66B39B3223044A2006D1CAD /* STPPaymentMethodTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = STPPaymentMethodTest.m; sourceTree = "<group>"; };
B66B39B5223045EF006D1CAD /* PaymentMethod.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = PaymentMethod.json; sourceTree = "<group>"; };
B66D5020222F5611004A9210 /* STPPaymentMethodCardChecks.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STPPaymentMethodCardChecks.m; sourceTree = "<group>"; };
@ -2290,6 +2296,8 @@
B6DB0CA822381B4900AEF640 /* STPPaymentMethod+Private.h */,
B69CFB4922370547001E9885 /* STPPaymentMethodCardChecks+Private.h */,
B6B41F74223481BA0020BA7F /* STPPaymentMethodCardWallet+Private.h */,
B665CE45228DE4C4008B546F /* STPPaymentMethodListDeserializer.h */,
B665CE46228DE4C4008B546F /* STPPaymentMethodListDeserializer.m */,
B32B176420F80442000D6EF8 /* STPRedirectContext+Private.h */,
C1C1012C1E57A26F00C7BFAE /* STPSource+Private.h */,
8BD87B871EFB131400269C2B /* STPSourceCardDetails+Private.h */,
@ -2562,6 +2570,7 @@
C1BD9B3A1E39416700CEE925 /* STPSourceOwner.h in Headers */,
F1D3A2541EB012350095BFA9 /* STPMultipartFormDataEncoder.h in Headers */,
C1C1012E1E57A26F00C7BFAE /* STPSource+Private.h in Headers */,
B67D7D4B2294A081000FBA12 /* STPPaymentMethodListDeserializer.h in Headers */,
04A488431CA3580700506E53 /* UINavigationController+Stripe_Completion.h in Headers */,
B6B5FC42222F4C0200440249 /* STPPaymentMethodThreeDSecureUsage.h in Headers */,
C124A1711CCA968B007D42EE /* STPAnalyticsClient.h in Headers */,
@ -2740,6 +2749,7 @@
C15993281D8808490047950D /* STPShippingAddressViewController.h in Headers */,
C1D7B5201E36C32F002181F5 /* STPSource.h in Headers */,
B621F053223454E9002141B7 /* STPPaymentMethodCardWallet.h in Headers */,
B665CE47228DE4C4008B546F /* STPPaymentMethodListDeserializer.h in Headers */,
049A3F7A1CC18D5300F57DE7 /* UIView+Stripe_FirstResponder.h in Headers */,
04CDB50E1A5F30A700B854EE /* STPCard.h in Headers */,
C1BD9B391E39416700CEE925 /* STPSourceOwner.h in Headers */,
@ -3038,6 +3048,7 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
"zh-Hans",
de,
@ -3507,6 +3518,7 @@
04F94DAE1D229F54004FC826 /* STPColorUtils.m in Sources */,
C1D7B51D1E36B8B9002181F5 /* STPSourceParams.m in Sources */,
C124A1731CCA968B007D42EE /* STPAnalyticsClient.m in Sources */,
B67D7D4D2294A0FD000FBA12 /* STPPaymentMethodListDeserializer.m in Sources */,
B6F16099223351C20088C970 /* STPPaymentIntentActionRedirectToURL.m in Sources */,
04F94DCC1D22A22C004FC826 /* UIView+Stripe_FirstResponder.m in Sources */,
F1D3A2571EB012350095BFA9 /* STPMultipartFormDataPart.m in Sources */,
@ -3636,6 +3648,7 @@
B6F16092223350640088C970 /* STPPaymentIntentAction.m in Sources */,
C15993391D8808680047950D /* STPShippingMethodTableViewCell.m in Sources */,
C1BD9B2A1E39406C00CEE925 /* STPSourceOwner.m in Sources */,
B665CE48228DE4C4008B546F /* STPPaymentMethodListDeserializer.m in Sources */,
F1DEB89B1E2074480066B8E8 /* STPCoreViewController.m in Sources */,
B6DE52DD2230981200B70A66 /* STPPaymentMethodParams.m in Sources */,
C1D7B5221E36C32F002181F5 /* STPSource.m in Sources */,

View File

@ -118,6 +118,56 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)updateCustomerWithShippingAddress:(STPAddress *)shipping completion:(nullable STPErrorBlock)completion;
#pragma mark - Payment Method
/**
Adds a Payment Method to a customer.
If you are implementing your own <STPBackendAPIAdapter>:
On your backend, retrieve the Stripe customer associated with your logged-in user.
Then, call the Attach method on the Payment Method with that customer's ID
( https://stripe.com/docs/api/payment_methods/attach ). If this API call succeeds,
call `completion(nil)`. Otherwise, call `completion(error)` with the error that
occurred.
@param paymentMethod A valid Payment Method
@param completion Call this callback when you're done adding the payment method
to the customer on your backend. For example, `completion(nil)` (if your call succeeds)
or `completion(error)` if an error is returned.
*/
- (void)attachPaymentMethodToCustomer:(STPPaymentMethod *)paymentMethod completion:(STPErrorBlock)completion;
/**
Deletes the given Payment Method from the customer.
If you are implementing your own <STPBackendAPIAdapter>:
Call the Detach method ( https://stripe.com/docs/api/payment_methods/detach )
on the Payment Method. If this API call succeeds, call `completion(nil)`.
Otherwise, call `completion(error)` with the error that occurred.
@param paymentMethod The Payment Method to delete from the customer
@param completion Call this callback when you're done deleting the Payment Method
from the customer on your backend. For example, `completion(nil)` (if your call
succeeds) or `completion(error)` if an error is returned.
*/
- (void)detachPaymentMethodFromCustomer:(STPPaymentMethod *)paymentMethod completion:(nullable STPErrorBlock)completion;
/**
Retrieves a list of Payment Methods attached to a customer.
If you are implementing your own <STPBackendAPIAdapter>:
Call the list method ( https://stripe.com/docs/api/payment_methods/lists )
with the Stripe customer. If this API call succeeds, call `completion(paymentMethods)`
with the list of PaymentMethods. Otherwise, call `completion(error)` with the error
that occurred.
@param completion Call this callback with the list of Payment Methods attached to the
customer. For example, `completion(paymentMethods)` (if your call succeeds) or
`completion(error)` if an error is returned.
*/
- (void)listPaymentMethodsForCustomerWithCompletion:(STPPaymentMethodsCompletionBlock)completion;
@end
NS_ASSUME_NONNULL_END

View File

@ -125,6 +125,14 @@ typedef void (^STPPaymentIntentCompletionBlock)(STPPaymentIntent * __nullable pa
*/
typedef void (^STPPaymentMethodCompletionBlock)(STPPaymentMethod * __nullable paymentMethod, NSError * __nullable error);
/**
A callback to be run with an array of PaymentMethods response from the Stripe API.
@param paymentMethods An array of PaymentMethod from the response. Will be nil if an error occurs. @see STPPaymentMethod
@param error The error returned from the response, or nil if none occurs. @see StripeError.h for possible values.
*/
typedef void (^STPPaymentMethodsCompletionBlock)(NSArray<STPPaymentMethod *> *__nullable paymentMethods, NSError * __nullable error);
/**
A callback to be run with a validation result and shipping methods for a
shipping address.

View File

@ -10,6 +10,7 @@
#import "STPAPIResponseDecodable.h"
#import "STPPaymentMethodEnums.h"
#import "STPPaymentOption.h"
@class STPPaymentMethodBillingDetails, STPPaymentMethodCard, STPPaymentMethodiDEAL, STPPaymentMethodCardPresent;
@ -20,7 +21,7 @@ NS_ASSUME_NONNULL_BEGIN
@see https://stripe.com/docs/api/payment_methods
*/
@interface STPPaymentMethod : NSObject <STPAPIResponseDecodable>
@interface STPPaymentMethod : NSObject <STPAPIResponseDecodable, STPPaymentOption>
/**
Unique identifier for the object.

View File

@ -13,6 +13,8 @@
NS_ASSUME_NONNULL_BEGIN
@class STPAddress;
/**
The billing address, a property on `STPPaymentMethodBillingDetails`
*/
@ -48,6 +50,11 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, copy, nullable, readwrite) NSString *state;
/**
Convenience initializer for creating a STPPaymentMethodAddress from an STPAddress.
*/
- (instancetype)initWithAddress:(STPAddress *)address;
@end
NS_ASSUME_NONNULL_END

View File

@ -77,6 +77,16 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, nullable, readonly) STPPaymentMethodCardWallet *wallet;
/**
Returns a string representation for the provided card brand;
i.e. `[NSString stringFromBrand:STPCardBrandVisa] == @"Visa"`.
@param brand the brand you want to convert to a string
@return A string representing the brand, suitable for displaying to a user.
*/
+ (NSString *)stringFromBrand:(STPCardBrand)brand;
@end
NS_ASSUME_NONNULL_END

View File

@ -35,13 +35,21 @@ typedef NS_OPTIONS(NSUInteger, STPPaymentOptionType) {
/**
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,
`STPApplePay`, which represents that the user wants to pay with
Apple Pay, and `STPSource`. Only `STPSource.type == STPSourceTypeCard` payment
pay.
Currently the classes that conform to it are:
- `STPCard`, which represents that the user wants to pay with a specific card
- `STPApplePay`, which represents that the user wants to pay with
Apple Pay
- `STPSource`. Only `STPSource.type == STPSourceTypeCard` payment
methods are supported by `STPPaymentContext` and `STPPaymentOptionsViewController`,
but the other types do have basic support for this protocol for use in a custom
integration.
- `STPPaymentMethod`. Only `STPPaymentMethod.type == STPPaymentMethodTypeCard` is
supported by `STPPaymentContext` and `STPPaymentOptionsViewController`, but the other
types do have basic support for this protocol for use in a custom integration.
*/
@protocol STPPaymentOption <NSObject>

View File

@ -81,6 +81,31 @@ toCustomerUsingKey:(STPEphemeralKey *)ephemeralKey
fromCustomerUsingKey:(STPEphemeralKey *)ephemeralKey
completion:(STPErrorBlock)completion;
/**
Attach a Payment Method to a customer
@see https://stripe.com/docs/api/payment_methods/attach
*/
+ (void)attachPaymentMethod:(NSString *)paymentMethodID
toCustomerUsingKey:(STPEphemeralKey *)ephemeralKey
completion:(STPErrorBlock)completion;
/**
Detach a Payment Method from a customer
@see https://stripe.com/docs/api/payment_methods/detach
*/
+ (void)detachPaymentMethod:(NSString *)paymentMethodID
fromCustomerUsingKey:(STPEphemeralKey *)ephemeralKey
completion:(STPErrorBlock)completion;
/**
Retrieves a list of Payment Methods attached to a customer.
@note This only fetches card type Payment Methods
*/
+ (void)listPaymentMethodsForCustomerUsingKey:(STPEphemeralKey *)ephemeralKey
completion:(STPPaymentMethodsCompletionBlock)completion;
@end
@interface Stripe (Private)

View File

@ -27,7 +27,9 @@
#import "STPMultipartFormDataEncoder.h"
#import "STPMultipartFormDataPart.h"
#import "STPPaymentConfiguration.h"
#import "STPPaymentMethodListDeserializer.h"
#import "STPPaymentMethodParams.h"
#import "STPPaymentMethod+Private.h"
#import "STPPaymentIntent+Private.h"
#import "STPPaymentIntentParams.h"
#import "STPSource+Private.h"
@ -588,6 +590,45 @@ toCustomerUsingKey:(STPEphemeralKey *)ephemeralKey
}];
}
+ (void)attachPaymentMethod:(NSString *)paymentMethodID toCustomerUsingKey:(STPEphemeralKey *)ephemeralKey completion:(STPErrorBlock)completion {
STPAPIClient *client = [self apiClientWithEphemeralKey:ephemeralKey];
NSString *endpoint = [NSString stringWithFormat:@"%@/%@/attach", APIEndpointPaymentMethods, paymentMethodID];
[STPAPIRequest<STPPaymentMethod *> postWithAPIClient:client
endpoint:endpoint
parameters:@{@"customer": ephemeralKey.customerID}
deserializer:[STPPaymentMethod new]
completion:^(__unused STPPaymentMethod *paymentMethod, __unused NSHTTPURLResponse *response, NSError *error) {
completion(error);
}];
}
+ (void)detachPaymentMethod:(NSString *)paymentMethodID fromCustomerUsingKey:(STPEphemeralKey *)ephemeralKey completion:(STPErrorBlock)completion {
STPAPIClient *client = [self apiClientWithEphemeralKey:ephemeralKey];
NSString *endpoint = [NSString stringWithFormat:@"%@/%@/detach", APIEndpointPaymentMethods, paymentMethodID];
[STPAPIRequest<STPPaymentMethod *> postWithAPIClient:client
endpoint:endpoint
parameters:nil
deserializer:[STPPaymentMethod new]
completion:^(__unused STPPaymentMethod *paymentMethod, __unused NSHTTPURLResponse *response, NSError *error) {
completion(error);
}];
}
+ (void)listPaymentMethodsForCustomerUsingKey:(STPEphemeralKey *)ephemeralKey completion:(STPPaymentMethodsCompletionBlock)completion {
STPAPIClient *client = [self apiClientWithEphemeralKey:ephemeralKey];
NSDictionary *params = @{
@"customer": ephemeralKey.customerID,
@"type": [STPPaymentMethod stringFromType:STPPaymentMethodTypeCard],
};
[STPAPIRequest<STPPaymentMethodListDeserializer *> getWithAPIClient:client
endpoint:APIEndpointPaymentMethods
parameters:params
deserializer:[STPPaymentMethodListDeserializer new]
completion:^(STPPaymentMethodListDeserializer *deserializer, __unused NSHTTPURLResponse *response, NSError *error) {
completion(deserializer.paymentMethods, error);
}];
}
@end
#pragma mark - Payment Intents

View File

@ -12,6 +12,7 @@
#import "STPCustomer+Private.h"
#import "STPEphemeralKey.h"
#import "STPEphemeralKeyManager.h"
#import "STPPaymentMethod.h"
#import "STPWeakStrongMacros.h"
#import "STPDispatchFunctions.h"
@ -203,4 +204,76 @@ static NSTimeInterval const CachedCustomerMaxAge = 60;
}];
}
#pragma mark Payment Method
- (void)attachPaymentMethodToCustomer:(STPPaymentMethod *)paymentMethod completion:(STPErrorBlock)completion {
[self.keyManager getOrCreateKey:^(STPEphemeralKey *ephemeralKey, NSError *retrieveKeyError) {
if (retrieveKeyError) {
if (completion) {
stpDispatchToMainThreadIfNecessary(^{
completion(retrieveKeyError);
});
}
return;
}
[STPAPIClient attachPaymentMethod:paymentMethod.stripeId
toCustomerUsingKey:ephemeralKey
completion:^(NSError *error) {
// No need to clearCachedCustomer since Customer doesnt have any PaymentMethod state
if (completion) {
stpDispatchToMainThreadIfNecessary(^{
completion(error);
});
}
}];
}];
}
- (void)detachPaymentMethodFromCustomer:(STPPaymentMethod *)paymentMethod completion:(STPErrorBlock)completion {
[self.keyManager getOrCreateKey:^(STPEphemeralKey *ephemeralKey, NSError *retrieveKeyError) {
if (retrieveKeyError) {
if (completion) {
stpDispatchToMainThreadIfNecessary(^{
completion(retrieveKeyError);
});
}
return;
}
[STPAPIClient detachPaymentMethod:paymentMethod.stripeId
fromCustomerUsingKey:ephemeralKey
completion:^(NSError *error) {
// No need to clearCachedCustomer since Customer doesnt have any PaymentMethod state
if (completion) {
stpDispatchToMainThreadIfNecessary(^{
completion(error);
});
}
}];
}];
}
- (void)listPaymentMethodsForCustomerWithCompletion:(STPPaymentMethodsCompletionBlock)completion {
[self.keyManager getOrCreateKey:^(STPEphemeralKey *ephemeralKey, NSError *retrieveKeyError) {
if (retrieveKeyError) {
if (completion) {
stpDispatchToMainThreadIfNecessary(^{
completion(nil, retrieveKeyError);
});
}
return;
}
[STPAPIClient listPaymentMethodsForCustomerUsingKey:ephemeralKey completion:^(NSArray<STPPaymentMethod *> *paymentMethods, NSError *error) {
if (completion) {
stpDispatchToMainThreadIfNecessary(^{
completion(paymentMethods, error);
});
}
}];
}];
}
@end

View File

@ -9,6 +9,8 @@
#import "STPPaymentMethod.h"
#import "NSDictionary+Stripe.h"
#import "STPImageLibrary.h"
#import "STPLocalizationUtils.h"
#import "STPPaymentMethodBillingDetails.h"
#import "STPPaymentMethodCard.h"
#import "STPPaymentMethodCardPresent.h"
@ -117,4 +119,39 @@
return paymentMethod;
}
#pragma mark - STPPaymentOption
- (UIImage *)image {
if (self.type == STPPaymentMethodTypeCard && self.card != nil) {
return [STPImageLibrary brandImageForCardBrand:self.card.brand];
} else {
return [STPImageLibrary brandImageForCardBrand:STPCardBrandUnknown];
}
}
- (UIImage *)templateImage {
if (self.type == STPPaymentMethodTypeCard && self.card != nil) {
return [STPImageLibrary templatedBrandImageForCardBrand:self.card.brand];
} else {
return [STPImageLibrary templatedBrandImageForCardBrand:STPCardBrandUnknown];
}
}
- (NSString *)label {
switch (self.type) {
case STPPaymentMethodTypeCard:
if (self.card != nil) {
NSString *brand = [STPPaymentMethodCard stringFromBrand:self.card.brand];
return [NSString stringWithFormat:@"%@ %@", brand, self.card.last4];
} else {
return [STPPaymentMethodCard stringFromBrand:STPCardBrandUnknown];
}
case STPPaymentMethodTypeiDEAL:
return @"iDEAL";
case STPPaymentMethodTypeCardPresent:
case STPPaymentMethodTypeUnknown:
return STPLocalizedString(@"Unknown", @"Default missing source type label");
}
}
@end

View File

@ -9,6 +9,7 @@
#import "STPPaymentMethodAddress.h"
#import "NSDictionary+Stripe.h"
#import "STPAddress.h"
@interface STPPaymentMethodAddress ()
@ -18,6 +19,19 @@
@implementation STPPaymentMethodAddress
- (instancetype)initWithAddress:(STPAddress *)address {
self = [super init];
if (self) {
_city = [address.city copy];
_country = [address.country copy];
_line1 = [address.line1 copy];
_line2 = [address.line2 copy];
_postalCode = [address.postalCode copy];
_state = [address.state copy];
}
return self;
}
- (NSString *)description {
NSArray *props = @[
// Object

View File

@ -74,4 +74,27 @@
return card;
}
#pragma mark - STPCardBrand
+ (NSString *)stringFromBrand:(STPCardBrand)brand {
switch (brand) {
case STPCardBrandAmex:
return @"American Express";
case STPCardBrandDinersClub:
return @"Diners Club";
case STPCardBrandDiscover:
return @"Discover";
case STPCardBrandJCB:
return @"JCB";
case STPCardBrandMasterCard:
return @"MasterCard";
case STPCardBrandUnionPay:
return @"UnionPay";
case STPCardBrandVisa:
return @"Visa";
case STPCardBrandUnknown:
return @"Unknown";
}
}
@end

View File

@ -0,0 +1,25 @@
//
// STPPaymentMethodListDeserializer.h
// StripeiOS
//
// Created by Yuki Tokuhiro on 5/16/19.
// Copyright © 2019 Stripe, Inc. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "STPAPIResponseDecodable.h"
NS_ASSUME_NONNULL_BEGIN
@class STPPaymentMethod;
/**
Deserializes the response returned from https://stripe.com/docs/api/payment_methods/list
*/
@interface STPPaymentMethodListDeserializer : NSObject <STPAPIResponseDecodable>
@property (nonatomic, readonly) NSArray<STPPaymentMethod *> *paymentMethods;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,51 @@
//
// STPPaymentMethodListDeserializer.m
// StripeiOS
//
// Created by Yuki Tokuhiro on 5/16/19.
// Copyright © 2019 Stripe, Inc. All rights reserved.
//
#import "STPPaymentMethodListDeserializer.h"
#import "STPPaymentMethod.h"
#import "NSDictionary+Stripe.h"
@interface STPPaymentMethodListDeserializer()
@property (nonatomic, copy) NSArray<STPPaymentMethod *> *paymentMethods;
@property (nonatomic, copy, nonnull, readwrite) NSDictionary *allResponseFields;
@end
@implementation STPPaymentMethodListDeserializer
#pragma mark STPAPIResponseDecodable
+ (nullable instancetype)decodedObjectFromAPIResponse:(nullable NSDictionary *)response {
NSDictionary *dict = [response stp_dictionaryByRemovingNulls];
if (!dict) {
return nil;
}
// Required fields
NSArray<NSDictionary *> *data = [dict stp_arrayForKey:@"data"];
if (!data) {
return nil;
}
STPPaymentMethodListDeserializer *paymentMethodsDeserializer = [[self class] new];
NSMutableArray<STPPaymentMethod *> *paymentMethods = [NSMutableArray new];
for (NSDictionary *paymentMethodJSON in data) {
STPPaymentMethod *paymentMethod = [STPPaymentMethod decodedObjectFromAPIResponse:paymentMethodJSON];
if (paymentMethod) {
[paymentMethods addObject:paymentMethod];
}
}
paymentMethodsDeserializer.paymentMethods = paymentMethods;
return paymentMethodsDeserializer;
}
@end

View File

@ -9,6 +9,8 @@
#import <Foundation/Foundation.h>
#import "STPPaymentOption.h"
@class STPPaymentMethod, STPPaymentConfiguration;
NS_ASSUME_NONNULL_BEGIN
@interface STPPaymentOptionTuple : NSObject
@ -20,6 +22,16 @@ NS_ASSUME_NONNULL_BEGIN
selectedPaymentOption:(nullable id<STPPaymentOption>)selectedPaymentOption
addApplePayOption:(BOOL)applePayEnabled;
/**
Returns a tuple for the given array of STPPaymentMethod, filtered to only include the
the types supported by STPPaymentContext/STPPaymentOptionsViewController and adding
Apple Pay as a method if appropriate.
@return A new tuple ready to be used by the SDK's UI elements
*/
+ (instancetype)tupleFilteredForUIWithPaymentMethods:(NSArray<STPPaymentMethod *> *)paymentMethods
configuration:(STPPaymentConfiguration *)configuration;
@property (nonatomic, nullable, readonly) id<STPPaymentOption> selectedPaymentOption;
@property (nonatomic, readonly) NSArray<id<STPPaymentOption>> *paymentOptions;

View File

@ -8,7 +8,8 @@
#import "STPPaymentOptionTuple.h"
#import "STPApplePayPaymentOption.h"
#import "STPCard.h"
#import "STPPaymentConfiguration+Private.h"
#import "STPPaymentMethod.h"
NS_ASSUME_NONNULL_BEGIN
@ -48,6 +49,20 @@ NS_ASSUME_NONNULL_BEGIN
selectedPaymentOption:selected];
}
+ (instancetype)tupleFilteredForUIWithPaymentMethods:(NSArray<STPPaymentMethod *> *)paymentMethods
configuration:(STPPaymentConfiguration *)configuration {
NSMutableArray *paymentOptions = [NSMutableArray new];
for (STPPaymentMethod *paymentMethod in paymentMethods) {
if (paymentMethod.type == STPPaymentMethodTypeCard) {
[paymentOptions addObject:paymentMethod];
}
}
return [[self class] tupleWithPaymentOptions:paymentOptions
selectedPaymentOption:nil
addApplePayOption:configuration.applePayEnabled];
}
@end
NS_ASSUME_NONNULL_END

View File

@ -315,6 +315,83 @@
[self waitForExpectationsWithTimeout:2 handler:nil];
}
#pragma mark - Payment Method
- (void)testAttachPaymentMethodCallsAPIClientCorrectly {
STPEphemeralKey *customerKey = [STPFixtures ephemeralKey];
STPPaymentMethod *expectedPaymentMethod = [STPFixtures paymentMethod];
id mockAPIClient = OCMClassMock([STPAPIClient class]);
XCTestExpectation *exp = [self expectationWithDescription:@"APIClient attachPaymentMethod"];
OCMStub([mockAPIClient attachPaymentMethod:[OCMArg isEqual:expectedPaymentMethod.stripeId]
toCustomerUsingKey:[OCMArg isEqual:customerKey]
completion:[OCMArg any]]).andDo(^(NSInvocation *invocation) {
STPErrorBlock completion;
[invocation getArgument:&completion atIndex:4];
completion(nil);
[exp fulfill];
});
STPEphemeralKeyManager *mockKeyManager = [self mockKeyManagerWithKey:customerKey];
STPCustomerContext *sut = [[STPCustomerContext alloc] initWithKeyManager:mockKeyManager];
XCTestExpectation *exp2 = [self expectationWithDescription:@"CustomerContext attachPaymentMethod"];
[sut attachPaymentMethodToCustomer:expectedPaymentMethod completion:^(NSError *error) {
XCTAssertNil(error);
[exp2 fulfill];
}];
[self waitForExpectationsWithTimeout:2 handler:nil];
}
- (void)testDetachPaymentMethodCallsAPIClientCorrectly {
STPEphemeralKey *customerKey = [STPFixtures ephemeralKey];
STPPaymentMethod *expectedPaymentMethod = [STPFixtures paymentMethod];
id mockAPIClient = OCMClassMock([STPAPIClient class]);
XCTestExpectation *exp = [self expectationWithDescription:@"APIClient detachPaymentMethod"];
OCMStub([mockAPIClient detachPaymentMethod:[OCMArg isEqual:expectedPaymentMethod.stripeId]
fromCustomerUsingKey:[OCMArg isEqual:customerKey]
completion:[OCMArg any]]).andDo(^(NSInvocation *invocation) {
STPErrorBlock completion;
[invocation getArgument:&completion atIndex:4];
completion(nil);
[exp fulfill];
});
STPEphemeralKeyManager *mockKeyManager = [self mockKeyManagerWithKey:customerKey];
STPCustomerContext *sut = [[STPCustomerContext alloc] initWithKeyManager:mockKeyManager];
XCTestExpectation *exp2 = [self expectationWithDescription:@"CustomerContext detachPaymentMethod"];
[sut detachPaymentMethodFromCustomer:expectedPaymentMethod completion:^(NSError *error) {
XCTAssertNil(error);
[exp2 fulfill];
}];
[self waitForExpectationsWithTimeout:2 handler:nil];
}
- (void)testListPaymentMethodCallsAPIClientCorrectly {
STPEphemeralKey *customerKey = [STPFixtures ephemeralKey];
NSArray<STPPaymentMethod *> *expectedPaymentMethods = @[[STPFixtures paymentMethod]];
id mockAPIClient = OCMClassMock([STPAPIClient class]);
XCTestExpectation *exp = [self expectationWithDescription:@"APIClient listPaymentMethods"];
OCMStub([mockAPIClient listPaymentMethodsForCustomerUsingKey:[OCMArg isEqual:customerKey]
completion:[OCMArg any]]).andDo(^(NSInvocation *invocation) {
STPPaymentMethodsCompletionBlock completion;
[invocation getArgument:&completion atIndex:3];
completion(expectedPaymentMethods, nil);
[exp fulfill];
});
STPEphemeralKeyManager *mockKeyManager = [self mockKeyManagerWithKey:customerKey];
STPCustomerContext *sut = [[STPCustomerContext alloc] initWithKeyManager:mockKeyManager];
XCTestExpectation *exp2 = [self expectationWithDescription:@"CustomerContext listPaymentMethods"];
[sut listPaymentMethodsForCustomerWithCompletion:^(NSArray<STPPaymentMethod *> *paymentMethods, NSError *error) {
XCTAssertNil(error);
XCTAssertEqualObjects(paymentMethods, expectedPaymentMethods);
[exp2 fulfill];
}];
[self waitForExpectationsWithTimeout:2 handler:nil];
}
#pragma mark - includeApplePaySources
- (void)testFiltersApplePaySourcesByDefault {

View File

@ -157,6 +157,11 @@ extern NSString *const STPTestJSONSourceSOFORT;
*/
+ (STPLegalEntityParams *)legalEntityParams;
/**
A PaymentMethod object
*/
+ (STPPaymentMethod *)paymentMethod;
@end
@interface STPJsonSources : NSObject

View File

@ -323,4 +323,8 @@ NSString *const STPTestJSONSourceSOFORT = @"SOFORTSource";
return person;
}
+ (STPPaymentMethod *)paymentMethod {
return [STPPaymentMethod decodedObjectFromAPIResponse:[STPTestUtils jsonNamed:STPTestJSONPaymentMethod]];
}
@end