Please please help if you know how to integrate these programs. I have spent 3 days trying to get around this problem. strong text
如果您知道如何整合这些程序,请帮助。我花了3天时间试图解决这个问题。强文
I am building an eCommerce platform into my app for accepting payment of Credit Cards and Apple Pay. There are two viewControllers included in this process, BagTableViewController and AddCreditCardViewController. There is also javascript for the Parse Cloud Code. I have included all code.
我正在我的应用程序中构建一个电子商务平台,用于接受信用卡和Apple Pay的支付。此过程中包含两个viewControllers,BagTableViewController和AddCreditCardViewController。还有用于Parse Cloud Code的javascript。我已经包含了所有代码。
My pods are all up-to-date and have reverted the Parse JavaScript SDK to version 1.5.0 because parse has not updated their libraries.
我的pod都是最新的,并已将Parse JavaScript SDK恢复为1.5.0版本,因为parse尚未更新其库。
My current issue occurs when I attempt to Authorize a Credit Card in the AddCreditCardViewController. After entering the test credit card information provided by Stripe, the user then presses the Authorize bar button.
当我尝试在AddCreditCardViewController中授权信用卡时,我遇到了当前的问题。输入Stripe提供的测试信用卡信息后,用户按下授权栏按钮。
When I press "Authorize", Stripe creates the Tokens and Customers, but it does not charge the customer. Instead, I receive this error in Xcode:
当我按下“授权”时,Stripe会创建令牌和客户,但它不会向客户收取费用。相反,我在Xcode中收到此错误:
[Bolts] Warning: BFTask
caught an exception in the continuation block. This behavior is discouraged and will be removed in a future release. Caught Exception: *** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[1]
[螺栓]警告:BFTask在延续块中捕获了异常。不鼓励这种行为,将来的版本中将删除此行为。捕获异常:*** - [__ NSPlaceholderDictionary initWithObjects:forKeys:count:]:尝试从对象[1]插入nil对象
In my attempts to debug this issue, I located this line as the point where a breakpoint initiates instead of the error.
在我尝试调试此问题时,我将此行定位为断点启动而不是错误的点。
NSDictionary *params = @{@"chargeCustomer":customerId, @"orderId":weakSelf.order.objectId};
Which makes sense because the charges are not being created on Stripe because the error happens on that line, and the very next line is the PFCloud callFuctionInBackround to charge the customer.
这是有道理的,因为没有在Stripe上创建费用,因为错误发生在该行上,而下一行是PFCloud callFuctionInBackround来为客户收费。
I can find very little information regarding this error, but I believe I am passing the wrong information into the NSDictionary for *params.
我可以找到关于此错误的非常少的信息,但我相信我将错误的信息传递给NSDictionary for * params。
Can anyone help me out here? I am totally lost
有人可以帮我从这里出去吗?我完全迷失了
// 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 customer.service@memoryjar.com ' + '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: 'chris.stahl12@gmail.com', //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);
}
});
});
1 个解决方案
#1
0
So, I finally figured this out. It was confusing but I was sending the wrong variables to the javascript from the AddCreditCard and Bag table view controllers.
所以,我终于弄明白了。这令人困惑,但我从AddCreditCard和Bag表视图控制器向javascript发送了错误的变量。
Inside the AddCreditCardViewController, we create the stripe customer for either an Apple Pay or Credit Card Transation. The dictionary is:
在AddCreditCardViewController中,我们为Apple Pay或Credit Card Transation创建条带客户。字典是:
NSDictionary *stripeCustomerDictionary = @{@"token":token.tokenId,
@"email":user.email
};
and the corresponding javascript Parse Cloud Code is:
和相应的javascript Parse Cloud Code是:
return Stripe.Customers.create({
description: 'customer for Memory Jar',
card: request.params.token,
email: request.params.email,
Then in BagTableViewController the dictionary for ChargeToken (Apple Pay) is:
然后在BagTableViewController中,ChargeToken(Apple Pay)的字典是:
NSDictionary *params = @{@"chargeToken":tokenId,
@"amount":[NSNumber numberWithDouble:(weakSelf.order.total*100)],
@"orderId":weakSelf.order.objectId
};
and the corresponding call for ChargeToken in the javascript Parse Cloud Code is:
并且javascript Parse Cloud Code中对ChargeToken的相应调用是:
return Stripe.Charges.create({
amount: request.params.amount, // express dollars in cents
currency: 'usd',
card: request.params.chargeToken
for ChargeCustomer (Credit Card) it is:
对于ChargeCustomer(信用卡),它是:
NSDictionary *params = @{
@"customerId":customerId,
@"amount":[NSNumber numberWithDouble:(weakSelf.order.total*100)],
@"orderId":weakSelf.order.objectId
};
and the corresponding call in the javascript Parse Cloud Code is:
并且javascript Parse Cloud Code中的相应调用是:
return Stripe.Charges.create({
customer: request.params.customerId,
currency: 'usd',
amount: request.params.amount // express dollars in cents
The error was being produced because I did not have the dictionary's aligned. I thought the first word in the javascript was the corresponding word in the Objective C code, but I was wrong.
错误正在产生,因为我没有字典对齐。我认为javascript中的第一个单词是Objective C代码中的相应单词,但我错了。
The last word is what javascript looks for in the ObjC code.
最后一个词是javascript在ObjC代码中查找的内容。
Ex: card: request.params.chargeToken
(called in ChargeToken)
例如:card:request.params.chargeToken(在ChargeToken中调用)
lines up with @"chargeToken":tokenId
in the NSDictionary. Javascript is asking you to provide the dictionary definition for the chargeToken which is then passed back as the tokenId.
与@“chargeToken”对齐:NSDictionary中的tokenId。 Javascript要求您提供chargeToken的字典定义,然后将其作为tokenId传回。
I hope this helps someone along the way. I lost about 8 days to this problem.
我希望这可以帮助一路上的人。我在这个问题上失去了大约8天。
#1
0
So, I finally figured this out. It was confusing but I was sending the wrong variables to the javascript from the AddCreditCard and Bag table view controllers.
所以,我终于弄明白了。这令人困惑,但我从AddCreditCard和Bag表视图控制器向javascript发送了错误的变量。
Inside the AddCreditCardViewController, we create the stripe customer for either an Apple Pay or Credit Card Transation. The dictionary is:
在AddCreditCardViewController中,我们为Apple Pay或Credit Card Transation创建条带客户。字典是:
NSDictionary *stripeCustomerDictionary = @{@"token":token.tokenId,
@"email":user.email
};
and the corresponding javascript Parse Cloud Code is:
和相应的javascript Parse Cloud Code是:
return Stripe.Customers.create({
description: 'customer for Memory Jar',
card: request.params.token,
email: request.params.email,
Then in BagTableViewController the dictionary for ChargeToken (Apple Pay) is:
然后在BagTableViewController中,ChargeToken(Apple Pay)的字典是:
NSDictionary *params = @{@"chargeToken":tokenId,
@"amount":[NSNumber numberWithDouble:(weakSelf.order.total*100)],
@"orderId":weakSelf.order.objectId
};
and the corresponding call for ChargeToken in the javascript Parse Cloud Code is:
并且javascript Parse Cloud Code中对ChargeToken的相应调用是:
return Stripe.Charges.create({
amount: request.params.amount, // express dollars in cents
currency: 'usd',
card: request.params.chargeToken
for ChargeCustomer (Credit Card) it is:
对于ChargeCustomer(信用卡),它是:
NSDictionary *params = @{
@"customerId":customerId,
@"amount":[NSNumber numberWithDouble:(weakSelf.order.total*100)],
@"orderId":weakSelf.order.objectId
};
and the corresponding call in the javascript Parse Cloud Code is:
并且javascript Parse Cloud Code中的相应调用是:
return Stripe.Charges.create({
customer: request.params.customerId,
currency: 'usd',
amount: request.params.amount // express dollars in cents
The error was being produced because I did not have the dictionary's aligned. I thought the first word in the javascript was the corresponding word in the Objective C code, but I was wrong.
错误正在产生,因为我没有字典对齐。我认为javascript中的第一个单词是Objective C代码中的相应单词,但我错了。
The last word is what javascript looks for in the ObjC code.
最后一个词是javascript在ObjC代码中查找的内容。
Ex: card: request.params.chargeToken
(called in ChargeToken)
例如:card:request.params.chargeToken(在ChargeToken中调用)
lines up with @"chargeToken":tokenId
in the NSDictionary. Javascript is asking you to provide the dictionary definition for the chargeToken which is then passed back as the tokenId.
与@“chargeToken”对齐:NSDictionary中的tokenId。 Javascript要求您提供chargeToken的字典定义,然后将其作为tokenId传回。
I hope this helps someone along the way. I lost about 8 days to this problem.
我希望这可以帮助一路上的人。我在这个问题上失去了大约8天。