Интеграция с полосой iOS eCommerce Анализ с использованием JavaScript-кода JavaScript

0 Chris Stahl [2016-07-29 17:22:00]

Пожалуйста, помогите, если вы знаете, как интегрировать эти программы. Я потратил 3 дня, пытаясь обойти эту проблему. сильный текст

Я создаю платформу электронной коммерции в своем приложении для принятия платежей по кредитным картам и Apple Pay. В этот процесс включены два контроллера viewControllers: BagTableViewController и AddCreditCardViewController. Также есть JavaScript для кода Parse Cloud. Я включил весь код.

Мои стручки обновлены и вернули Parse JavaScript SDK до версии 1.5.0, потому что синтаксический анализ не обновил свои библиотеки.

Моя текущая проблема возникает, когда я пытаюсь авторизовать кредитную карту в AddCreditCardViewController. После ввода тестовой информации кредитной карты, предоставленной Stripe, пользователь затем нажимает кнопку Авторизация.

Когда я нажимаю "Авторизовать", Stripe создает токены и клиенты, но не взимает плату с клиента. Вместо этого я получаю эту ошибку в Xcode:

[Болты] Предупреждение: BFTask обнаружил исключение в блоке продолжения. Такое поведение не рекомендуется и будет удалено в будущем выпуске. Caught Exception: *** - [__ NSPlaceholderDictionary initWithObjects: forKeys: count:]: попытка вставить нулевой объект из объектов [1]

В моих попытках отладить эту проблему я нашел эту строку как точку, где вместо точки ошибки инициируется точка останова.

NSDictionary *params = @{@"chargeCustomer":customerId, @"orderId":weakSelf.order.objectId};

Это имеет смысл, потому что плата не создается на Stripe, потому что ошибка происходит на этой линии, а следующая строка - это PFCloud callFuctionInBackround, чтобы зарядить клиента.

Я могу найти очень мало информации об этой ошибке, но я считаю, что передаю неверную информацию в NSDictionary для * params.

Может кто-нибудь помочь мне здесь? Я полностью потерял

//  BagTableViewController.h
//  Created by Chris Stahl on 6/28/16.
//  Copyright © 2016 Memory Jar. All rights reserved.

#import <UIKit/UIKit.h>
@interface BagTableViewController : UITableViewController
@end   

//  BagTableViewController.m
//  Created by Chris Stahl on 6/28/16.
//  Copyright © 2016 Memory Jar. All rights reserved.

    #import "BagTableViewController.h"
    #import "OrderItemTableViewCell.h"
    #import "Constants.h"
    #import "User.h"
    #import "Order.h"
    #import "OrderItem.h"
    #import "Product.h"
    #import "UserProfileTableViewController.h"
    #import "UserPaymentMethodTableViewController.h"
    #import "PaymentMethod.h"
    #import "AddCreditCardViewController.h"
    #import "SVProgressHUD/SVProgressHUD.h"
    #import "PassKit/PassKit.h"

    @interface BagTableViewController () <PKPaymentAuthorizationViewControllerDelegate>
    @property (nonatomic, weak) IBOutlet UILabel *orderNoLabel;
    @property (nonatomic, weak) IBOutlet UILabel *orderDateLabel;
    @property (nonatomic, weak) IBOutlet UILabel *totalLabel;
    @property (nonatomic, weak) IBOutlet UILabel *totalTextLabel;

    @property (nonatomic, weak) IBOutlet UIButton *payWithCCButton;
    @property (nonatomic, weak) IBOutlet UIButton *payWithApplePayButton;
    @property (nonatomic, strong) Order *order;
    @property (nonatomic, weak) NSArray *creditCards;
    @property (nonatomic) NSDecimalNumber *amount;
    @property (nonatomic, strong) PKPaymentRequest *paymentRequest;
    @end

    @implementation BagTableViewController

    -(void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
        if ([User currentUser]) {
            [self queryForUnfinishedOrder];
        }
    }

    - (void)viewDidLoad {
        [self.refreshControl addTarget:self action:@selector(queryForUnfinishedOrder) forControlEvents:UIControlEventValueChanged];
    }

    -(void)viewWillDisappear:(BOOL)animated {
        if (self.order && self.order.isDirty) {
            [self.order saveInBackground];
        }
    }

    -(IBAction)queryForUnfinishedOrder {
        self.order = nil; //to get ride of the cache
        PFQuery *orderQuery = [Order queryForCustomer:[User currentUser] orderStatus:ORDER_NOT_MADE];
        __weak typeof(self) weakSelf = self;
        [orderQuery getFirstObjectInBackgroundWithBlock:^(PFObject *order, NSError *error){
            if ([weakSelf.refreshControl isRefreshing]) {
                [weakSelf.refreshControl endRefreshing];
            }
            if (!error) {
                if (order) {
                    weakSelf.order = (Order *)order;
                    weakSelf.orderNoLabel.text = @"";
                    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
                    [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
                    [dateFormatter setTimeStyle:NSDateFormatterShortStyle];
                    weakSelf.orderDateLabel.text = [dateFormatter stringFromDate:[NSDate date]];
                    weakSelf.totalLabel.text = [self.order friendlyTotal];
                    [weakSelf updateUI];
                } else {
                    [weakSelf updateUI];
                }

            } else {
                [weakSelf updateUI];
            }
        }];
    }

    -(void)updateUI {
        BOOL shouldClear = self.order == nil;
        if (shouldClear) {
            self.orderNoLabel.text = NSLocalizedString(@"Your bag is empty.", @"");
            self.orderDateLabel.text = @"";
            self.totalLabel.text = @"";
            self.totalTextLabel.text = @"";
            self.payWithApplePayButton.hidden = YES;
            self.payWithCCButton.hidden = YES;
            self.payWithApplePayButton.enabled = NO;
            self.payWithCCButton.enabled = NO;
        } else {
            self.totalTextLabel.text = NSLocalizedString(@"Total: ", @"");
            self.payWithApplePayButton.hidden = NO;
            self.payWithCCButton.hidden = NO;
            self.payWithApplePayButton.enabled = YES;
            self.payWithCCButton.enabled = YES;
        }
        [self.tableView reloadData];
    }

    #pragma Mark --- APPLE PAY PROCESS
    -(IBAction)onApplePay:(id)sender{
        NSString *merchantId = kAppleMerchatID;
        self.paymentRequest = [Stripe paymentRequestWithMerchantIdentifier:merchantId];
        if ([Stripe canSubmitPaymentRequest:self.paymentRequest]) {
            [self.paymentRequest setRequiredShippingAddressFields:PKAddressFieldPostalAddress];
            [self.paymentRequest setRequiredBillingAddressFields:PKAddressFieldPostalAddress];
            self.paymentRequest.paymentSummaryItems = [self summaryItemsForShippingMethod:nil];
            PKPaymentAuthorizationViewController *auth = [[PKPaymentAuthorizationViewController alloc] initWithPaymentRequest:self.paymentRequest];
            auth.delegate = self;
            if (auth) {
                [self presentViewController:auth animated:YES completion:nil];
            } else
                [SVProgressHUD showErrorWithStatus:NSLocalizedString(@"Something Wrong", @"Something Wrong")];
        } else {
            [SVProgressHUD showErrorWithStatus:NSLocalizedString(@"Apple Pay is not enabled. Please enable your Apple Pay or Pay with Credit Card.", @"")];
        }
    }
    -(void)paymentAuthorizationViewController:(nonnull PKPaymentAuthorizationViewController *) controller didAuthorizePayment:(nonnull PKPayment *)payment completion:(nonnull void (^)(PKPaymentAuthorizationStatus))completion{
        [self handlePaymentAuthorizationWithPayment:payment completion:nil];
    }
    -(void)paymentAuthorizationViewControllerDidFinish:(nonnull PKPaymentAuthorizationViewController *)controller {
        [self dismissViewControllerAnimated:YES completion:nil];
        [self queryForUnfinishedOrder];
    }
    - (void)handlePaymentAuthorizationWithPayment:(PKPayment *)payment completion:(void (^)(PKPaymentAuthorizationStatus))completion {
        [[STPAPIClient sharedClient] createTokenWithPayment:payment
                                                 completion:^(STPToken *token, NSError *error) {
                                                     if (error) {
                                                         completion(PKPaymentAuthorizationStatusFailure);
                                                         return;
                                                     }
                                                     [self createBackendChargeWithToken:token completion:completion];
                                                 }];
    }
    - (void)createBackendChargeWithToken:(STPToken *)token completion:(void (^)(PKPaymentAuthorizationStatus))completion {
        [self chargeWithToken:token.tokenId];
    }
    -(void)chargeWithToken:(NSString *)tokenId {
        [self.order saveInBackgroundWithBlock:^(BOOL success, NSError *error){
            if (!error) {
                __weak typeof(self) weakSelf = self;
                NSDictionary *params = @{@"chargeToken":tokenId, @"orderId":weakSelf.order.objectId};
                [PFCloud callFunctionInBackground:@"chargeToken" withParameters:params block:^(NSString *message, NSError *error){
                    if (!error) {
                        [weakSelf queryForUnfinishedOrder];

                    }
                }];
            }
        }];

    }

    #pragma mark - Credit Card Process
    -(IBAction)onPayWithCreditCard:(id)sender{
        if ([[User currentUser] isShippingAddressCompleted]) {
            [self inputCreditCard];
        } else {
            UserProfileTableViewController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:@"UserProfileTableViewController"];
            [self.navigationController pushViewController:viewController animated:YES];
        }
    }

    - (void)inputCreditCard {
        AddCreditCardViewController *addCreditCardViewController = (AddCreditCardViewController *)[self.storyboard instantiateViewControllerWithIdentifier:@"AddCreditCardViewController"];
            __weak typeof(self) weakSelf = self;
            addCreditCardViewController.finishBlock = ^(NSString *customerId){
                [weakSelf charge:customerId];
            };
        [self.navigationController pushViewController:addCreditCardViewController animated:YES];
        }

    -(void)charge:(NSString *)customerId {
        [self.order saveInBackgroundWithBlock:^(BOOL success, NSError *error){
            if (!error) {
                __weak typeof(self) weakSelf = self;
                NSDictionary *params = @{@"chargeCustomer":customerId, @"orderId":weakSelf.order.objectId};
                [PFCloud callFunctionInBackground:@"chargeCustomer" withParameters:params block:^(NSString *message, NSError *error){
                    if (!error) {
                        [weakSelf queryForUnfinishedOrder];
                    }
                }];
            }
        }];
    }

    - (NSArray *)summaryItemsForShippingMethod:(PKShippingMethod *)shippingMethod {
        NSMutableArray *purchasedItems = [NSMutableArray arrayWithCapacity:[self.order.items count]];
        for (OrderItem *item in self.order.items) {
            double total = item.quantity * item.product.unitPrice;
            NSDecimalNumber *price = [NSDecimalNumber decimalNumberWithMantissa:total exponent:-2 isNegative:NO];
            PKPaymentSummaryItem *purchasedItem = [PKPaymentSummaryItem summaryItemWithLabel:item.product.name amount:price];
            [purchasedItems addObject:purchasedItem];
        }
        return [NSArray arrayWithArray:purchasedItems];
    }


    -(IBAction)onStepper:(id)sender {
        UIStepper *stepper = (UIStepper *)sender;
        NSInteger index = stepper.tag - 100;
        NSMutableArray *orderItems = [NSMutableArray arrayWithArray:self.order.items];
        OrderItem *orderItem = orderItems[index];
        orderItem.quantity = (int)stepper.value;
        if ((int)stepper.value == 0) {
            [orderItems removeObjectAtIndex:index];
        } else {
            [orderItems replaceObjectAtIndex:index withObject:orderItem];
        }
        if ([orderItems count] == 0) {
            [self showDeleteAlert];
        } else {
            self.order.items = [orderItems copy];
            [self.tableView reloadData];
            self.totalLabel.text = [self.order friendlyTotal];
        }
    }

    #pragma mark - Table view data source
    -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 80.0;
    }
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
    }
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.order.items count];
    }

    - (OrderItemTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        OrderItemTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BagItemCell" forIndexPath:indexPath];
        if (self.order) [cell configureItem:self.order.items[indexPath.row] tag:indexPath.row];
        else [cell configureItem:nil tag:100+indexPath.row];
        return cell;
    }

    -(void)showDeleteAlert {
        UIAlertController* alert = [UIAlertController alertControllerWithTitle:NSLocalizedString
                                    (@"Empty Bag",@"")
                                                                       message:NSLocalizedString(@"Are you sure you want to empty your bag?",@"")
                                                                preferredStyle:UIAlertControllerStyleAlert];
        __weak typeof(self) weakSelf = self;
        UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:NSLocalizedString
                                        (@"Yes",@"") style:UIAlertActionStyleDefault
                                                              handler:^(UIAlertAction * action) {
                                                                  [weakSelf.order deleteInBackgroundWithBlock:^(BOOL success, NSError *error){
                                                                      if (!error) {
                                                                          [weakSelf queryForUnfinishedOrder];
                                                                      } }];
                                                              }];
        UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString
                                       (@"cancel",@"") style:UIAlertActionStyleCancel
                                                             handler:^(UIAlertAction * action) {}];
        [alert addAction:defaultAction];
        [alert addAction:cancelAction];
        [self presentViewController:alert animated:YES completion:nil];
    }
    @end

//  AddCreditCardViewController.h
//  Created by Chris Stahl on 6/28/16.
//  Copyright © 2016 Memory Jar. All rights reserved.

#import <UIKit/UIKit.h>
@class AddCreditCardViewController;
typedef void (^AddCreditCardViewControllerDidFinish)(NSString *customerId);
@interface AddCreditCardViewController : UIViewController
@property (nonatomic, copy) AddCreditCardViewControllerDidFinish finishBlock;
@end

//  AddCreditCardViewController.m
//  Created by Chris Stahl on 6/28/16.
//  Copyright © 2016 Memory Jar. All rights reserved.

#import "AddCreditCardViewController.h"
#import "Stripe/Stripe.h"
#import "User.h"
#import "PaymentMethod.h"

@interface AddCreditCardViewController ()<STPPaymentCardTextFieldDelegate>
@property (nonatomic, weak) IBOutlet STPPaymentCardTextField *paymentView;
@property (weak, nonatomic) UIActivityIndicatorView *activityIndicator;
@end

@implementation AddCreditCardViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(onCancel:)];
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Authorize", @"") style:UIBarButtonItemStylePlain target:self action:@selector(onAuthorize:)];

    UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    activityIndicator.hidesWhenStopped = YES;
    self.activityIndicator = activityIndicator;
    [self.view addSubview:activityIndicator];
}
- (void)paymentView:(STPPaymentCardTextField *)paymentView withCard:(STPPaymentCardTextField *)card isValid:(BOOL)valid {
    self.navigationItem.rightBarButtonItem.enabled = valid;
}
- (void)paymentCardTextFieldDidChange:(STPPaymentCardTextField *)textField {
    self.navigationItem.rightBarButtonItem.enabled = textField.isValid;
}
- (void)onCancel:(id)sender {
    [self.navigationController popViewControllerAnimated:YES];
}


#pragma mark - Authorize the payment (get paid)

- (void)onAuthorize:(id)sender {
    if (![self.paymentView isValid]) {
        return;
    }

    STPCardParams *card = [[STPCardParams alloc] init];
        card.number = self.paymentView.cardParams.number;
        card.expMonth = self.paymentView.cardParams.expMonth;
        card.expYear = self.paymentView.cardParams.expYear;
        card.cvc = self.paymentView.cardParams.cvc;

    __weak typeof(self) weakSelf = self;

    [[STPAPIClient sharedClient] createTokenWithCard:card
                                          completion:^(STPToken *token, NSError *error) {
                                              if (error) {
                                              } else {
                                                  User *user = [User currentUser];
                                                  NSDictionary *stripeCustomerDictionary = @{@"tokenId":token.tokenId, @"customerEmail":user.email};


      [PFCloud callFunctionInBackground:@"createStripeCustomer" withParameters:stripeCustomerDictionary block:^(NSString *customerId, NSError *error) {

          if (!error) {
            PaymentMethod *creditCard = [PaymentMethod object];
              creditCard.owner  = user;
              creditCard.stripeCustomerId = customerId;
              creditCard.expirationMonth = card.expMonth;
              creditCard.expirationYear = card.expYear;
              creditCard.type = [creditCard friendlyType:(STPCardBrand)creditCard];
              creditCard.lastFourDigit = card.last4;
              creditCard.stripeCustomerId = customerId;

              [creditCard saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
                  if (!error) {
                    [weakSelf readyToCharge:customerId];
                }
            }];

          } else {

          }
      }];
            }
    }];
}

-(void)readyToCharge:(NSString *)customerId {
    self.finishBlock(customerId);
    [self.navigationController popViewControllerAnimated:YES];
}
@end

Parse.Cloud.define("sendNotification", function(request, response) {
  var query = new Parse.Query(Parse.Installation);
  var userObj = new Parse.User({
    id: request.params.userId
  });
  query.equalTo("user", userObj);
  Parse.Push.send({
    where: query,
    data: {
      alert: request.params.message
    }
  }, {
    success: function() {
      response.success(0);
    },
    error: function(error) {
      response.error('push notification error');
    }
  });
});


var Stripe = require('stripe');
Stripe.initialize('sk_test_xxx');

var STRIPE_API_BASE_URL = 'api.stripe.com/v1';
Stripe.initialize('sk_test_xxx');

var Mailgun = require('mailgun');
Mailgun.initialize("Memory_Jar", "pubkey-xxx");



//Create a stripe customer
Parse.Cloud.define("createStripeCustomer", function(request, response) {
  Parse.Cloud.useMasterKey();
  Parse.Promise.as().then(function() {
    return Stripe.Customers.create({
      description: 'customer for Memory Jar',
      card: request.params.tokenId,
      email: request.params.customerEmail,

    }).then(null, function(error) {
      console.log('Creating customer with stripe failed. Error: ' + error);
      return Parse.Promise.error('An error has occurred.');
    });

  }).then(function(customer) {
    response.success(customer.id);

  }, function(error) {
    response.error('error with customer creation');
  });
});



//Charge the customer
Parse.Cloud.define("chargeCustomer", function(request, response) {
  Parse.Cloud.useMasterKey();
  var order;
  var orderNo;
  var total;

  Parse.Promise.as().then(function() {
    var orderQuery = new Parse.Query('Order');
    orderQuery.equalTo('objectId', request.params.orderId);
    orderQuery.include("customer");
    orderQuery.include(["items.product"]);
    orderQuery.descending("createdAt");

    return orderQuery.first().then(null, function(error) {
      return Parse.Promise.error('Sorry, this order doesn\'t exist.');
    });

  }).then(function(result) {
    order = result;

    var items = order.get("items");
    for (var i = 0; i < items.length; i++) {
      var item = items[i];
      var unitPrice = item.get("product").get("unitPrice");
      var quantity = item.get("quantity");
      total += unitPrice * quantity;
    }

  }).then(function(result) {
    var countQuery = new Parse.Query("Order");
    return countQuery.count().then(null, function(error) {
      return Parse.Promise.error('Something wrong.');
    });

  }).then(function(result) {
    orderNo = result;

  }).then(function(order) {
    return Stripe.Charges.create({
      amount: 10000, //total.toFixed(2)*100, // express dollars in cents
      currency: 'usd',
      customer: request.params.customerId


    }).then(null, function(error) {
      console.log('Charging with stripe failed. Error: ' + error);
      return Parse.Promise.error('An error has occurred. Your credit card was not charged.');
    });

  }).then(function(purchase) {
    orderNo = 1000000 + orderNo + 1;

    order.set('stripePaymentId', purchase.id);
    order.set('orderStatus', 1);
    order.set('orderNo', orderNo);
    return order.save().then(null, function(error) {
      return Parse.Promise.error('A critical error has occurred with your order. Please ' + 'contact us at your earliest convinience. ');
    });

  }).then(function(order) {
    var greeting = "Dear ";
    //                        if (request.params.firstName !== "N/A") greeting += request.params.firstName + ",\n\n";
    //                        var orderId = "Order No. " + orderNo + "\n";
    var body = greeting + orderId + "We have received your order for the following item(s): \n\n" + request.params.itemDesc + "\n";
    var note = "Note: " + request.params.note + "\n\n";
    body += "\Total: $" + 1000 + "\n\n"; //total.toFixed(2)
    var thankyou = "Contact us if you have any question!\n\n" + "\n Thank you,\n";
    body += thankyou;

    return Mailgun.sendEmail({
      to: request.params.email,
      bcc: 'CUSTOMER-EMAIL',
      from: 'YOUR-EMAIL',
      subject: '',
      text: body

    }).then(null, function(error) {
      return Parse.Promise.error('Your purchase was successful, but we were not able to ' + 'send you an email. Contact us at [email protected] ' + 'you have any questions.');
    });

  }).then(function(charge) {
      response.success(charge.id);
    },
    function(error) {
      response.error(error);
    });
});


//Create Stripe token for charged customer
Parse.Cloud.define("chargeToken", function(request, response) {
  Parse.Cloud.useMasterKey();
  var order;
  var orderNo;
  var total;

  Parse.Promise.as().then(function() {
    var orderQuery = new Parse.Query('Order');
    orderQuery.equalTo('objectId', request.params.orderId);
    orderQuery.include("customer");
    orderQuery.include(["items.product"]);
    orderQuery.descending("createdAt");
    return orderQuery.first().then(null, function(error) {
      return Parse.Promise.error('Sorry, this order doesn\'t exist.');
    });
  }).then(function(result) {
    order = result;
    var items = order.get("items");
    for (var i = 0; i < items.length; i++) {
      var item = items[i];
      var unitPrice = item.get("product").get("unitPrice");
      var quantity = item.get("quantity");
      total += unitPrice * quantity;
    }

  }).then(function(result) {
    var countQuery = new Parse.Query("Order");
    return countQuery.count().then(null, function(error) {
      return Parse.Promise.error('Something wrong.');
    });

  }).then(function(result) {
    orderNo = result;

  }).then(function(order) {
    return Stripe.Charges.create({
      amount: 10000, //amount: total.toFixed(2)*100, // express dollars in cents
      currency: 'usd',
      card: request.params.chargeToken,


    }).then(null, function(error) {
      console.log('Charging with stripe failed. Error: ' + error);
      return Parse.Promise.error('An error has occurred. Your credit card was not charged.');
    });

  }).then(function(purchase) {
    orderNo = 1000000 + orderNo + 1;
    order.set('orderStatus', 1); // order made
    order.set('orderNo', orderNo);
    order.set('stripePaymentId', purchase.id);
    return order.save().then(null, function(error) {
      return Parse.Promise.error('A critical error has occurred with your order. Please ' + 'contact us at your earliest convinience. ');
    });

  }).then(function(result) {
    var greeting = "Dear ";
    //                            if (order.customer.firstName !== "N/A") greeting +=
    //                            order.customer.firstName + ",\n\n";
    var orderId = "Order No. " + orderNo + "\n";
    var body = greeting + orderId + " We have received your order for the following item(s): \n\n" + request.params.itemDesc + "\n";
    body += "\Total: $" + 1000 + "\n\n";
    var thankyou = "Contact us if you have any question!\n\n" + "\n Thank you,\n";
    body += thankyou;

    return Mailgun.sendEmail({
      to: '[email protected]', //order.customer.email,
      from: 'YOUR-CONTACT-EMAIL',
      subject: 'Your order was successful!',
      text: body

    }).then(null, function(error) {
      return Parse.Promise.error('Your purchase was successful, but we were not able to ' + 'send you an email. Contact us if you have any questions.');
    });

  }).then(function() {
    response.success('Success');
  }, function(error) {
    response.error(error);
  });
});


Parse.Cloud.define("StripeUserCards", function(request, response) {
  Parse.Cloud.httpRequest({
    method: "GET",
    url: "https://" + 'sk_test_bSJVNSp6BUre8e6wOzxhHYgQ' + ':@' + STRIPE_API_BASE_URL + "/customers/" + request.params.customer_id + "/cards",
    success: function(cards) {
      response.success(cards["data"]);
    },
    error: function(httpResponse) {
      response.error('Request failed with response code ' + httpResponse.status);
    }
  });
});

javascript ios objective-c stripe-payments parse.com


1 ответ


0 Решение Chris Stahl [2016-08-08 19:36:00]

Итак, я, наконец, понял это. Это было запутанно, но я отправлял неправильные переменные в javascript из контроллеров представления таблиц AddCreditCard и Bag.

Внутри AddCreditCardViewController мы создаем клиента полосы для транзакции Apple Pay или Credit Card. Словарь:

NSDictionary *stripeCustomerDictionary = @{@"token":token.tokenId,
                                           @"email":user.email 
};

и соответствующий javascript Parse Cloud Code:

return Stripe.Customers.create({

                            description: 'customer for Memory Jar',
                            card: request.params.token,
                            email: request.params.email,

Затем в BagTableViewController словарь для ChargeToken (Apple Pay):

NSDictionary *params = @{@"chargeToken":tokenId,
                       @"amount":[NSNumber numberWithDouble:(weakSelf.order.total*100)],
                           @"orderId":weakSelf.order.objectId 
};

и соответствующий вызов для ChargeToken в javascript Parse Cloud Code:

return Stripe.Charges.create({
                             amount: request.params.amount,  // express dollars in cents
                             currency: 'usd',
                             card: request.params.chargeToken

для ChargeCustomer (Кредитная карта):

NSDictionary *params = @{
                       @"customerId":customerId,
                       @"amount":[NSNumber numberWithDouble:(weakSelf.order.total*100)],
                       @"orderId":weakSelf.order.objectId
};

и соответствующий вызов в javascript Parse Cloud Code:

return Stripe.Charges.create({

                        customer: request.params.customerId,
                        currency: 'usd',
                        amount: request.params.amount  // express dollars in cents

Ошибка создавалась, потому что у меня не было выровненного словаря. Я думал, что первое слово в javascript было соответствующим словом в коде Objective C, но я был неправ.

Последнее слово - это то, что ищет javascript в коде ObjC.

Пример: card: request.params.chargeToken (называется ChargeToken)

выравнивается с помощью @"chargeToken":tokenId в NSDictionary. Javascript просит вас предоставить определение словаря для chargeToken, которое затем передается обратно как tokenId.

Надеюсь, это поможет кому-то на этом пути. Я потерял около 8 дней для этой проблемы.