Skip to content

Commit fb23c79

Browse files
author
Brian Collins
committed
Initial commit
0 parents  commit fb23c79

17 files changed

+1520
-0
lines changed

.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
build/*
2+
*.pbxuser
3+
*.mode1v3
4+
5+
.DS_Store
6+
profile
7+
8+
xcuserdata
9+
10+
project.xcworkspace
11+

src/Stripe.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#define kStripeAPIBase @"https://api.stripe.com/v1"
2+
#define kStripeTokenPath @"tokens"
3+
4+
@interface StripeCard : NSObject
5+
6+
@property (strong, nonatomic) NSString *number;
7+
@property (strong, nonatomic) NSNumber *expiryMonth;
8+
@property (strong, nonatomic) NSNumber *expiryYear;
9+
@property (strong, nonatomic) NSString *cardSecurityCode;
10+
@property (strong, nonatomic) NSString *name;
11+
@property (strong, nonatomic) NSString *addressLine1;
12+
@property (strong, nonatomic) NSString *addressLine2;
13+
@property (strong, nonatomic) NSString *addressZip;
14+
@property (strong, nonatomic) NSString *addressState;
15+
@property (strong, nonatomic) NSString *addressCountry;
16+
17+
@property (strong, readonly) NSString *country;
18+
@property (strong, readonly) NSString *cvcCheck;
19+
@property (strong, readonly) NSString *lastFourDigits;
20+
@property (strong, readonly) NSString *type;
21+
22+
- (id)initWithResponseDictionary:(NSDictionary *)card;
23+
24+
@end
25+
26+
@interface StripeResponse : NSObject
27+
@property (strong, nonatomic) NSNumber *createdAt;
28+
@property (strong, nonatomic) NSString *currency;
29+
@property (strong, nonatomic) NSNumber *amount;
30+
@property (nonatomic) BOOL isUsed;
31+
@property (nonatomic) BOOL isLiveMode;
32+
@property (strong, nonatomic) NSString *token;
33+
@property (strong, nonatomic) StripeCard *card;
34+
35+
- (id)initWithResponseDictionary:(NSDictionary *)response;
36+
@end
37+
38+
@interface StripeConnection : NSObject
39+
40+
+ (StripeConnection *)connectionWithPublishableKey:(NSString *)publishableKey;
41+
- (id)initWithPublishableKey:(NSString *)publishableKey;
42+
- (void)performRequestWithCard:(StripeCard *)card amountInCents:(NSNumber *)amount currency:(NSString *)currency success:(void (^)(StripeResponse *response))success failure:(void (^)(NSDictionary *failure))failure;
43+
- (void)performRequestWithCard:(StripeCard *)card amountInCents:(NSNumber *)amount success:(void (^)(StripeResponse *response))success failure:(void (^)(NSDictionary *failure))failure;
44+
45+
@end
46+

src/Stripe.m

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
#import "Stripe.h"
2+
#import "STBase64.h"
3+
4+
@interface StripeCard ()
5+
@property (readonly) NSDictionary *attributes;
6+
@property (strong, readwrite) NSString *country;
7+
@property (strong, readwrite) NSString *cvcCheck;
8+
@property (strong, readwrite) NSString *lastFourDigits;
9+
@property (strong, readwrite) NSString *type;
10+
@end
11+
12+
@interface StripeConnection ()
13+
@property (strong, nonatomic) NSString *publishableKey;
14+
@end
15+
16+
@implementation StripeConnection
17+
@synthesize publishableKey = _publishableKey;
18+
19+
+ (StripeConnection *)connectionWithPublishableKey:(NSString *)publishableKey {
20+
return [[self alloc] initWithPublishableKey:publishableKey];
21+
}
22+
23+
- (id)initWithPublishableKey:(NSString *)publishableKey {
24+
if ((self = [super init])) {
25+
self.publishableKey = publishableKey;
26+
}
27+
28+
return self;
29+
}
30+
31+
- (NSString *)escapedString:(NSString *)string {
32+
return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
33+
(__bridge CFStringRef)string,
34+
NULL,
35+
(CFStringRef)@"!*'();:@&=+$,/?%#[]",
36+
kCFStringEncodingUTF8 );
37+
}
38+
39+
- (NSData *)HTTPBodyWithCard:(StripeCard *)card amountInCents:(NSNumber *)amount currency:(NSString *)currency {
40+
NSMutableString *body = [NSMutableString string];
41+
NSDictionary *attributes = card.attributes;
42+
43+
for (NSString *key in attributes) {
44+
NSString *value = [attributes objectForKey:key];
45+
if ((id)value == [NSNull null]) continue;
46+
47+
if (body.length != 0)
48+
[body appendString:@"&"];
49+
50+
if ([value isKindOfClass:[NSString class]])
51+
value = [self escapedString:value];
52+
53+
[body appendFormat:@"card[%@]=%@", [self escapedString:key], value];
54+
}
55+
56+
if (amount) {
57+
if (body.length != 0)
58+
[body appendString:@"&"];
59+
[body appendFormat:@"amount=%@", amount];
60+
}
61+
62+
if (currency) {
63+
if (body.length != 0)
64+
[body appendString:@"&"];
65+
[body appendFormat:@"currency=%@", currency];
66+
}
67+
68+
return [body dataUsingEncoding:NSUTF8StringEncoding];
69+
}
70+
71+
- (void)performRequestWithCard:(StripeCard *)card amountInCents:(NSNumber *)amount currency:(NSString *)currency success:(void (^)(StripeResponse *response))success failure:(void (^)(NSDictionary *failure))failure {
72+
NSURL *url = [[NSURL URLWithString:kStripeAPIBase] URLByAppendingPathComponent:kStripeTokenPath];
73+
74+
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
75+
request.HTTPBody = [self HTTPBodyWithCard:card amountInCents:amount currency:currency];
76+
77+
NSString *basicAuth = [NSString stringWithFormat:@"Basic %@",
78+
[STBase64 encode:[NSString stringWithFormat:@"%@:", self.publishableKey]]];
79+
[request setValue:basicAuth forHTTPHeaderField:@"Authorization"];
80+
[request setHTTPMethod:@"POST"];
81+
82+
[NSURLConnection sendAsynchronousRequest:request
83+
queue:[NSOperationQueue mainQueue]
84+
completionHandler:^(NSURLResponse *response, NSData *body, NSError *error)
85+
{
86+
NSDictionary *unserialized = [NSJSONSerialization JSONObjectWithData:body options:0 error:NULL];
87+
if ([(NSHTTPURLResponse *)response statusCode] == 200) {
88+
StripeResponse *stripeResponse = [[StripeResponse alloc] initWithResponseDictionary:unserialized];
89+
90+
success(stripeResponse);
91+
} else {
92+
failure(unserialized);
93+
}
94+
}];
95+
}
96+
97+
- (void)performRequestWithCard:(StripeCard *)card amountInCents:(NSNumber *)amount success:(void (^)(StripeResponse *response))success failure:(void (^)(NSDictionary *failure))failure {
98+
[self performRequestWithCard:card amountInCents:amount currency:@"usd" success:success failure:failure];
99+
}
100+
101+
@end
102+
103+
104+
@implementation StripeCard
105+
@synthesize number, expiryMonth, expiryYear, cardSecurityCode, name, addressLine1, addressLine2, addressZip, addressState, addressCountry, country, cvcCheck, lastFourDigits, type;
106+
107+
- (NSDictionary *)attributes {
108+
return [NSDictionary dictionaryWithObjectsAndKeys:
109+
self.number ? self.number : [NSNull null], @"number",
110+
self.expiryMonth ? self.expiryMonth : [NSNull null], @"exp_month",
111+
self.expiryYear ? self.expiryYear : [NSNull null], @"exp_year",
112+
self.cardSecurityCode ? self.cardSecurityCode : [NSNull null], @"cvc",
113+
self.name ? self.name : [NSNull null], @"name",
114+
self.addressLine1 ? self.addressLine1 : [NSNull null], @"address_line1",
115+
self.addressLine2 ? self.addressLine2 : [NSNull null], @"address_line2",
116+
self.addressZip ? self.addressZip : [NSNull null], @"address_zip",
117+
self.addressState ? self.addressState : [NSNull null], @"address_state",
118+
self.addressCountry ? self.addressCountry : [NSNull null], @"address_country",
119+
nil];
120+
}
121+
122+
- (id)initWithResponseDictionary:(NSDictionary *)card {
123+
if ((self = [super init])) {
124+
self.country = [card objectForKey:@"country"];
125+
self.cvcCheck = [card objectForKey:@"cvc_check"];
126+
self.expiryMonth = [card objectForKey:@"exp_month"];
127+
self.expiryYear = [card objectForKey:@"exp_year"];
128+
self.lastFourDigits = [card objectForKey:@"last4"];
129+
self.type = [card objectForKey:@"type"];
130+
}
131+
132+
return self;
133+
}
134+
135+
@end
136+
137+
@implementation StripeResponse
138+
@synthesize createdAt, currency, amount, isUsed, isLiveMode, token, card;
139+
140+
- (id)initWithResponseDictionary:(NSDictionary *)response {
141+
if ((self = [super init])) {
142+
self.createdAt = [response objectForKey:@"created"];
143+
self.currency = [response objectForKey:@"currency"];
144+
self.isUsed = [[response objectForKey:@"used"] boolValue];
145+
self.amount = [response objectForKey:@"amount"];
146+
self.isLiveMode = [[response objectForKey:@"livemode"] boolValue];
147+
self.token = [response objectForKey:@"id"];
148+
self.card = [[StripeCard alloc] initWithResponseDictionary:[response objectForKey:@"card"]];
149+
}
150+
151+
return self;
152+
}
153+
154+
@end

src/base/STBase64.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@interface STBase64 : NSObject
2+
3+
+ (NSString *)encode:(NSString *)string;
4+
5+
@end

src/base/STBase64.m

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#import "STBase64.h"
2+
3+
static char *alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
4+
5+
@implementation STBase64
6+
7+
+ (NSString *)encode:(NSString *)string {
8+
unsigned char *inputBuffer = (unsigned char *)[string UTF8String];
9+
int len = strlen((const char *)inputBuffer);
10+
int encodedLength = ((((len % 3) + len) / 3) * 4) + 1;
11+
unsigned char outputBuffer[encodedLength + 1];
12+
13+
14+
NSInteger i, j = 0;
15+
int remain;
16+
17+
for(i = 0; i < len; i += 3) {
18+
remain = len - i;
19+
20+
outputBuffer[j++] = alphabet[(inputBuffer[i] & 0xFC) >> 2];
21+
outputBuffer[j++] = alphabet[((inputBuffer[i] & 0x03) << 4) |
22+
((remain > 1) ? ((inputBuffer[i + 1] & 0xF0) >> 4): 0)];
23+
24+
if(remain > 1)
25+
outputBuffer[j++] = alphabet[((inputBuffer[i + 1] & 0x0F) << 2)
26+
| ((remain > 2) ? ((inputBuffer[i + 2] & 0xC0) >> 6) : 0)];
27+
else
28+
outputBuffer[j++] = '=';
29+
30+
if(remain > 2)
31+
outputBuffer[j++] = alphabet[inputBuffer[i + 2] & 0x3F];
32+
else
33+
outputBuffer[j++] = '=';
34+
}
35+
36+
outputBuffer[j] = '\0';
37+
38+
return [NSString stringWithUTF8String:(const char *)outputBuffer];
39+
}
40+
41+
@end

src/base/prefix.pch

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//
2+
// Prefix header for all source files of the 'stripe-ios' target in the 'stripe-ios' project
3+
//
4+
5+
#ifdef __OBJC__
6+
#import <Foundation/Foundation.h>
7+
#endif

stripe-example/Info.plist

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleDevelopmentRegion</key>
6+
<string>en</string>
7+
<key>CFBundleDisplayName</key>
8+
<string>${PRODUCT_NAME}</string>
9+
<key>CFBundleExecutable</key>
10+
<string>${EXECUTABLE_NAME}</string>
11+
<key>CFBundleIconFiles</key>
12+
<array/>
13+
<key>CFBundleIdentifier</key>
14+
<string>info.brisy.${PRODUCT_NAME:rfc1034identifier}</string>
15+
<key>CFBundleInfoDictionaryVersion</key>
16+
<string>6.0</string>
17+
<key>CFBundleName</key>
18+
<string>${PRODUCT_NAME}</string>
19+
<key>CFBundlePackageType</key>
20+
<string>APPL</string>
21+
<key>CFBundleShortVersionString</key>
22+
<string>1.0</string>
23+
<key>CFBundleSignature</key>
24+
<string>????</string>
25+
<key>CFBundleVersion</key>
26+
<string>1.0</string>
27+
<key>LSRequiresIPhoneOS</key>
28+
<true/>
29+
<key>UIRequiredDeviceCapabilities</key>
30+
<array>
31+
<string>armv7</string>
32+
</array>
33+
<key>UISupportedInterfaceOrientations</key>
34+
<array>
35+
<string>UIInterfaceOrientationPortrait</string>
36+
<string>UIInterfaceOrientationLandscapeLeft</string>
37+
<string>UIInterfaceOrientationLandscapeRight</string>
38+
</array>
39+
<key>UISupportedInterfaceOrientations~ipad</key>
40+
<array>
41+
<string>UIInterfaceOrientationPortrait</string>
42+
<string>UIInterfaceOrientationPortraitUpsideDown</string>
43+
<string>UIInterfaceOrientationLandscapeLeft</string>
44+
<string>UIInterfaceOrientationLandscapeRight</string>
45+
</array>
46+
</dict>
47+
</plist>

stripe-example/STAppDelegate.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#import <UIKit/UIKit.h>
2+
3+
@interface STAppDelegate : UIResponder <UIApplicationDelegate>
4+
5+
@property (strong, nonatomic) UIWindow *window;
6+
7+
@end

stripe-example/STAppDelegate.m

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#import "STAppDelegate.h"
2+
#import "STRootViewController.h"
3+
4+
@implementation STAppDelegate
5+
6+
@synthesize window = _window;
7+
8+
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
9+
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
10+
11+
STRootViewController *rootViewController = [[STRootViewController alloc] init];
12+
13+
self.window.rootViewController = [[UINavigationController alloc]
14+
initWithRootViewController:rootViewController];
15+
16+
[self.window makeKeyAndVisible];
17+
return YES;
18+
}
19+
20+
@end

stripe-example/STCardViewController.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
@class StripeConnection;
2+
3+
@protocol STCardViewControllerDelegate <NSObject>
4+
- (void)addToken:(NSString *)token;
5+
@end
6+
7+
@interface STCardViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate>
8+
9+
@property (strong, nonatomic) StripeConnection *stripeConnection;
10+
@property (weak, nonatomic) IBOutlet UITextField *nameField;
11+
@property (weak, nonatomic) IBOutlet UITextField *numberField;
12+
@property (weak, nonatomic) IBOutlet UITextField *expiryField;
13+
@property (weak, nonatomic) IBOutlet UITextField *CVCField;
14+
@property (weak, nonatomic) IBOutlet UIPickerView *pickerView;
15+
@property (weak, nonatomic) IBOutlet UIToolbar *keyboardToolbar;
16+
@property (weak, nonatomic) id <STCardViewControllerDelegate>delegate;
17+
18+
- (IBAction)fieldSelected:(UISegmentedControl *)control;
19+
- (IBAction)donePressed:(id)sender;
20+
@end

0 commit comments

Comments
 (0)