I have a web form which I want to validate the inputs, and if it passes validation, send the info to a web service, and save to mySQL as a backup. If there is an error either sending to the web service, or with sql, I want to email myself an alert to let me know. When there are no errors, everything runs fine. To test what would happen if there is an error, I have put in the wrong mysql credentials. When this happens, the whole script takes about 30 seconds to process. I'm wondering if there is a way to run the validation part and return the response, before finishing the script. I want to call the web service and save to mysql in the background, after the response to the server has been sent. Is this possible? Would I need to implement something like gearman?
Also, this would be a fairly high volume form. If two people tried to submit at the same time, would there be a mysql issue? Are there any ways to better improve security? I'm a beginner so any extra advice would be great.
Thanks!
<?php
if( isset($_POST) ){
//form validation vars
$formok = true;
$errors = array();
//sumbission data
$ipaddress = $_SERVER['REMOTE_ADDR'];
//
//form data
//
//Services
if(isset($_POST['services'])) {
$services = $_POST['services'];
} else {
$services = array(
'Neck' => NULL,
'Back' => NULL,
'Other' => NULL,
);
}
$firstname = $_POST['firstname'];
$lastname = $_POST['lastname'];
$email = $_POST['email'];
$telephone = $_POST['telephone'];
$TelephoneSanitized = preg_replace("/[^0-9]/", "", $telephone); //format phone as number only
//if phone number does not start with 1, and the length is less than 11 characters, add the 1 to the beginning
if ((substr($TelephoneSanitized, 0, 1) != '1') && (strlen($TelephoneSanitized) < 11)) {
$TelephoneSanitized = "1".$TelephoneSanitized;
}
//$state = strip_tags($_POST['state']);
$location = $_POST['location'];
$message = $_POST['message'];
$leadsource = $_POST['leadsource'];
$refId = $_POST['refId'];
$isconsult = $_POST['isconsult'];
//Third Party Emails
if(isset($_POST['receiveThirdPtyEmails'])) {
$receiveThirdPtyEmails = strip_tags($_POST['receiveThirdPtyEmails']);
} else {
$receiveThirdPtyEmails = NULL;
}
//
//validation
//
//validate location has been set
if($location == 0){
$formok = false;
$errors[] = "Please select your nearest location";
}
//validate name is not empty
if(empty($firstname)){
$formok = false;
$errors[] = "Please enter your first name";
}
if(empty($lastname)){
$formok = false;
$errors[] = "Please enter your last name";
}
//validate email address is not empty
if(empty($email)){
$formok = false;
$errors[] = "Please enter your email address";
//validate email address is valid
}elseif(!filter_var($email, FILTER_VALIDATE_EMAIL)){
$formok = false;
$errors[] = "You have not entered a valid email address";
}
//validate phone is not empty
if(empty($telephone)){
$formok = false;
$errors[] = "Please enter your phone number";
}
//validate phone is at least 10 characters
elseif(strlen($TelephoneSanitized) < 10){
$formok = false;
$errors[] = "Your phone number must be at least 10 characters";
}
//what we need to return back to our form
$returndata = array(
'posted_form_data' => array(
'services' => $services,
'firstname' => $firstname,
'lastname' => $lastname,
'email' => $email,
'telephone' => $telephone,
//'state' => $state,
'location' => $location,
'message' => $message
),
'form_ok' => $formok,
'errors' => $errors,
);
//if this is not an ajax request
if(empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) !== 'xmlhttprequest'){
//set session variables
session_start();
$_SESSION['cf_returndata'] = $returndata;
//redirect back to form
header('location: ' . $_SERVER['HTTP_REFERER']);
}
//
//send to web service if all is ok
//
if($formok){
//build query string
$fields = array('services' => $services,
'location' => $location,
'firstname' => $firstname,
'lastname' => $lastname,
'email' => $email,
'emailconfirm' => $email,
'phone' => $TelephoneSanitized,
'comments' => $message,
'refid' => $refId,
'leadsource' => $leadsource,
'isconsult' => $isconsult,
'receiveThirdPtyEmails' => $receiveThirdPtyEmails);
$url = "http://fake.aspx?" . http_build_query($fields, '', "&");
$url = preg_replace('/%5B[a-zA-Z]+%5D/', '', $url);
$curl_handle = curl_init($url);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true);
$results = curl_exec($curl_handle);
curl_close($curl_handle);
}
//
//save data to mysql if all is ok PDO
//
if($formok){
// Connecting to the MySQL server
$host="fakehost-on the same server as form";
$user_name="fakeuser";
$pwd="fakepass";
$database_name="fakedb";
$services = implode(',',array_filter($services)); // change array to string
date_default_timezone_set('America/New_York');
$date = date('m/d/Y h:i:s a', time());
$date = date("Y-m-d H:i:s",strtotime($date));
// mysql
try {
//connect to db
$conn = new PDO("mysql:host=$host;dbname=$database_name", $user_name, $pwd);
//set error handling
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
//prepare statement
$q = $conn->prepare("INSERT INTO leads
(ip_address, lead_time, location, first_name, last_name, email_address, telephone, comments, services, receiveThirdPtyEmails, leadsource, refid)
VALUES
(:ip_address, :lead_time, :location, :first_name, :last_name, :email_address, :telephone, :comments, :services, :receiveThirdPtyEmails, :leadsource, :refid)");
//execute statement
$q->execute(array(
':ip_address'=>$ipaddress,
':lead_time'=>$date,
':location'=>$location,
':first_name'=>$firstname,
':last_name'=>$lastname,
':email_address'=>$email,
':telephone'=>$TelephoneSanitized,
':comments'=>$message,
':services'=>$services,
':receiveThirdPtyEmails'=>$receiveThirdPtyEmails,
':leadsource'=>$leadsource,
':refid'=>$refId));
}
catch(PDOException $e) {
$error_code = $e->getMessage(); // Specify the error code
$error_type = "SQL Insert Failed";
require_once("resources/error-mailer.php"); // Include the error mailer script
}
# close the connection
$conn = null;
}
}
Javascript/jQuery using JSON and AJAX is your best bet. There's a great example here:
Send JSON data via POST (ajax) and receive json response from Controller (MVC)
Also security wise, you'll want to use the mysqli_real_escape_string():
http://php.net/manual/en/mysqli.real-escape-string.php
on strings values you accept via POST or GET before you put the value into your query. It avoids SQL injection. For integers use abs(intval($_POST['posted_integer'])) or ctype_digit, whatever floats your needs, or preg_replace() / preg_match() regular expressions.
DO NOT let POST or GET values go untouched into your database!!
Related
It seems I am missing something when trying to handle some errors with Stripe in test mode with PHP.
Payment are successful when I enter a test card number like 4242424242424242 (for VISA) but I have no error and nothing is recorded when I enter a bad card number.
It is like if the button "Pay" was not working although it displays an error message if I use a real correct card number in test mode.
Does someone know what am I doing wrong here ? Thanks.
Here is the PHP code :
// Check whether stripe token is not empty
if(!empty($_POST['stripeToken'])){
// Retrieve stripe token, card and user info from the submitted form data
$token = $_POST['stripeToken'];
$name = $_POST['name'];
$email = $_POST['email'];
$card_number = $_POST['card_number'];
$card_exp_month = $_POST['card_exp_month'];
$card_exp_year = $_POST['card_exp_year'];
$card_cvc = $_POST['card_cvc'];
$itemPrice = $_POST['itemPrice'];
$itemNumber = $_POST['itemNumber'];
$Ticket_number = $_POST['Ticket_number'];
// Include Stripe PHP library
require_once 'stripe-php/init.php';
// Set API key
\Stripe\Stripe::setApiKey(STRIPE_API_KEY);
// Add customer to stripe
$customer = \Stripe\Customer::create(array(
'email' => $email,
'source' => $token
));
// Unique order ID
$orderID = strtoupper(str_replace('.','',uniqid('', true)));
// Convert price to cents
$itemPrice = ($itemPrice*100);
// Charge a credit or a debit card
$charge = \Stripe\Charge::create(array(
'customer' => $customer->id,
'amount' => $itemPrice,
'currency' => $currency,
'description' => $itemName,
'metadata' => array(
'order_id' => $orderID
)
));
// Retrieve charge details
$chargeJson = $charge->jsonSerialize();
// Check whether the charge is successful
if($chargeJson['amount_refunded'] == 0 && empty($chargeJson['failure_code']) && $chargeJson['paid'] == 1 && $chargeJson['captured'] == 1){
// Order details
$transactionID = $chargeJson['balance_transaction'];
$paidAmount = $chargeJson['amount'];
$paidCurrency = $chargeJson['currency'];
$payment_status = $chargeJson['status'];
// Include database connection file
include_once 'dbConnect.php';
$itemPrice = ($itemPrice/100);
$paidAmount = ($paidAmount/100);
// Insert tansaction data into the database
$sql = "INSERT INTO orders(name,email,card_number,card_exp_month,card_exp_year,item_name,item_number,item_price,item_price_currency,paid_amount,paid_amount_currency,txn_id,payment_status,created,modified) VALUES('".$name."','".$email."','".$card_number."','".$card_exp_month."','".$card_exp_year."','".$itemName."','".$itemNumber."','".$itemPrice."','".$currency."','".$paidAmount."','".$paidCurrency."','".$transactionID."','".$payment_status."',NOW(),NOW())";
$insert = $db->query($sql);
$payment_id = $db->insert_id;
// If the order is successful
if($payment_status == 'succeeded'){
$ordStatus = 'success';
$statusMsg = '';
}else{
$statusMsg = "Your Payment has Failed!";
}
}else{
print '<pre>';print_r($chargeJson);
$statusMsg = "Transaction has been failed!";
}
}else{
$statusMsg = "Error on form submission.";
}
?>
Thank you for your answers but in fact it was a dummy mistake : I did not declare an id to display my error. I had to add the following code in my form :
<p id="payment-status" role="alert"></p>
I'm creating reset login signup api in PHP using JWT and I'm facing some problems when using postman. When I'll try to send raw data in JSON(application/json) format, it gets success but when I send form-data, it's not working.
login api
<?PHP
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: POST");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
function msg($success,$status,$message,$extra = []){
return array_merge([
'success' => $success,
'status' => $status,
'message' => $message
],$extra);
}
// INCLUDING DATABASE AND MAKING OBJECT
require __DIR__.'/classes/Database.php';
$db_connection = new Database();
$conn = $db_connection->dbConnection();
// GET DATA FORM REQUEST
$data = json_decode(file_get_contents("php://input"));
$returnData = [];
// IF REQUEST METHOD IS NOT POST
if($_SERVER["REQUEST_METHOD"] != "POST"):
$returnData = msg(0,404,'Page Not Found!');
// CHECKING EMPTY FIELDS
elseif(!isset($data->firstname)
|| !isset($data->lastname)
|| !isset($data->mobile)
|| !isset($data->email)
|| !isset($data->password)
|| !isset($data->class)
|| empty(trim($data->firstname))
|| empty(trim($data->lastname))
|| empty(trim($data->mobile))
|| empty(trim($data->email))
|| empty(trim($data->password))
|| empty(trim($data->class))
):
$fields = ['fields' => ['firstname', 'lastname', 'mobile', 'email', 'password', 'class']];
$returnData = msg(0,422,'Please Fill in all Required Fields!',$fields);
// IF THERE ARE NO EMPTY FIELDS THEN-
else:
$firstname = trim($data->firstname);
$lastname = trim($data->lastname);
$mobile = trim($data->mobile);
$email = trim($data->email);
$password = trim($data->password);
$class = trim($data->class);
if(!filter_var($email, FILTER_VALIDATE_EMAIL)):
$returnData = msg(0,422,'Invalid Email Address!');
elseif(strlen($password) < 8):
$returnData = msg(0,422,'Your password must be at least 8 characters long!');
elseif(strlen($firstname) < 3):
$returnData = msg(0,422,'Your first name must be at least 3 characters long!');
elseif(strlen($lastname) < 3):
$returnData = msg(0,422,'Your last name must be at least 3 characters long!');
elseif(strlen($mobile) < 10):
$returnData = msg(0,422,'Your mobile number must be at least 10 characters long!');
else:
try{
$check_email = "SELECT `email` FROM `users` WHERE `email`=:email";
$check_email_stmt = $conn->prepare($check_email);
$check_email_stmt->bindValue(':email', $email,PDO::PARAM_STR);
$check_email_stmt->execute();
if($check_email_stmt->rowCount()):
$returnData = msg(0,422, 'This E-mail already in use!');
else:
$insert_query = "INSERT INTO `users`(`firstname`,`lastname`,`mobile`,`email`,`password`,`class`) VALUES(:firstname,:lastname,:mobile,:email,:password,:class)";
$insert_stmt = $conn->prepare($insert_query);
// DATA BINDING
$insert_stmt->bindValue(':firstname',
htmlspecialchars(strip_tags($firstname)),PDO::PARAM_STR);
$insert_stmt->bindValue(':lastname',
htmlspecialchars(strip_tags($lastname)),PDO::PARAM_STR);
$insert_stmt->bindValue(':mobile', $mobile,PDO::PARAM_STR);
$insert_stmt->bindValue(':email', $email,PDO::PARAM_STR);
$insert_stmt->bindValue(':password', password_hash($password, PASSWORD_DEFAULT),PDO::PARAM_STR);
$insert_stmt->bindValue(':class', $class,PDO::PARAM_STR);
$insert_stmt->execute();
$returnData = msg(1,201,'You have successfully registered.');
endif;
}
catch(PDOException $e){
$returnData = msg(0,500,$e->getMessage());
}
endif;
endif;
echo json_encode($returnData);
please tell me where I'm wrong and help me to solve this issue.
Thanks in advance
You aren't correct sending the form to the your API endpoint.
Step 1. - Use the header params! (Header tab - key:value -> Content-type: application/json)
Step 2. - Don't use formdata options! This method send simple POST request without json_encoding! You can only use raw option.
I have built a PHP form, but want an email to be sent to whatever country the user chooses on a dropdown.
E.g. If they choose UK on dropdown, send an email to our UK account. If they choose US, send to our US account etc...
The entire form is working perfectly at the moment, I just need this little feature to work then it would be perfect. Thank you for looking, its appreciated!
This is my code so far:-
<?php
// require ReCaptcha class
require('recaptcha-master/src/autoload.php');
// configure
// an email address that will be in the From field of the email.
$from = 'A new client has registered their details <noreply#emailaddress.com>';
// an email address that will receive the email with the output of the form
$sendTo = '<scott#emailaddress.com>';
// subject of the email
$subject = 'New Registered Form:';
// form field names and their translations.
// array variable name => Text to appear in the email
$fields = [
'firstname' => 'First Name', 'lastname' => 'Last Name', 'company' => 'Company', 'email' => 'Email Address', 'jobrole' => 'Job Role',
'postcode' => 'Postcode', 'country' => 'Country',
];
// message that will be displayed when everything is OK :)
$okMessage = 'Thank you for registering.';
// If something goes wrong, we will display this message.
$errorMessage = 'There was an error while submitting the form. Please try again later';
// ReCaptch Secret
$recaptchaSecret = 'AAAA';
// let's do the sending
// if you are not debugging and don't need error reporting, turn this off by error_reporting(0);
error_reporting(E_ALL & ~E_NOTICE);
try
{
if ( ! empty($_POST))
{
// validate the ReCaptcha, if something is wrong, we throw an Exception,
// i.e. code stops executing and goes to catch() block
if ( ! isset($_POST['g-recaptcha-response']))
{
throw new \Exception('ReCaptcha is not set.');
}
// do not forget to enter your secret key from https://www.google.com/recaptcha/admin
$recaptcha = new \ReCaptcha\ReCaptcha($recaptchaSecret, new \ReCaptcha\RequestMethod\CurlPost);
// we validate the ReCaptcha field together with the user's IP address
$response = $recaptcha->verify($_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR']);
if ( ! $response->isSuccess())
{
throw new \Exception('ReCaptcha was not validated.');
}
// everything went well, we can compose the message, as usually
$emailText = "This person has registered their details \n=============================\n";
foreach ($_POST as $key => $value)
{
// If the field exists in the $fields array, include it in the email
if (isset($fields[$key]))
{
$emailText .= "$fields[$key]: $value\n";
}
}
// All the neccessary headers for the email.
$headers = [
'Content-Type: text/plain; charset="UTF-8";',
'From: ' . $from,
'Reply-To: ' . $from,
'Return-Path: ' . $from,
];
// Send email
mail($sendTo, $subject, $emailText, implode("\n", $headers));
$responseArray = ['type' => 'success', 'message' => $okMessage];
}
}
catch (\Exception $e)
{
$responseArray = ['type' => 'danger', 'message' => $e->getMessage()];
}
if ( ! empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
{
$encoded = json_encode($responseArray);
header('Content-Type: application/json');
echo $encoded;
}
else
{
echo $responseArray['message'];
}
?>
Thank you very much in advance!!
Scott Geere
Personally I would do something like this:
switch ($_POST['country']):
case 'UK':
$sendTo = '<UK#emailaddress.com>';
break;
case 'US';
$sendTo = '<US#emailaddress.com>';
break;
default:
$sendTo = '<scott#emailaddress.com>';
endswitch;
Which means you could change:
// an email address that will receive the email with the output of the form
//$sendTo = '<helena#dropbox.com>,<l.stone#emeraldcolour.com>';
$sendTo = '<scott#emailaddress.com>';
To:
// an email address that will receive the email with the output of the form
//$sendTo = '<helena#dropbox.com>,<l.stone#emeraldcolour.com>';
switch ($_POST['send_to']):
case 'UK':
$sendTo = '<UK#emailaddress.com>';
break;
case 'US';
$sendTo = '<US#emailaddress.com>';
break;
default:
$sendTo = '<scott#emailaddress.com>';
endswitch;
Please do not forget: never trust the user. So do not just do stuff on $_POST data, make sure you validate the given input before you use it.
Another side note:
Instead of using this raw code in yours, you could make it a function (so you can reuse it somewhere else as well).
For example:
function getSendToEmail($country)
{
switch ($country):
case 'UK':
return '<UK#emailaddress.com>';
break;
case 'US';
return '<US#emailaddress.com>';
break;
default:
return '<scott#emailaddress.com>';
endswitch;
}
// an email address that will receive the email with the output of the form
//$sendTo = '<helena#dropbox.com>,<l.stone#emeraldcolour.com>';
$sendTo = $this->getSendToEmail($_POST['country']);
Documentation:
http://php.net/manual/en/control-structures.switch.php // Switch
http://php.net/manual/en/functions.user-defined.php // Functions
http://php.net/manual/en/filter.examples.validation.php // Validation
if (isset($_POST['country'])) {
$country = $_POST['country'];
if ($country === 'France') {
$sendTo = 'france#emailadress.com';
} elseif ($country === 'England') {
$sendTo = 'england#emailadress.com';
}
}
You can put it before the mail function.
You can also use an array like that:
$emailList = [
'France' => 'france#emailadress.com',
'England' => 'england#emailadress.com'
];
if (isset($_POST['country'])) {
// Get email from the key
$sendTo = $emailList[$_POST['country']];
}
I have this contact form but I am confused as to how I can insert PHPMailer (without Composer) into the script?
I am not sure how to properly add it so that way, once it processes and sends the form it alerts the user. I do not have the ability to utilize composer, so I would need to upload PHPMailer into the directory.
<?php
function validateRecaptcha($secret, $clientResponse, $clientIp)
{
$data = http_build_query([
"secret" => $secret,
"response" => $clientResponse,
"remoteip" => $clientIp,
]);
$options = [
"http" => [
"header" =>
"Content-Type: application/x-www-form-urlencoded\r\n".
"Content-Length: ".strlen($data)."\r\n",
"method" => "POST",
"content" => $data,
],
];
$response = file_get_contents(
"https://www.google.com/recaptcha/api/siteverify",
false,
stream_context_create($options)
);
if($response === false)
{
return false;
}
else if(($arr = json_decode($response, true)) === null)
{
return false;
}
else
{
return $arr["success"];
}
}
$errors = array(); // array to hold validation errors
$data = array(); // array to pass back data
// validate the variables ======================================================
// if any of these variables don't exist, add an error to our $errors array
if (empty($_POST['firstName']))
$errors['firstName'] = 'First Name is required.';
if (empty($_POST['lastName']))
$errors['lastName'] = 'Last Name is required.';
if (empty($_POST['companyName']))
$errors['companyName'] = 'Company Name is required.';
if (empty($_POST['companyAddress']))
$errors['companyAddress'] = 'Company Address is required.';
if (empty($_POST['city']))
$errors['city'] = 'City is required.';
if (empty($_POST['state']))
$errors['state'] = 'State is required.';
if (empty($_POST['emailAddress']))
$errors['emailAddress'] = 'Email Address is required.';
if (empty($_POST['comment']))
$errors['comment'] = 'Comment is required.';
if (empty($_POST['g-recaptcha-response']))
$errors['captcha'] = 'Captcha is required.';
// return a response ===========================================================
// if there are any errors in our errors array, return a success boolean of false
if(!validateRecaptcha($secret, $_POST['g-recaptcha-response'], $_SERVER["REMOTE_ADDR"]))
{
$errors['recaptcha'] = 'Captcha is required.';
}
if ( ! empty($errors)) {
// if there are items in our errors array, return those errors
$data['success'] = false;
$data['errors'] = $errors;
} else {
// if there are no errors process our form, then return a message
// DO ALL YOUR FORM PROCESSING HERE
// THIS CAN BE WHATEVER YOU WANT TO DO (LOGIN, SAVE, UPDATE, WHATEVER)
// show a message of success and provide a true success variable
$data['success'] = true;
$data['message'] = 'Success!';
}
// return all our data to an AJAX call
echo json_encode($data);
Without autoloader:
<?php
//You shall use the following exact namespaces no
//matter in whathever directory you upload your
//phpmailer files.
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
//Now include the following following files based
//on the correct file path. Third file is required only if you want to enable SMTP.
require 'path/to/PHPMailer/src/Exception.php';
require 'path/to/PHPMailer/src/PHPMailer.php';
require 'path/to/PHPMailer/src/SMTP.php';
?>
You shall add the following class to initiate the mailer after checking if your query or condition is executed.
<?php
$mail = new PHPMailer(true);
?>
You shall find a nice and simple example at https://github.com/PHPMailer/PHPMailer/blob/master/README.md to start with.
I hope it helps.
<?php
$emparray = array();
if($_SERVER['REQUEST_METHOD'] == "POST")
{
$name = urldecode($_POST['name']);
$email = filter_var($_POST["email"],FILTER_SANITIZE_EMAIL);
$subject = urldecode($_POST['subject']);
$message = urldecode($_POST['message']);
$message_final = 'Name :-'.$name."\n".'Email Id :-'.$email."\n".'Message :-'.$message;
$to = 'xyz';
if($name!=NULL && $email!=NULL && $subject!=NULL && $message!=NULL)
{
if (!filter_var($email, FILTER_VALIDATE_EMAIL))
{
$emparray =array(
'status' => 0, 'message' => 'Invalid Email Format');
}
else
{
$emparray= mail($to,$subject,$message_final);
$emparray =array(
'status' => 1, 'message' => 'Thank you for writing us,Email sent successfully');
}
}
else
{
$emparray =array(
'status' => 0, 'message' => 'All fields are required');
}
}
else
{
$emparray = array("status" => 0, "message" => "Request Method Not accepted");
}
echo json_encode($emparray,JSON_PRETTY_PRINT,JSON_FORCE_OBJECT);
?>
I am using postman tool for testing. If I send data using headers with key value it goes like body. How to stop this to send data with headers too.
I want if data will send from body then only it should work. If i send it from headers it should prompt me error of cant send data using headers.
Someone tells me about headers_sent function to overcome this issue. But im unable to implement it. please help me this the same.
You have to select body/raw/JSON (application/json).
Hope it works for you.