The Parse stripe API is not as complete as possible and should be. There are many functions that do not include initially, but the VIA HTTP request can be performed. I had to learn a bit of Javascript and an HTTP request to make many functions work. Of course, your first instinct should tell you that DO NOT store the CC number on any device! Each time you enter a custom CC number, you immediately receive a token, and then thatβs all you need to use.
Luckly stripe gives you the ability to retain customers and attach CC to customers, and then charge that customer in the future without returning a CC number. Parse api does not handle adding CC to the client, so I added this function myself.
So, steps 1 and 2 Create a client using the API, and create a token from the CC information that they enter again using the Parse API. If you need help with this and need cloud code, let me know.
Step 3 Add CC to the client. I use a custom Customer object, but the main thing you really need is a stripe customerId, which is the customer.identifier identifier in my code, and the tokenID from your CC, which in my case is token.tokenId. The answer will be a JSON string with map information, I will turn it into a dictionary, and then create an STPCard from the dictionary. I also show how to remove a card from a client.
IOS code:
+(void)addToken:(STPToken *)token toCustomerId:(NSString *)customerId completionHandler:(PFIdResultBlock)block { [PFCloud callFunctionInBackground:@"stripeUpdateCustomer" withParameters:@{@"customerId":customerId,@"data":@{@"card":token.tokenId}} block:block]; } + (void)removeCard:(STPCard *)card FromCustomer:(ELCustomer *)customer completion:(STPCardDeletionBlock)handler { if (!customer ||!customer.identifier || !card || !card.identifier || !handler) [NSException raise:@"RequiredParameter" format:@"Required Parameter Missing for deleting card from customer"]; [PFCloud callFunctionInBackground:@"stripeDeleteCardFromCustomer" withParameters:@{@"cardId":card.identifier,@"customerId":customer.identifier} block:^(id object, NSError *error) { NSDictionary *dict = nil; NSError *jsonError = nil; if (object && [object isKindOfClass:[NSString class]] && !error) { dict = [NSJSONSerialization JSONObjectWithData:[object dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&jsonError]; } if (!jsonError && dict) { handler(dict[@"id"],[dict[@"deleted"] boolValue],error); } else if(jsonError) handler(nil,NO,jsonError); else handler(nil,NO,error); }]; }
Cloud code required:
Parse.Cloud.define("stripeUpdateCustomer", function(request, response) { Stripe.Customers.update ( request.params["customerId"], request.params["data"], { success:function(results) { console.log(results["id"]); response.success(results); }, error:function(error) { response.error("Error:" +error); } } ); }); Parse.Cloud.define("stripeDeleteCardFromCustomer", function(request, response) { Stripe.initialize(STRIPE_SECRET_KEY); Parse.Cloud.httpRequest({ method:"DELETE",
The iOS code for charging a client or token notifies you of the necessary parameters in the dictionary: the amount in cents is not dollars, the currency, and then either the client or the token. Please note that a customer may have many credit cards, but one of them is an active credit card. An active card is a card that will be charged when paying a client:
//Will attempt to charge customer, if no customer exists, or it fails to charge the custoemr it will attempt to charge a card token directly; //*********Warning: This is the final step it will APPLY A CHARGE TO THE ACCOUNT.*************** -(void)processChargeThroughStripeWithCompletionHandler:(STPChargeCompletionHandler)handler { if (![self validForCardProcessing] && ![self validForCustomerProcessing]) { handler(nil,[NSError errorWithDomain:MY_ERROR_DOMAIN code:elErrorCodeNoCustomerOrTokenID userInfo:[NSDictionary dictionary]]); return; } [self processChargeThroughStripeUsingCustomerWithCompletionHandler:^(STPCharge *charge, NSError *error) { if (!error) handler(charge,error); else{ [self processChargeThroughStripeUsingCardWithCompletionHandler:^(STPCharge *charge, NSError *error) { handler(charge, error); }]; } }]; } //Process payment using a customer to their active card. No token is required if customer exists with a card on record. //*********Warning: This is the final step it will APPLY A CHARGE TO THE ACCOUNT.*************** -(void)processChargeThroughStripeUsingCustomerWithCompletionHandler:(STPChargeCompletionHandler)handler { if (!self.validForCustomerProcessing) { handler(self,[NSError errorWithDomain:MY_ERROR_DOMAIN code:elErrorCodeNoCustomerID userInfo:[NSDictionary dictionary]]); return; } [PFCloud callFunctionInBackground:@"chargeToken" withParameters:[STPCharge dictionaryFromSTPChargeForProccessingUsingCustomer:self] block:^(id object, NSError *error) { if (!error) { [self initSelfWithDictionary:object]; NSLog(@"object:%@",object); } handler(self,error); }]; } //Process payment using a token that is attached to the charge, when complete self will be updated with the new charge information //*********Warning: This is the final step it will APPLY A CHARGE TO THE ACCOUNT.*************** -(void)processChargeThroughStripeUsingCardWithCompletionHandler:(STPChargeCompletionHandler)handler { if (!self.validForCardProcessing) { handler(self,[NSError errorWithDomain:MY_ERROR_DOMAIN code:elErrorCodeNoTokenID userInfo:[NSDictionary dictionary]]); return; } [PFCloud callFunctionInBackground:@"chargeToken" withParameters:[STPCharge dictionaryFromSTPChargeForProccessingUsingCard:self] block:^(id object, NSError *error) { if (!error) { [self initSelfWithDictionary:object]; } handler(self,error); }]; } + (NSDictionary *)dictionaryFromSTPChargeForProccessingUsingCard:(STPCharge *)charge { NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; dictionary[@"amount"] = charge.amountInCents; dictionary[@"currency"] = charge.currency; dictionary[@"card"] = charge.token.tokenId; return dictionary; } + (NSDictionary *)dictionaryFromSTPChargeForProccessingUsingCustomer:(STPCharge *)charge { NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; dictionary[@"amount"] = charge.amountInCents; dictionary[@"currency"] = charge.currency; dictionary[@"customer"] = charge.customer.identifier; return dictionary; }
Cloud code for charging the client / token:
Parse.Cloud.define("chargeToken",function(request,response) { Stripe.initialize(STRIPE_SECRET_KEY); Stripe.Charges.create ( request.params, { success:function(results) { response.success(results); }, error:function(error) { response.error("Error:" +error); } } ); });