【问题标题】:iOS Parse Stripe IntegrationiOS Parse Stripe 集成
【发布时间】:2014-07-23 00:56:04
【问题描述】:

我对编程很陌生,我创建了一个应用程序来向客户收费,并希望存储他们的 CC 信息并在以后收费。我一直在阅读所有教程和文档,但我无法理解如何将其集成到我的应用程序中。我是否需要了解其他技术技能,例如 Rest API、Curl、Ruby 等才能进行此设置?所有的指南和文档都指向这个方向。我真的不明白 GET/POST 的用途以及它如何适合 iOS Objective-C 编程。

任何有关如何设置的指导都将不胜感激。我已经坚持了一段时间了。

【问题讨论】:

标签: ios api parse-platform stripe-payments


【解决方案1】:

您如何存储他们的抄送信息以便日后收费?在继续之前,您需要知道它是否符合 PCI 标准。最多,您应该存储的唯一内容是到期日期、最后 4 位数字以及 Parse Stripe 为您提供的与该 CC 对应的关联记录对象。不要尝试存储完整的 CC。

关于您的其他问题:

通常,您需要了解一种网络语言才能执行此类操作。这是我在这种情况下看到的可能堆栈的示例:

iOS 应用程序 -> 向服务器发送请求(rails、python、php 等)-> 将向第 3 方站点发送请求

第三方站点响应 -> 服务器 -> iOS 应用程序。

服务器的重点是拦截移动应用程序对 Parse 的调用,并将 Parse 的响应返回给移动应用程序。这样做的原因是您可以拥有交易/状态的“主”数据库,并且可以在用户手机上重新安装应用程序时恢复。它还可以让您在解析条上存储一个指向用户 CC 的标识符(我假设)。

您应该真正了解 GET/POST,因为它们正在成为任何 iOS 应用程序的一个非常基本的功能。它们只是您从服务器获取/插入记录的方式。考虑到几乎所有流行的应用程序都嵌入了某种网络连接,它确实是 iOS 编程 IMO 的核心部分。

【讨论】:

    【解决方案2】:

    Parse 的条带 API 并不像它应该的那样完整。它本身不包含许多功能,但可以通过 HTTP 请求来完成。我必须学习一点 Javascript 和 HTTP 请求才能使许多功能正常工作。当然,您的第一直觉应该告诉您永远不要在任何设备上存储 CC 号码!每当您让用户输入 CC 号码时,立即获得一个令牌,然后您就需要使用它。

    幸运的是,条纹使您能够保存客户,并将 CC 附加到客户,然后在将来向该客户收费而无需再次获得 CC 号码。 Parse 的 api 不处理向客户添加 CC,所以我自己添加了该功能。

    所以步骤 1 和 2 使用 Parse 的 API 生成客户,并使用 Parse 的 API 从他们再次输入的 CC 信息生成 Token。如果您需要这方面的帮助,以及所需的云代码,请告诉我。

    第 3 步向客户添加抄送。我正在使用自定义客户对象,但您真正需要的主要是条纹 customerId,它是我的代码中的 customer.identifier,以及来自您的 CC 的 tokenID,在我的情况下是 token.tokenId。返回的响应将是带有卡片信息的 JSON 字符串,我将其转换为字典,然后从字典中创建一个 STPCard。我还展示了如何从客户那里移除卡片。

    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);
        }];
    }
    

    需要云代码:

    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 代码通知字典中所需的参数是以美分而不是美元为单位的金额、货币,然后是客户或令牌 ID。请注意,客户可以拥有多张信用卡,但其中一张是有效信用卡。有效卡是您向客户收费时将收取的卡:

    //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;
    }
    

    用于向客户/代币收费的云代码:

    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); 
                }
            }
        );
    });
    

    【讨论】:

    • 非常感谢您的支持。我没有在我的数据库或设备上存储任何 CC 我知道存在合规性问题。我要做的是学习 GET 和 POST……我可以学习什么语言?红宝石?我还需要学习 XML 或 Node 吗?不是很清楚那是什么。希望大家见识见识,见谅。我已经离开技术领域超过 10 年了,我已经自学了 objecticeC,我正在尝试将所有部分拼凑在一起!谢谢。
    • 我在同一条船上,自学了目标 c,并且必须深入研究其他语言,因为我正在尝试使用一些后端。 Parse 云代码是您可能已经研究过的 javascript。我喜欢 parse,因为它可以很容易地直接进入,而无需深入了解所有后端语言。就获取/发布而言,如果您愿意,您可以从目标 c 执行此操作。我正在使用解析云代码来执行我的 HTTP Post,因为我需要使用我的密钥。切勿在最终用户设备上使用您的密钥。通过解析服务器传递它是保证交易安全的原因。
    • 嗨,感谢您的反馈。所以你说的是云代码是javascript,它是云计算?它会执行代码并将结果返回给设备吗?我不知道任何 Javascript,所以这可能是我没有遵循您提供的云代码部分的原因。您是否建议我选择 JavaScript 的特定部分来在我的应用程序中实现它?你还知道我在 Stripe API 文档提供的 URL 链接中放了什么吗?这个网址是干什么用的?它应该指向一个条带 URL? initWithURL:[NSURL URLWithString:@"example.com"]
    • 为什么不使用Stripe.Customers.create/update/destroy/etc... 而不是HTTP 请求? parse.com/docs/js/symbols/Stripe.Customers.html
    • 我确实在使用 parse 的模块时使用它们。 parse 的 API 没有完成某些条带功能,这就是我使用 http 请求的目的。在此示例中,现在无法使用 parse 的模块向条带客户添加 cc。
    猜你喜欢
    • 1970-01-01
    • 2015-06-14
    • 2015-01-05
    • 2017-02-16
    • 2018-12-27
    • 1970-01-01
    • 1970-01-01
    • 2021-05-03
    • 1970-01-01
    相关资源
    最近更新 更多