How can I invoke an error in my Stripe.card.createToken function? - ajax

I'm using stripe in React and processing the charge through an AJAX call.
I've tried to strip down the Stripe.card.createToken function to the bare essentials for this question.
The if else statement checks if the response has any errors.
I use the 4100000000000019 card number to ensure a card declined error but the else statement(the successful charge) fires regardless which card number is entered.
Entering the 4100000000000019 card number results in a blocked charge in the Stripe dashboard. An error definitely gets generated:
{
"error": {
"message": "Your card was declined.",
"type": "card_error",
"code": "card_declined",
"decline_code": "generic_decline",
"charge": "ch_19gMBaIWHxnqld7LCdbCtdNz"
}
}
But the if(response.error) is ignored and runs the else statement.
Stripe.card.createToken({
number: $('.card-number').val(),
cvc: $('.card-cvc').val(),
exp_month: $('.card-expiry-month').val(),
exp_year: $('.card-expiry-year').val(),
name: $('.first-name').val()
}, function(status, response){
if (response.error) {
this.reportError(response.error.message);
} else { // No errors, submit the form.
var token = response.id;
$.ajax({
type: 'POST',
url: 'components/charge.php',
data : {
stripeToken: token
},
success: function(data,response) {
paymentSuccessful();
},
error: function(data,textStatus) {
console.log("Ajax Error!");
}
});//$.ajax
}//else
});//Stripe.card.createToken
Any help is much appreciated.
Moe
UPDATE: Thanks to this awesome tutorial by Larry Ullman and it's section on stripe error handling, I came up with a fairly good solution.
http://www.larryullman.com/2013/01/30/handling-stripe-errors/
So I added the if else statment inside the AJAX success function.
success: function(data,response) {
if(data == "success"){
$('#payment-error-copy').text("Your payment was successful. Thank you for ordering!");
paymentSuccessful();
} else {
$('#payment-error-copy').text(data);
}
};//success function
Inside the charge we can return the error response and the precise reason for the error.
my charge.php file
<?php
require_once('vendor/autoload.php');
// Get the payment token submitted by the form:
$token = $_POST['stripeToken'];
try{
\Stripe\Stripe::setApiKey("<secret_KEY>");
$customer = \Stripe\Customer::create(array(
"source" => $token,
"email" => $email
)
);
// Charge the Customer instead of the card
\Stripe\Charge::create(array(
"amount" => $price, // amount in cents, again
"currency" => "aud",
"description" => $email." ".$first_name,
"customer" => $customer->id
)
);
echo "success";
} catch (\Stripe\Error\ApiConnection $e) {
// Network problem, perhaps try again.
$e_json = $e->getJsonBody();
$error = $e_json['error'];
echo "Sorry, your charge couldn't be processed. Reason: ".$error['message'];
} catch (\Stripe\Error\InvalidRequest $e) {
// You screwed up in your programming. Shouldn't happen!
$e_json = $e->getJsonBody();
$error = $e_json['error'];
echo "Sorry, your charge couldn't be processed. Reason: ".$error['message'];
} catch (\Stripe\Error\Api $e) {
// Stripe's servers are down!
$e_json = $e->getJsonBody();
$error = $e_json['error'];
echo "Sorry, your charge couldn't be processed. Reason: ".$error['message'];
} catch (\Stripe\Error\Card $e) {
// Card was declined.
$e_json = $e->getJsonBody();
$error = $e_json['error'];
echo "Sorry, your charge couldn't be processed. Reason: ".$error['message'];
}
?>
The try catch statement returns a precise message about the charge error and returns it to our success function, so if the charge is anything other than success it runs the error function.
Although my question remains unanswered, the build works as expected and still remains safe for the user to enter their billing info.
Thanks to the other SO users for their input, it is really appreciated.

I think this particular card number only gives an error when Stripe actually tries to use it.
Just built a change-card-function for my SaaS and noticed that when I update my StripeCustomer default source with the token received, it fails.

Related

How to retrieve draft grade from Google Classroom using api in php

I want to read draft grade marks from Google Classroom using API for a project. But I can't find out the draft grade. Already I've added some code to the quickstart.php file:
require __DIR__ . '/vendor/autoload.php';
// if (php_sapi_name() != 'cli') {
// throw new Exception('This application must be run on the command line.');
// }
/**
* Returns an authorized API client.
* #return Google_Client the authorized client object
*/
function getClient()
{
$client = new Google_Client();
$client->setApplicationName('Google Classroom API PHP Quickstart');
$client->setScopes(array(
Google_Service_Classroom::CLASSROOM_COURSES,
Google_Service_Classroom::CLASSROOM_STUDENT_SUBMISSIONS_STUDENTS_READONLY,
Google_Service_Classroom::CLASSROOM_ROSTERS)
);
$client->setAuthConfig(__DIR__ .'/credentials.json');
$client->setAccessType('offline');
$client->setPrompt('select_account consent');
// Load previously authorized token from a file, if it exists.
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
$tokenPath = 'token.json';
if (file_exists($tokenPath)) {
$accessToken = json_decode(file_get_contents($tokenPath), true);
$client->setAccessToken($accessToken);
}
// If there is no previous token or it's expired.
if ($client->isAccessTokenExpired()) {
// Refresh the token if possible, else fetch a new one.
if ($client->getRefreshToken()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
} else {
// Request authorization from the user.
$authUrl = $client->createAuthUrl();
printf("Open the following link in your browser:\n%s\n", $authUrl);
print 'Enter verification code: ';
$authCode = trim(fgets(STDIN));
// Exchange authorization code for an access token.
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
$client->setAccessToken($accessToken);
// Check to see if there was an error.
if (array_key_exists('error', $accessToken)) {
throw new Exception(join(', ', $accessToken));
}
}
// Save the token to a file.
if (!file_exists(dirname($tokenPath))) {
mkdir(dirname($tokenPath), 0700, true);
}
file_put_contents($tokenPath, json_encode($client->getAccessToken()));
}
return $client;
}
$optParams = array(
'pageSize' => 1000
);
// Copyright 2021 Google LLC.
// SPDX-License-Identifier: Apache-2.0
// Get the API client and construct the service object.
$client = getClient();
$service = new Google_Service_Classroom($client);
// set these parameters:
// 328776504166 <- It is my course id
// 339429593407 <- It is my course work id
$courseId = "328776504166";
$courseWorkId = "339429593407";
$results = $service->courses_courseWork_studentSubmissions->listCoursesCourseWorkStudentSubmissions($courseId, $courseWorkId);
foreach ($results->studentSubmissions as $r => $submission) {
$student = $service->courses_students->get($courseId, $submission->userId);
$studentName = $student->profile->name->fullName;
print("<br>Student Name: ".$studentName . ": ");
print("<br>Draft Grade: ".$submission->draftGrade. "\n");
print("<br>Course Work Id: ".$submission->courseWorkId. "\n");
echo '<pre>';
print_r($submission);
}
Then when I run quickstart.php at localhost the following problems can be seen:
Fatal error: Uncaught Google_Service_Exception: { "error": { "code": 400, "message": "Precondition check failed.", "errors": [ { "message": "Precondition check failed.", "domain": "global", "reason": "failedPrecondition" } ], "status": "FAILED_PRECONDITION" } } in C:\xampp\htdocs\api\vendor\google\apiclient\src\Google\Http\REST.php:118 Stack trace: #0
I can't find my wrong. How to solve this problem? please give me some suggestions.
As stated in the documentation:
Students cannot see draft grades
This is why a student who intents to retrieve a draft grade will obtain a
403 - "Insufficient Permission" error.

PayPal v2 Orders API - difference between OrdersGetRequest and OrdersCaptureRequest

I'm using checkout-sdk with angular and spring boot. Here is the code I have on the angular side
paypal
.Buttons({
style: {
color: 'blue',
shape: 'pill',
label: 'pay',
height: 40
},
createOrder: (data, actions) => {
return actions.order.create({
purchase_units: [
{
description: 'Order id: '+this.order.id,
amount: {
currency_code: 'EUR',
value: this.order.totalPrice
}
}
]
});
},
onApprove: async (data, actions) => {
const order = await actions.order.capture();
this.paidFor = true;
this.checkoutPaypal(this.id,order.id)
},
onError: err => {
}
})
.render(this.paypalElement.nativeElement);
This is function used to retrieve payment, and save details to database..
public String checkoutPaypal(Integer id, String orderId) {
OrdersCaptureRequest request = new OrdersCaptureRequest(orderId);
request.requestBody(buildRequestBody());
HttpResponse<com.paypal.orders.Order> response;
try {
response = payPalClient.client().execute(request);
} catch (IOException e) {
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage());
}
for (PurchaseUnit purchaseUnit : response.result().purchaseUnits()) {
purchaseUnit.amountWithBreakdown();
for (Capture capture : purchaseUnit.payments().captures()) {
if (capture.status().equals("COMPLETED")) {
Order order = orderRepository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Not found!"));
order.setOrderState(OrderState.PAID);
order.setPaymentDetails("Charge id: " + capture.id() + "; Status: " + capture.status() + "; Time paid: " + capture.createTime() + " GMT");
order.addOrderStateChange(OrderState.PAID, false);
sendEmail(order, " paid successfully!", "Thanks for your purchase!<br>We will work as hard as we can, to deliver the order to you, as soon as possible!");
orderRepository.save(order);
}
}
}
return "Successfully paid!";
}
Which worked few days ago.. But now I'm getting this error
{"name":"UNPROCESSABLE_ENTITY","details":[{"issue":"ORDER_ALREADY_CAPTURED","description":"Order already captured.If 'intent=CAPTURE' only one capture per order is allowed."}],"message":"The requested action could not be performed, semantically incorrect, or failed business validation.","debug_id":"f058cb447ccbb","links":[{"href":"https://developer.paypal.com/docs/api/orders/v2/#error-ORDER_ALREADY_CAPTURED","rel":"information_link","method":"GET"}]}
But after replacing
OrdersCaptureRequest request = new OrdersCaptureRequest(orderId);
request.requestBody(buildRequestBody());
HttpResponse<com.paypal.orders.Order> response;
with
OrdersGetRequest request = new OrdersGetRequest(orderId);
HttpResponse<com.paypal.orders.Order> response;
It works as it should.
So my question is, what is the difference between
https://developer.paypal.com/docs/checkout/reference/server-integration/capture-transaction/
and
https://developer.paypal.com/docs/checkout/reference/server-integration/get-transaction/ ?
One is to get the status of the order, the other is to capture the order.
Capturing should not be done once you have called actions.order.capture() on the client side, and will always return an error in such a case. It may also also return an error when the order has been created on the client side (actions.order.create())
A correct server-based integration uses neither actions.order.create() nor actions.order.capture() on the client side. It is very important not to do so, as transactions will be created without your server receiving any immediate direct response from PayPal.
Instead, create two routes on your server, one for 'Create Order' and one for 'Capture Order' as documented here. These routes should return JSON data. Before returning data, the capture route should check for success and act accordingly to send an email or whatever other business operation you need.
The approval flow to pair with the above two routes is https://developer.paypal.com/demo/checkout/#/pattern/server

NativeScript - Not getting any response from back-end with patch on NotFound()

On my back-end I got two possible responses within that action.
The first one:
return Ok(new { Message = "email_confirmed" });
And the second one:
return NotFound();
And on my front-end I got this:
let url: string = "http://10.0.2.2:53286/api/Home/AccountValidation?codeActivation=" + this.code;
this.http.patch(url, {
}).subscribe((res) => {
console.log(JSON.stringify(res));
if(res.status != 404) {
alert({title: "Sistema 3 Esferas", message: "¡Tu cuenta ha sido activada satisfactoriamente! :)", okButtonText: "¡Entendido!"});
this.router.navigate(["/Miembro"]);
} else {
this.btnEnabled = true;
alert({title: "Sistema 3 Esferas", message: "Has introducido un código inválido. :(", okButtonText: "Entiendo..."});
}
});
If the back-end reaches the Ok(), then the if gets executed and everything works perfectly.
However, if my back-end reaches the second return, which is the NotFound() one, nothing happens. You see this log at the beginning of the subscribe()?
console.log(JSON.stringify(res));
Well, if NotFound() is returned, nothing is showed on the log. It's almost like if the subscribe was never executed.
Why is that happening?
You need to add catch handler to catch all other responses than 200(OK) because they are treated as errors, like this -
this.http.patch(url, {
}).subscribe((res) => {
console.log(JSON.stringify(res));
alert({title: "Sistema 3 Esferas", message: "¡Tu cuenta ha sido activada satisfactoriamente! :)", okButtonText: "¡Entendido!"});
this.router.navigate(["/Miembro"]);
}).catch(this.handleError);
};
private handleError(error: any) {
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg);
this.btnEnabled = true;
alert({title: "Sistema 3 Esferas", message: "Has introducido un código inválido. :(", okButtonText: "Entiendo..."});
}
For more information, refer to this.

Did Plaid Change Something About It's MFA?

I had this little piece of code working perfectly returning account and transactions objects in response to the Plaid MFA questions. I'm not sure what went wrong as I (had not until it stopped working and I've since tried a few things) did not touch the code (to my recollection) and even checked several previous working versions to be safe. Anyhow I now get the following list of errors given the scenario:
1) If I try to US Bank MFA, it returns an MFA and after I answer it also returns a account and transactions object. At the end of that info in my terminal it also returns events.js 85 throw er; // Unhandled error event
2) If I try USAA or Bank of America I get the following error object for my response:
{ code: 1203,
message: 'invalid mfa',
resolve: 'The MFA response provided was not correct.',
access_token: 'test_bofa' }
It returns the MFA question though and when I answer with 'again', I get:
{ type: 'questions',
mfa: [ { question: 'You say tomato, I say...?' } ],
access_token: 'test_bofa' }
events.js:85 throw er; // Unhandled 'error' event
plaid.connect({username: req.body.cardName, password: req.body.cardPass, pin: req.body.pin}, req.body.type,
'test#plaid.com',
function (error, response, mfa) {
if (response == undefined) {
res.send(response);
} else if (response.hasOwnProperty('accounts')) {
res.send(response);
} else if (response.hasOwnProperty("mfa")) {
res.send(response);//If I remove this response it kicks me out right away. But with it, I receive an undefined MFA response.
plaid.step(response.access_token, req.body.answer, function (err, response) {
if (response == undefined) {
res.send(response);
} else if (response.hasOwnProperty("resolve")) {
res.send(response);
} else if (response.hasOwnProperty('accounts')) {
res.send(response);
} else if (response.hasOwnProperty('mfa')) {
res.send(response);
}
}
)
}
else {
response = "error";
response.send("something went wrong with Plaid");
}
}
)
}
As i understand during testing mfa code should be string or and array(if there are few questions). So if you enter mfa as an int you will get error.
'again' mfa will call one more mfa loop, and 'tomato' will finalize it.

Magento Ajax Login - Over SSL

I am working on an ajax login for magento and I have run into a small issue when dealing with ssl.
The request page that I am using to display my login view is a non-secure page. From this page, I am using ajax to post to a secure url (https://client.devserver/customer/account/ajaxLoginPost/). The json response I get back is correct, however when I refresh the page the user is not logged in.
I have tested this function on a non-secure site and it works as intended. It seems to only break when I add in the next layer of SSL.
Any help with this is greatly appreciated.
Here is the code from my controller.
public function ajaxLoginPostAction()
{
if ($this->_getSession()->isLoggedIn()) {
$this->_redirect('*/*/');
return;
}
$session = $this->_getSession();
if ($this->getRequest()->isPost()) {
$login = $this->getRequest()->getPost('login');
if (!empty($login['username']) && !empty($login['password'])) {
try {
$session->login($login['username'], $login['password']);
if ($session->getCustomer()->getIsJustConfirmed()) {
$this->_welcomeCustomer($session->getCustomer(), true);
}
$messages = array("isAuthed" => true);
} catch (Mage_Core_Exception $e) {
switch ($e->getCode()) {
case Mage_Customer_Model_Customer::EXCEPTION_INVALID_EMAIL_OR_PASSWORD:
$message = $e->getMessage();
break;
default:
$message = $e->getMessage();
}
$messages = array("isAuthed" => false, "userName" => $login['username'],"error"=> $message);
} catch (Exception $e) {
// Mage::logException($e); // PA DSS violation: this exception log can disclose customer password
}
} else {
$messages = array("isAuthed" => false, "userName" => $login['username'],"error"=>'Login and password are required.');
}
}
//$this->_loginPostRedirect();
$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($messages));
}
There are effectively two cookies (and hence two sessions), one for the "http" connection and one for the "https".
You can either forward to a secure page after performing the login - which negates the need for an AJAX form - or return the SID in the JSON response and find a way to set the non-secure cookie with that value.
A third option is to leave the entire site as secured, it's extra work & cost for the server so not all businesses are willing to take that sensible precaution.

Resources