I am attempting to store a users credit card into stripe. Once the token is made, I attempt to save the token with the user to Stripe as a customer. But I didnt find any answer to my problem, I just need to store a card to a user that already exist.
I tried to use the method Stripe.Customers.update but it store the new card removing the "default" card if the user had one. And using the method Stripe.Customers.create it create a new customer with the new card, but I need to store in specific user.
Cloud Code:
Parse.Cloud.define("stripeCreateCard", function(request,response)
{
Stripe.initialize(STRIPE_SECRET_KEY);
Stripe.Customers.create
(
request.params,
{
success:function(results)
{
response.success(results);
},
error:function(error)
{
response.error("Error:" +error);
}
}
);
});
Parse.Cloud.define("stripeUpdateCustomer", function(request, response)
{
Stripe.initialize(STRIPE_SECRET_KEY);
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);
}
}
);
});
iOS Code:
class func getParamsForAddingCardToCustomer(custormerId: String, cardToken: String) -> NSDictionary {
let params = NSMutableDictionary()
params.setObject(["card" : cardToken], forKey: "data")
params.setObject(custormerId, forKey: "customerId")
return params
}
var params = ParamsHelper.getParamsForAddingCardToCustomer(stripeId, cardToken: token)
PFCloud.callFunctionInBackground("stripeCreateCard", withParameters: params as [NSObject : AnyObject]) {
(response: AnyObject?, error: NSError?) -> Void in
let responseString = response as? String
if (error === nil) {
println("Response: \(responseString) ")
}
else if (error != nil) {
println("Error: \(error) \(error!.userInfo)")
}
}
I have tried several parameters to store the card as I need, but I always got error 'Received unknown parameters'
Anyone got any ideas how to store a card without removing or creating new customer?
Parse's stripe implementation is not as complete as it could be. In many cases you must use an HTTPRequest to perform stripe functions that Parse does not offer.
For those cases I use the following iOS method and CloudCode to execute all of my stripe HTTPRequests. It is very easy to code while following the stripe CURL API documentation. I then build off this method to perform most stripe tasks, IE create/update/delete customers, cards, charges etc.
I start by feeding it a Method, ie GET, POST, DELETE depending on whether you want to retrieve, create/update, or remove a stripe object.
I then feed it a combination of optional pre/suf/postfixes to create a url.
Example URL created:
Finally I give it the parameters, in the instance of creating a card and adding it to a customer this would only need to be a dictionary containing the tokenID.
+(void)executeStripeCloudCodeWithMethod:(NSString *)method
prefix:(NSString *)prefix
suffix:(NSString *)suffix
postfix:(NSString *)postfix
secondPostfix:(NSString *)secondPostfix
parameters:(NSDictionary *)params
completionHandler:(ELStripeCompletionBlock)handler
{
NSDictionary *parameters = @{@"method":method,
@"prefix":prefix?prefix:@"",
@"suffix":suffix?suffix:@"",
@"postfix":postfix?postfix:@"",
@"secondPostfix":secondPostfix?secondPostfix:@"",
@"params":params?params:[NSNull null]
};
[PFCloud callFunctionInBackground:@"stripeHTTPRequest"
withParameters:parameters
block:^(id object, NSError *error) {
id jsonObject;
if (!error) {
NSError *jsonError = nil;
//Turn the json string into an NSDictionary
jsonObject = [NSJSONSerialization JSONObjectWithData:[object dataUsingEncoding:NSUTF8StringEncoding]
options:kNilOptions error:&jsonError];
}
handler(jsonObject,error);
}];
}
The cloud code that is executed:
var STRIPE_SECRET_KEY = 'sk_test_your_test_code_here';
var STRIPE_API_BASE_URL = 'api.stripe.com/v1/'
Parse.Cloud.define("stripeHTTPRequest", function(request, response)
{
//Check for valid pre/suf/postfixes, if they are not there do not include them.
var prefix = request.params["prefix"];
var suffix = "";
var postfix = "";
var secondPostfix = "";
if (!isEmpty(request.params["suffix"])) suffix = '/'+request.params['suffix'];
if (!isEmpty(request.params["postfix"])) postfix = '/'+request.params['postfix'];
if (!isEmpty(request.params["secondPostfix"])) secondPostfix = '/'+request.params['secondPostfix'];
Parse.Cloud.httpRequest(
{
method: request.params["method"],
//Create URL from base url and pre/suf/postfixes
url: 'https://'+STRIPE_API_BASE_URL + prefix + suffix + postfix + secondPostfix,
headers: {
'Authorization': "Bearer " + STRIPE_SECRET_KEY
},
params:request.params["params"],
success: function(httpResponse)
{
//response text is a json dictionary
response.success(httpResponse.text);
},
error: function(httpResponse)
{
response.error(httpResponse.text);
}
});
});
Using the method above I can create individual methods to perform most of the stripe tasks I need.
Here is an example that will create a new card and attach it to a customer Stripe Card creation API
+ (void)createCardFromToken:(NSString *)tokenId customerId:(NSString *)customerId completionHandler:(ELCardCompletionBlock)handler
{
[ELStripe executeStripeCloudCodeWithMethod:@"POST" //I use post here because we are creating a card. POST would also be used for updating a customer/card or refunding a charge for example
prefix:@"customers" //If you look at the documentation and the example URL I use "customers" here as the prefix
suffix:customerId //The customerID is the suffix, this will be the customer you are going to add the card to
postfix:@"cards" //I believe this is "sources" now
secondPostfix:nil //Not needed for this URL
parameters:@{
@"card":tokenId //Only parameter is a tokenId, and I wrap this inside an NSDictionary
}
completionHandler:^(id jsonObject, NSError *error) {
if (error)
{
//Handle the error code here
handler(nil,rejectError);
return;
}
//If no error stripe returns a dictionary containing the card information. You can use this information to create a card object if so desired.
handler([ELCard cardFromDictionary:jsonObject],error);
}];
}