I've been trying and trying all day to get in-app payment support with Square setup. If this looks familiar, I initially was using Stripe, only to realize Square is what the client needed done. So, here's what I've done so far. I've created my application in Square Dashboard, set its production to Sandbox. On my AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[Parse initializeWithConfiguration:[ParseClientConfiguration configurationWithBlock:^(id<ParseMutableClientConfiguration> configuration) {
configuration.applicationId = @"gbLxB2ABsxRviFHMz0jdnCvqal6aNfImyJiTCI1U";
configuration.clientKey = @"s8p1mIwbFr17PEn1K6ZGuT4ee9nvrdjQdcp7BmTD";
configuration.server = @"https://parseapi.back4app.com";
}]];
[SQIPInAppPaymentsSDK setSquareApplicationID:@"sandbox-random letters"];
return YES;
}
On my ViewController where I want to make the payment:
- (void)showCardEntryForm {
SQIPTheme *theme = [[SQIPTheme alloc] init];
// Customize the card entry form theme if needed
SQIPCardEntryViewController *cardEntryForm =
[[SQIPCardEntryViewController alloc] initWithTheme:theme];
cardEntryForm.delegate = self;
UINavigationController *navigationController =
[[UINavigationController alloc] initWithRootViewController:cardEntryForm];
[self presentViewController:navigationController animated:YES completion:nil];
}
- (void)cardEntryViewController:(SQIPCardEntryViewController *)cardEntryViewController
didObtainCardDetails:(SQIPCardDetails *)cardDetails
completionHandler:(void (^)(NSError * _Nullable))completionHandler {
// Retrieve the nonce from cardDetails object
NSString *nonce = cardDetails.nonce;
// Pass the nonce to your server-side code for payment processing
[self processPaymentWithNonce:nonce];
// Call the completion handler
completionHandler(nil);
}
- (void)cardEntryViewController:(nonnull SQIPCardEntryViewController *)cardEntryViewController
didCompleteWithStatus:(SQIPCardEntryCompletionStatus)status;
{
// Note: If you pushed the card entry form onto an existing navigation controller,
// use [self.navigationController popViewControllerAnimated:YES] instead
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)processPaymentWithNonce:(NSString *)nonce {
[PFCloud callFunctionInBackground:@"processSquarePayment"
withParameters:@{@"nonce": nonce, @"amount": @(50)} // Pass the amount parameter
block:^(id result, NSError *error) {
if (error) {
NSLog(@"Error processing payment: %@", error.localizedDescription);
// Handle error
} else {
NSLog(@"Payment processed successfully! Result: %@", result);
// Handle success
}
}];
}
On my Back4App.com CloudCode (and yes, I have square added to dependencies and confirmed the module is installed there).
// Import necessary modules from the square package
const { Client, Environment, ApiError } = require('square');
// Define your Cloud Code function to process Square payments
Parse.Cloud.define("processSquarePayment", async (request) => {
// Retrieve nonce and amount from client request
const { nonce, amount } = request.params;
try {
// Configure Square client
const squareClient = new Client({
environment: Environment.Sandbox, // Change to Sandbox for testing
accessToken: 'MY_ACCESS_TOKEN', // Replace with your Square access token
});
// Create a payment request
const requestBody = {
sourceId: nonce, // Payment nonce received from client
amountMoney: {
amount: amount * 100, // Amount in cents
currency: 'USD', // Change as needed
},
idempotencyKey: Math.random().toString(36).substring(7), // Random idempotency key
};
// Process payment
const response = await squareClient.paymentsApi.createPayment(requestBody);
// Payment successful
return { success: true, paymentDetails: response.result };
} catch (error) {
// Handle errors
console.error('Error processing Square payment:', error);
if (error instanceof ApiError) {
console.error('Square API Error:', error.errors);
return { success: false, error: error.errors };
} else {
console.error('Unexpected Error:', error.message);
return { success: false, error: error.message };
}
}
});
I use the test card and get this error in Xcode console:
[Error]: {"code":1,"message":"Internal server error."} (Code: 1, Version: 1.19.4)
Error processing payment: {"code":1,"message":"Internal server error."}
I go to back4app console and it says this:
2024-02-06T20:04:15.292Z - Uncaught internal server error. Do not know how to serialize a BigInt
I also get:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:558:11)
at ServerResponse.header (/usr/src/app/node_modules/express/lib/response.js:771:10)
at ServerResponse.send (/usr/src/app/node_modules/express/lib/response.js:170:12)
at ServerResponse.json (/usr/src/app/node_modules/express/lib/response.js:267:15)
at /usr/src/app/src/back/app.js:279:9
at Layer.handle_error (/usr/src/app/node_modules/express/lib/router/layer.js:71:5)
at trim_prefix (/usr/src/app/node_modules/express/lib/router/index.js:315:13)
at /usr/src/app/node_modules/express/lib/router/index.js:284:7
at Function.process_params (/usr/src/app/node_modules/express/lib/router/index.js:335:12)
at next (/usr/src/app/node_modules/express/lib/router/index.js:275:10)
I'm at a loss quite honestly.