2016-07-29 2 views
0

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

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

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

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

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

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

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

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

Который имеет смысл, потому что заряды не создаются на полоской, потому что ошибка происходит на этой линии, и очень следующая строка является 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); 
 
    } 
 
    }); 
 
});

+0

Возможно, стоит отметить, что код и сценарий для Apple Pay работают нормально. –

ответ

0

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

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

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

и соответствующий Javascript Анализировать Cloud Кодекс:

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

и соответствующий вызов в яваскрипта Разбор Облака кодекса:

return Stripe.Charges.create({ 

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

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

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

Ex: card: request.params.chargeToken (называемый в ChargeToken)

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

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

Смежные вопросы