简体   繁体   English

iOS Parse Stripe Integration

[英]iOS Parse Stripe Integration

I'm fairly new to programming and I created an app to charge customers and would like to store their CC information and charge it at a later time. 我对编程很新,我创建了一个应用程序来向客户收费,并希望存储他们的CC信息并在以后收费。 I've been going through all the tutorials and documentation and I am unable to follow how I can integrate this into my app. 我一直在阅读所有的教程和文档,我无法理解如何将其集成到我的应用程序中。 Do I need to know other technical skills such as Rest API, Curl, Ruby, etc to get this set up? 我是否需要了解其他技术技能,例如Rest API,Curl,Ruby等才能进行此设置? All the guides and documentation is pointing to that direction. 所有指南和文档都指向了这个方向。 I don't really understand what GET/POST is for and how that fits into iOS Objective-C programming. 我真的不明白GET / POST是什么以及它如何适合iOS Objective-C编程。

Any guidance on how to set this up would be tremendously appreciated. 关于如何设置它的任何指导都将非常感激。 I've been stuck on this for some time now. 我已经坚持了一段时间了。

Parse's stripe API is not as complete as it could and should be. Parse的条带API并不像它应该的那样完整。 There are many features it does not include natively, but can be accomplished VIA an HTTP Request. 它本身不包含许多功能,但可以通过HTTP请求完成。 I had to learn a little bit of Javascript, and HTTP request to get many features working. 我必须学习一点Javascript和HTTP请求以获得许多功能。 Of course your first instinct should tell you do NOT store a CC number on any device ever! 当然,你的第一直觉应该告诉你不要在任何设备上存储CC号码! Anytime you have a user input a CC number, immediately get a token and then that is all you will need to use. 只要您有用户输入CC编号,立即获得一个令牌,然后就是您需要使用的全部内容。

Luckily stripe gives you the ability to save customers, and attached CC to customers, and then charge that customer in the future without getting the CC number again. 幸运的条纹使您能够节省客户,并将CC附加到客户,然后在未来再次获得CC编号时向该客户收费。 Parse's api does not handle adding a CC to a customer so I added the feature myself. Parse的api无法处理向客户添加CC,因此我自己添加了该功能。

So Step 1 and 2 Generate a Customer using Parse's API, and generate a Token from the CC information they enter again using Parse's API. 因此,步骤1和2使用Parse的API生成客户,并使用Parse的API再次从他们输入的CC信息生成令牌。 If you need help with this, and the cloud code required let me know. 如果您需要有关此方面的帮助,请告知我们所需的云代码。

Step 3 Add a CC to a customer. 步骤3向客户添加CC。 I'm using a custom Customer object, but the main thing you really need is the stripe customerId which is customer.identifier in my code, and tokenID from your CC which in my case is token.tokenId. 我正在使用自定义Customer对象,但您真正需要的主要是条形customerId,我的代码中是customer.identifier,CC中的tokenID,在我的例子中是token.tokenId。 The response back will be a JSON string with the card information, I turn this into a Dictionary, and then create a STPCard from the dictionary. 响应将是带有卡信息的JSON字符串,我将其转换为字典,然后从字典中创建STPCard。 Also I show how to remove a card from a customer. 此外,我还将展示如何从客户处取出卡片。

iOS Code: iOS代码:

    +(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",
                //STRIPE_SECRET_KEY will be your stripe secrect key obviously, this is different from the public key that you will use in your iOS/Android side.
                // STRIPE_API_BASE_URL = 'api.stripe.com/v1'
                url: "https://" + STRIPE_SECRET_KEY + ':@' + STRIPE_API_BASE_URL + "/customers/" + request.params.customerId + "/cards/" + request.params.cardId,
                success: function(httpResponse) {
                response.success(httpResponse.text);
                },
                error: function(httpResponse) {
                response.error('Request failed with response code ' + httpResponse.status);
                }
        });
});

iOS Code for applying a charge to a customer or token notice the required parameters in the dictionary are an amount in cents not dollars, a currency, and then either a customer or a tokenId. 用于向客户或令牌收取费用的iOS代码通知字典中所需的参数是以美分而非美元,货币,然后是客户或tokenId的金额。 Note a customer can have many credit cards, but one of them is the active credit card. 请注意,客户可以拥有多张信用卡,但其中一张是活动信用卡。 The active card is the card that will be charged when you charge a customer: 有效卡是在向客户收费时将收取的卡:

//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 a customer/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); 
            }
        }
    );
});

How are you storing their CC information to charge it at a later time? 你如何存储他们的CC信息以便以后收费? Before proceeding, you need to know if it is PCI compliant or not. 在继续之前,您需要知道它是否符合PCI标准。 At most, the only things you should be looking to store is the expiration date, last 4 digits, and an associated record object that Parse Stripe gives you that corresponds to that CC. 最多,您应该查看的唯一内容是到期日期,最后4位数,以及Parse Stripe为您提供的与该CC对应的关联记录对象。 Do not try to store the full CC. 不要试图存储完整的CC。

As to your other questions: 至于你的其他问题:

Generally you need to know a web language to do something like this. 通常,您需要知道一种Web语言才能执行此类操作。 Here is an example of a possible stack that I've seen in a situation like this: 以下是我在以下情况中看到的可能堆栈的示例:

iOS App -> sends request to Server (rails, python, php, etc) -> Will send request to 3rd party site iOS App - >向Server发送请求(rails,python,php等) - >将请求发送到第三方站点

3rd party site response -> Server -> iOS app. 第三方站点响应 - >服务器 - > iOS应用程序。

The point of the server is to intercept the call from the mobile App to Parse, and the response from Parse back to the mobile app. 服务器的要点是拦截从移动应用程序到Parse的呼叫,以及从Parse到移动应用程序的响应。 The reason for this is so you can have a "master" db of the transactions/states and can recover if the app is ever reinstalled on the user's phone. 这样做的原因是,您可以拥有交易/状态的“主”数据库,并且如果在用户的手机上重新安装该应用程序,则可以恢复。 It also will let you store an identifier that points to the user's CC on parse stripe (I'm assuming). 它还允许您在解析条带上存储指向用户CC的标识符(我假设)。

You should really understand GET/POST as they are becoming a very basic feature of any iOS app. 你应该真正理解GET / POST,因为它们正在成为任何iOS应用程序的一个非常基本的功能。 They are simply how you get/insert records from a server. 它们只是您从服务器获取/插入记录的方式。 Considering almost all of the popular apps have some kind of network connectivity embedded in them, it really is a core part of iOS programming IMO. 考虑到几乎所有流行的应用程序都嵌入了某种网络连接,它实际上是iOS编程IMO的核心部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM