what is doing on SMS send Reminder to remain from Server Side for package end within 7 days or less than 10 days? any code or example video how to implement query.
I want the alert will come out about 2 weeks before the expiry date.
Many Paid SMS api available in online.
Here i'm using SmsHorizon
// Replace with your username
$user = "yourname";
// Replace with your API KEY (We have sent API KEY on activation email, also available on panel)
$apikey = "ABCBEFGH786756";
// Replace if you have your own Sender ID, else donot change
$senderid = "WEBSMS";
// For Plain Text, use "txt" ; for Unicode symbols or regional Languages like hindi/tamil/kannada use "uni"
$type = "txt";
// Database Configuration
$con = mysql_connect("143.114.0.49","username","password");
$con_db = mysql_select_db("db_name",$con);
/***********************Over Speed Alert***/ //Run every 1 minute
$i = 0;
$message = "2 Week Before Expiry Alert.\n" ;
$device_query = mysql_query("SELECT * FROM table_name); // Write whatever the query you've required.
while($device_value = mysql_fetch_array($device_query))
{
$message.= ""; // Content you load here.
$i++;
}
// Replace with the destination mobile Number to which you want to send sms
$mobile = array('9999999999');
// Replace with your Message content
$message = urlencode($message);
if($i > 0)
{
for($j = 0; $j < count($mobile); $j++)
{
$ch = curl_init("http://smshorizon.co.in/api/sendsms.php?user=".$user."&apikey=".$apikey."&mobile=".$mobile[$j]."&senderid=".$senderid."&message=".$message."&type=".$type."");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//$output = curl_exec($ch);
if(curl_errno($ch))
{
echo 'Curl error: ' . curl_error($ch);
}
curl_close($ch);
// Display MSGID of the successful sms push
//echo $output;
}
}
Hope it help you.
Related
I have a code that sends SMS to customers that is set up as cron job. My problem is, when I use cURL, it's sending 2-part messages and our wallet is being charged twice. We have an average of 500 messages to send per day. My goal is to make the message 1-part only.
So I'm trying to find the best way to send messages in loop without using cURL.
I have thought of saving the post data from the loop in an array and send it to my view. Then when the view is called, I will automatically send the form withouth hitting the submit button and using javascript to auto submit. After the view is called, I will use file_get_contents() to get the response from the URL. But I cant make it work:
The view is not working inside the loop. It just works outside the loop.
If I pass the loop inside the view and not in the controller, how can I get the response data each loop?
My current code in CURL:
public function send_sms_globe(){
error_reporting(-1);
ini_set('display_errors', 1);
set_time_limit(0);
//get all data from the database pull with status = queue
$globe_data = $this->New_Sms_Api_model->get_queued_data('globe_api');
$passphrase = '[our_pass_phrase]';
$app_id = '[our_app_id]';
$app_secret = '[our_app_secret]';
$url = 'https://devapi.globelabs.com.ph/smsmessaging/v1/outbound/<our_shortcode>/requests/';
$ch = curl_init($url);
$limit = 0;
foreach($globe_data AS $records_data){
if($limit == 49){
break;
}
switch($limit) {
case 49:
$limit = 0;
break;
default:
if($records_data['Remarks'] == 'LOADED'){
if($records_data['sent_to'] == 'sender'){
$address = $records_data['sender_phone_number'];
}else if($records_data['sent_to'] == 'consignee'){
$address = $records_data['consignee_phone_number'];
}
} else {
$address = $records_data['sender_phone_number'];
}
//$address = '+63917*******';//address : *subscriber number $records_data['phone_number'];
$message = (isset($records_data['Message']) && $records_data['Message'] != '') ? $records_data['Message']:''; //message : *sms content
$str = iconv('UTF-8', 'ASCII//IGNORE//TRANSLIT', $message);
$post_data = [
'app_id' => $app_id,
'app_secret' => $app_secret,
'passphrase' => $passphrase,
'message' => rawurlencode($str),
'address' => $address
];
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
// execute!
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$queue_id = $records_data['ID'];
$invoice_number = $records_data['InvoicecNumber'];
$status_remark = $records_data['Remarks'];
$record_id = $records_data['record_id'];
if($http_code == 201 || $http_code == 200){
$no_of_tries = $records_data['no_of_tries'];
if($no_of_tries == 0){
$no_of_tries = 1;
} else {
$no_of_tries = $records_data['no_of_tries'];
}
$status = 'sent';
$retry = 0;
} else {
$no_of_tries = $records_data['no_of_tries'] + 1;
if($no_of_tries == 3){
$status = 'failed';
$retry = 0;
} else {
$status = 'retry';
$retry = 1;
}
}
$update_queued_data = $this->New_Sms_Api_model->update_queued_data($queue_id, $invoice_number, $status, $retry, $no_of_tries);
if($update_queued_data){
if($status == 'sent'){
if($status_remark == 'LOADED'){
$sent_to = $records_data['sent_to'];
} else {
$sent_to = NULL;
}
$this->New_Sms_Api_model->save_to_cq_sms($invoice_number, $status_remark, $record_id,$sent_to);
echo $records_data['record_id'].' ---- '.$status;
}
$limit++;
}
}
}
// close the connection, release resources used
curl_close($ch);
}
We have a message with 157 characters (160 max). I already talked to the API support we're using. First they suggested to format my message as URL encoding, and so I did. So from 3-part message it became 2-part. And then they said it will send as 2-part even if it's formatted that way because we use cURL. They suggested that we use PostMan but it's not for free so it's not an option.
Any ideas that can replace my current code? Thanks!
Sorry for the confusion. I was able to fix the issue without changing all of my code. I just removed rawurlencode in my string message and it's sending a 1-part message now.
Maybe using $str = iconv('UTF-8', 'ASCII//IGNORE//TRANSLIT', $message); already did the trick and using rawurlencode after just added additional characters ex: %20.
Thanks everyone!
I am doing a api for cab booking app like uber and ola using laravel.In that the customer will send the request to available cab driver using gcm and cab driver will accept the request.During these process when customer click the request button it will be loading until driver accept the request.When driver accept the request customer get the driver details and driver get the customer details.How can i do it in laravel..??
I can send the customer request using below code:
public function customer_booking(Request $req)
{
if ($req->isMethod('post'))
{
$customer_id=$req->customer_id;
$driver_type=$req->type_id;
//getting driver
$res=DriverLatLongModel::where('driver_type',$driver_type)
->where('booking_status','3')->orwhere('booking_status','2')
->where('active_status','0')->orderBy('created_at', 'desc')->first();
$driver_lat='';
$driver_long='';
$driver_id_booking='';
if(empty($res))
{
$gcm_data[]=array('status'=>'0');
return Response::json(array('message'=>$gcm_data), 200);
}
else
{
$driver_id_booking=$res->driver_id;
}
$registration_id = array();
//getting gcm id
$driver_position = DriverLatLongModel::where('driver_id',$driver_id_booking)->get();
foreach($driver_position as $resid)
{
array_push($registration_id , $resid['registration_id']);
}
//send gcm
$url = 'https://android.googleapis.com/gcm/send';
$message_gcm = array("Status"=>"1","Notice" =>"WELCOME","customer_id"=>$customer_id);
$fields = array(
'registration_ids' => $registration_id ,
'data' => $message_gcm ,
);
$headers = array(
'Authorization: key=AIzaSyDCDmsrv3ELqD_6qseFgERciRnmm9uBtNg',
'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$result = curl_exec($ch);
if ($result === FALSE) {
die('Curl failed: ' . curl_error($ch));
}
curl_close($ch);
$driver_data=array();
//getting result of driver side
$finding_donor_loc=CustomerBookingModel::getCustomer($customer_id);
if(empty($finding_donor_loc))
{
$driver_data[]=array('status'=>'0');
}
else
{
//getting driver details
$driver_details=DriverDetailsModel::where('driver_id',$finding_donor_loc)->first();
$driver_name=$driver_details->driver_name;
$driver_data[]=array('status'=>'1','driver_name'=>$driver_name);
}
return Response::json(array('message'=>$driver_data), 200);
}
}
I am using Helper class to write the codeing for waiting until the driver accept the request:
public static function getCustomer($customer_id)
{
$duration =15; // Duration of the loop in seconds
$sleep = 5;// Sleep beetween each execution (with stuff execution)
for ($i = 0; $i < floor($duration / $sleep); ++$i)
{
$start = microtime(true);
$users = DB::table('booking_information')
->where('customer_id',$customer_id)->where('booking_status','1')
->where('book_confirm','1')->orderBy('created_at', 'asc')->first();
time_sleep_until($start + $sleep);
}
if(empty($users))
{
$confim_driver_id='0';
return $confim_driver_id;
}
else
{
$confim_driver_id=$users ->driver_id;
return $confim_driver_id;
}
}
The helper class do the work of get the driver id when they accept the request within 15 seconds.It's work for me but the driver will accept the request within 15 seconds.How can i do without time duration to check the db if driver id present or not and also it will loading in customer side until driver accept the request.!!
If you want to return the booking confirmation to user as soon as the booking is confirmed then you can put a IF condition in your for loop & return the driver_id as soon as the conditions are satisfied.
$duration = 15; // Duration of the loop in seconds
$sleep = 5; // Sleep between each execution (with stuff execution)
for ($i = 0; $i < floor($duration / $sleep); ++$i)
{
$start = microtime(true);
// query the database to check if the booking is confirmed
$booking = DB::table('booking_information')
->where('customer_id', $customer_id)
->where('booking_status', '1')
->where('book_confirm', '1')
->orderBy('created_at', 'asc')
->first();
// if the booking is confirmed then return the driver_id
// return will also stop the loop
if($booking) {
return $booking->driver_id;
}
// Make the script execution sleep
time_sleep_until($start + $sleep);
}
// if booking is not confirmed then return 0
if(empty($booking)) return 0;
A better way to do a task like this in laravel can be achieved via Events & Listeners. The workflow would be something like this.
1. Your API recieves a request to book a cab
2. A NewBookingRequest event is fired & NewBookingRequestListener sends a push notificaton to the nearest driver about the new booking
3. Driver confirms/denies the booking & your API fires BookingConfirmed/BookingDenied event
4. Notification is sent to the user about the booking
I am new here to get answers for my issues, hoping for your kind advice. Thanks in advance.
I have written a HTTP API to send SMS using curl. Everything is working fine, except I am failing to loop and post curl for certain phone numbers. For example: User uploads 50000 phone numbers using excel sheet on my site, I fetch all the mobile numbers from the database, and then post it through CURL.
Now the sms gateway which I send the request accepts only maximum 10000 numbers at once via http api.
So from the 50000 fetched numbers I want to split the numbers to 10000 each and loop that and send curl post.
Here is my code
//have taken care of sql injection on live site
$resultRestore = mysql_query("SELECT * FROM temptable WHERE userid = '".$this->user_id."' AND uploadid='".$uploadid."' ");
$rowRestoreCount = mysql_num_rows($resultRestore);
#mysql_data_seek($resultRestore, 0);
$phone_list = "";
while($rowRestore = mysql_fetch_array($resultRestore))
{
$phone_list .= $rowRestore['recphone'].",";
}
$url = "http://www.smsgatewaycenter.com/library/send_sms_2.php?UserName=".urlencode($this->param[userid])."&Password=".urlencode($this->param[password])."&Type=Bulk&To=".urlencode(substr($phone_list, 0, -1))."&Mask=".urlencode($this->sendname)."&Message=Hello%20World";
//echo $url;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$curl_scraped_page = curl_exec($ch);
curl_close($ch);
Now, from the $phone_list, I need to loop for every 10000 numbers, How can I achieve this?
Its been 2 days, I have tried several things and not getting the result.
Kindly help...
NOTE: I'm going to start off with the obligatory warning about using mysql functions. Please consider switching to mysqli or PDO.
There are a number of different ways you could do this. Personally, I would reconfigure your script to only fetch 10,000 numbers at a time from the database and put that inside a loop. It might look something like this (note that for simplicity I am not updating your mysql* calls to mysqli*). Keep in mind I didn't run this through a compiler since most of your code I can't actually test
// defines where the query starts from
$offset= 0;
// defines how many to get with the query
$limit = 10000;
// set up base SQL to use over and over updating offset
$baseSql = "SELECT * FROM temptable WHERE userid = '".$this->user_id."' AND uploadid='".$uploadid."' LIMIT ";
// get first set of results
$resultRestore = mysql_query($baseSql . $offset . ', '. $limit);
// now loop
while (mysql_num_rows($resultRestore) > 0)
{
$rowRestoreCount = mysql_num_rows($resultRestore);
$phone_list = "";
while($rowRestore = mysql_fetch_array($resultRestore))
{
$phone_list .= $rowRestore['recphone'].",";
}
$url = "http://www.smsgatewaycenter.com/library/send_sms_2.php?UserName=".urlencode($this->param[userid])."&Password=".urlencode($this->param[password])."&Type=Bulk&To=".urlencode(substr($phone_list, 0, -1))."&Mask=".urlencode($this->sendname)."&Message=Hello%20World";
//echo $url;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$curl_scraped_page = curl_exec($ch);
curl_close($ch);
// now update for the while loop
// increment by value of limit
$offset += $limit;
// now re-query for the next 10000
// this will continue until there are no records left to retrieve
// this should work even if there are 50,123 records (the last loop will process 123 records)
$resultRestore = mysql_query($baseSql . $offset . ', '. $limit);
}
You could also achieve this without using offset and limit in your sql query. This might be a simpler approach for you:
// define our maximum chunk here
$max = 10000;
$resultRestore = mysql_query("SELECT * FROM temptable WHERE userid = '".$this->user_id."' AND uploadid='".$uploadid."' ");
$rowRestoreCount = mysql_num_rows($resultRestore);
#mysql_data_seek($resultRestore, 0);
$phone_list = "";
// hold the current number of processed phone numbers
$count = 0;
while($rowRestore = mysql_fetch_array($resultRestore))
{
$phone_list .= $rowRestore['recphone'].",";
$count++;
// when count hits our max, do the send
if ($count >= $max)
{
$url = "http://www.smsgatewaycenter.com/library/send_sms_2.php?UserName=".urlencode($this->param[userid])."&Password=".urlencode($this->param[password])."&Type=Bulk&To=".urlencode(substr($phone_list, 0, -1))."&Mask=".urlencode($this->sendname)."&Message=Hello%20World";
//echo $url;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$curl_scraped_page = curl_exec($ch);
curl_close($ch);
// now reset count back to zero
$count = 0;
// and reset phone_list
$phone_list = '';
}
}
// if we don't have # of phones evenly divisible by $max then handle any leftovers
if ($count > 0)
{
$url = "http://www.smsgatewaycenter.com/library/send_sms_2.php?UserName=".urlencode($this->param[userid])."&Password=".urlencode($this->param[password])."&Type=Bulk&To=".urlencode(substr($phone_list, 0, -1))."&Mask=".urlencode($this->sendname)."&Message=Hello%20World";
//echo $url;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$curl_scraped_page = curl_exec($ch);
curl_close($ch);
}
I notice that you are retrieving the information in $curl_scraped_page. In either of these scenarios above, you will need to account for the new loop if you're doing any processing on $curl_scraped_page.
Again, please consider switching to mysqli or PDO, and keep in mind that there are likely more efficient and flexible ways to achieve this than what you are doing here. For example, you might want to log successful sends in case your script breaks and incorporate that into your script (for example, by selecting from the database only those numbers that have not yet received this text). This would allow you to re-run your script but only send to those who did NOT yet receive the text, rather than hitting everyone again (or maybe your SMS gateway handles that for you?)
EDIT
Another approach would be to load all the retrieved numbers into a single array, then chunk the array into pieces and process each chunk.
$numbers = array();
while ($rowRestore = mysql_fetch_array($resultRestore))
{
$numbers[] = $rowRestore['recphone'];
}
// split into chunks of 10,000
$chunks = array_chunk($numbers, 10000);
// loop and process the chunks
foreach ($chunks AS $chunk)
{
// $chunk will be an array, so implode it with comma to get the phone list
$phone_list = implode(',', $chunk);
// note that there is no longer a need to substr -1 the $phone_list because it won't have a trailing comma using implode()
$url = "http://www.smsgatewaycenter.com/library/send_sms_2.php?UserName=".urlencode($this->param[userid])."&Password=".urlencode($this->param[password])."&Type=Bulk&To=".urlencode($phone_list)."&Mask=".urlencode($this->sendname)."&Message=Hello%20World";
//echo $url;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$curl_scraped_page = curl_exec($ch);
curl_close($ch);
}
I know you may ask why I don't try to google the solution first, now I can say that I already googled for it, unfortunately it come out too many solutions and different ways to do that.
My situation is like this, I want to allow those clients to be able to subscribe my service annually.
From this link, they suggested too much solution, I don't know which 1 is fit to my situation. And of course, I want to use the free service (direct debit need monthly fee).
Which mean that, I want to store the transaction# into my db every year when the service subscribed by my client is expired, and it automatically send an acknowledgement email to clients and my company's email.
In summary,
Which way is suitable to my situation.
Is cron job need in this case? or just need to use recurring payment that provided by paypal?
Is there any link or example (i.e. coding implementation in sandbox)?
Thanks in advanced.
You could use PayPal Payments Pro with the Direct Payment API to process the initial credit card transactions. Then you can store the transaction in your system, and set your system to run a cron job and perform a reference transaction API call to charge the buyer again. This will give you the effects of setting up a recurring payment profile without actually having the service through PayPal.
However, if you prefer to do less coding and setting up your system to perform cron jobs and etc, then you could just sign up for PayPal's recurring payments/recurring billing services, which would allow you to just make an API call to PayPal to set up a profile. Then PayPal will take of billing your buyers when they should be billed.
HI I have made code for ZF
public function processPaymentAction()
{
$methodName = 'CreateRecurringPaymentsProfile';
// from nvpHeader function
$API_Endpoint = 'https://api-3t.sandbox.paypal.com/nvp';
$version = '65.2';
// But you can use here your own Sandbox API credentials of Business account
// and you can get through Payapl Sandbox API Credentials Link on Left.
$API_UserName = 'platfo_1255077030_biz_api1.gmail.com';
$API_Password = '1255077037';
$API_Signature = 'Abg0gYcQyxQvnf2HDJkKtA-p6pqhA1k-KTYE0Gcy1diujFio4io5Vqjf';
$subject = '';
global $nvp_Header, $AUTH_token, $AUTH_signature, $AUTH_timestamp;
$nvpHeaderStr = "";
//pr($this->data);die;
//$this->data['User']['paymentType']
$paymentType = urlencode('Sale');
$firstName = urlencode("Jaskaran");
$lastName = urlencode("Singh");
$creditCardType = urlencode("Visa");
$creditCardNumber = urlencode("4798720058660243");
$expDateMonth =urlencode(11);
// Month must be padded with leading zero
$padDateMonth = str_pad($expDateMonth, 2, '0', STR_PAD_LEFT);
$expDateYear = urlencode(2015);
$cvv2Number = urlencode(962);
$address1 = urlencode("1 Main St");
$address2 = urlencode("");
$city = urlencode("San Jose");
$state = urlencode("CA");
$zip = urlencode(95131);
$amount = urlencode(1.00);
// $init_amount = urlencode($this->data['User']['pack_price']);
$currencyCode="USD";
$profileDesc = urlencode("Welcome to the world of shopping where you get everything");
$billingPeriod = urlencode("Week");
$billingFrequency = urlencode(4);
$totalBillingCycles = urlencode(0);
################# Commented as we need to define through Admin ##############
$profileStartDateDay = 10;
// Day must be padded with leading zero
$padprofileStartDateDay = str_pad($profileStartDateDay, 2, '0', STR_PAD_LEFT);
$profileStartDateMonth = 02;
// Month must be padded with leading zero
$padprofileStartDateMonth = str_pad($profileStartDateMonth, 2, '0', STR_PAD_LEFT);
$profileStartDateYear = 2015;
$profileStartDate = urlencode($profileStartDateYear . '-' . $padprofileStartDateMonth . '-' . $padprofileStartDateDay . 'T00:00:00Z');
//string from nvpHeader
$nvpHeaderStr = "&PWD=".urlencode($API_Password)."&USER=".urlencode($API_UserName)."&SIGNATURE=".urlencode($API_Signature);
$nvpstr="&AMT=$amount&CREDITCARDTYPE=$creditCardType&ACCT=$creditCardNumber&EXPDATE=". $padDateMonth.$expDateYear."&CVV2=$cvv2Number&FIRSTNAME=$firstName&LASTNAME=$lastName&STREET=$address1&CITY=$city&STATE=$state".
"&ZIP=$zip&COUNTRYCODE=US&CURRENCYCODE=$currencyCode&PROFILESTARTDATE=$profileStartDate&DESC=$profileDesc&BILLINGPERIOD=$billingPeriod&BILLINGFREQUENCY=$billingFrequency&TOTALBILLINGCYCLES=$totalBillingCycles";
$nvpstr = $nvpHeaderStr.$nvpstr;
//check if version is included in $nvpStr else include the version.
if(strlen(str_replace('VERSION=','', strtoupper($nvpstr))) == strlen($nvpstr))
{
$nvpstr = "&VERSION=" . urlencode($version) . $nvpstr;
}
$nvpreq="METHOD=".urlencode($methodName).$nvpstr;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$API_Endpoint);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POST, 1);
//$nvpreq=”METHOD=”.urlencode($methodName).$nvpStr;
//setting the nvpreq as POST FIELD to curl
curl_setopt($ch,CURLOPT_POSTFIELDS,$nvpreq);
//getting response from server
$response = curl_exec($ch);
//convrting NVPResponse to an Associative Array
$nvpResArray=$this->deformatNVP($response);
$nvpReqArray=$this->deformatNVP($nvpreq);
if (curl_errno($ch))
{
echo "cURL Error";
die;
// moving to display page to display curl errors
$_SESSION['curl_error_no']=curl_errno($ch) ;
$_SESSION['curl_error_msg']=curl_error($ch);
//$location = "APIError.php";
//header("Location: $location");
}
else
{
//closing the curl
curl_close($ch);
}
#### Checking error ###
if(!empty($nvpResArray))
{
if($nvpResArray['ACK'] == 'Failure')
{
echo "ERROR : ". $errmsg = $nvpResArray["L_LONGMESSAGE0"];
echo "<pre>";
print_r($nvpResArray);
die;
}
}
// Print this array you will get some necessary info
################ Starting data insert##################
if($nvpResArray['ACK'] == 'Success')
{
echo 'Success';
print_r($nvpResArray);
die;
// save data into tables for Recurring Profile
}
}
############### Function deformatNVP #########
/** This function will take NVPString and convert it to an Associative Array and it will decode the response.
* It is usefull to search for a particular key and displaying arrays.
* #nvpstr is NVPString.
* #nvpArray is Associative Array.
*/
function deformatNVP ($nvpstr)
{
$intial = 0;
$nvpArray = array();
while (strlen($nvpstr)) {
//postion of Key
$keypos = strpos($nvpstr, '=');
//position of value
$valuepos = strpos($nvpstr, '&') ? strpos($nvpstr, '&') : strlen(
$nvpstr);
/*getting the Key and Value values and storing in a Associative Array*/
$keyval = substr($nvpstr, $intial, $keypos);
$valval = substr($nvpstr, $keypos + 1, $valuepos - $keypos - 1);
//decoding the respose
$nvpArray[urldecode($keyval)] = urldecode($valval);
$nvpstr = substr($nvpstr, $valuepos + 1, strlen($nvpstr));
}
return $nvpArray;
}
function formAutorization ($auth_token, $auth_signature, $auth_timestamp)
{
$authString = "token=" . $auth_token . ",signature=" . $auth_signature .
",timestamp=" . $auth_timestamp;
return $authString;
}
I'm looking for a PHP script that can be run as a cron job on my web host. It needs to run through a list of websites and check to make sure that each returns the Http response 200 OK. If a site doesn't return that response, or isn't available, it needs to send off an email to the website admin.
I've since refined this script to check to see if your website/webserver is still up and running. I've improved the error handling slightly and added a comfort email to let you know that the script is running successfully.
The comfort email relies on another file called healthcheck.txt to store some values until the script is run the next time. If it doesn't get automatically created, just create a 0 bytes text file, upload it and set the correct file permissions on it (read/write).
<?php
// set email server parameters
ini_set('sendmail_from', 'server.status#host.example.com' );
ini_set('SMTP', '127.0.0.1' );
ini_set('smtp_port', '25' );
ini_set('allow_url_fopen', true); //enable fopen
// define list of webservers to check
$webservers = array('www.example.com', 'www.example2.com');
function sendemail($subject,$message) // email function using standard php mail
{
$wrapmessage = wordwrap($message,70,"\n",true); // mail function can't support a message more than 70 characters per line
$to = 'you#example.com'; // who to send the emails to
// Headers ensure a properly formatted email
$headers = 'From: server.status#host.example.com' . "\r\n" .
'Reply-To: server.status#host.example.com' . "\r\n" .
'X-Mailer: PHP/' . phpversion();
return mail($to, $subject, $wrapmessage, $headers); //send the email
}
function getresponse($url) //queries a url and provides the header returned and header response
{
$ch = curl_init(); // create cURL handle (ch)
if (!$ch) { // send an email if curl can't initialise
$subject = "Web Server Checking Script Error";
$message = "The web server checking script issued an error when it tried to process ".$url.". Curl did not initialise correctly and issued the error - ".curl_error($ch)." The script has died and not completed any more tasks.";
sendemail($subject,$message);
die();
}
// set some cURL options
$ret = curl_setopt($ch, CURLOPT_URL, "http://".$url."/");
$ret = curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
$ret = curl_setopt($ch, CURLOPT_HEADER, true);
$ret = curl_setopt($ch, CURLOPT_NOBODY, true);
$ret = curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$ret = curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
$ret = curl_setopt($ch, CURLOPT_TIMEOUT, 30);
// execute
$ret = curl_exec($ch);
if (empty($ret)) {
// some kind of an error happened
$subject = "Web Server Checking Script Error";
$message = "The web server checking script issued an error when it tried to process ".$url.". Curl was trying to execute and issued the error - ".curl_error($ch)." Further URLs will be tried.";
sendemail($subject,$message);
curl_close($ch); // close cURL handler
} else {
$info = curl_getinfo($ch); //get header info - output is an array
curl_close($ch); // close cURL handler
if (empty($info['http_code'])) {
$subject = "Web Server Checking Script Error";
$message = "The web server checking script issued an error when it tried to process ".$url."\r\nNo HTTP code was returned";
sendemail($subject,$message);
} else {
// load the HTTP code descriptions
$http_codes = parse_ini_file("/server/path/to/http-response-codes.ini");
// results - code number and description
$result = $info['http_code'] . " " . $http_codes[$info['http_code']];
return $result; // $result contained a code, so return it
}
return None; //$info was empty so return nothing
}
return None; // $ret was empty so return nothing
}
// this bit of code initiates the checking of the web server
foreach ($webservers as $webserver) { //loop through the array of webservers
$status = getresponse($webserver); //get the status of the webserver
if (empty($status)) {
// nothing happens here because if $status is empty, the function returned nothing and an email was already sent.
} else {
if (strstr($status, "200")) { //search for the error code that means everything is ok
// If found, don't do anything, just process the next one
} else {
$timestamp = date("m/d/Y H:i:s a", time()); //get the current date and time
$error = $webserver." - ".$status." status error detected"; //set error message with server and response code
$message = "At - ".$timestamp." - a http response error was detected on ".$webserver.".\r\nInstead of a 200 OK response, the server returned ".$status."\r\nThis requires immediate attention!"; //At what time was an error detected on which server and what was the error message
sendemail($error,$message); //trigger the sendemail function
}
}
}
// Health Check. Comfort email twice a day to show script is actually running.
$healthfile = "/server/path/to/healthcheck.txt"; // path with the name of the file to store array data
$hfsize = filesize($healthfile); // filesize of healthcheck file
$notify = "16:00"; // specify the earliest time in the day to send the email - cron job settings dictate how close you'll get to this
$datenow = date("d-m-Y"); //what is current date as of now
if (file_exists($healthfile) && $hfsize !== 0) { //read contents of array from file if it exists and has data, otherwise create array with some defaults
$valuestor = unserialize(file_get_contents($healthfile));
} else { // file doesn't exist so we'll create an array with some defaults
$valuestor = array("email_sent"=>0, "sent_date"=>$datenow, "iterations"=>0);
}
$i = $valuestor['iterations']; //get the iterations number from the valuestor array
$curdate = strtotime($datenow); //convert current date to seconds for comparison
$stordate = strtotime($valuestor['sent_date']); //convert stored date to seconds
if ($valuestor['email_sent'] == 1) { // has the email already been sent today
if ($curdate == $stordate) { // if it has, is the current date equal to the stored date
$i++; // yes it is, just increment the iterations
} else { // it's a new day, reset the array
$timestamp = date("m/d/Y H:i:s a", time()); //get the current date and time
$subject = "Web Server Checking Script Health Status"; //set email subject line
$message = "Message created: ".$timestamp."\r\nThe Web Server Checking script ran successfully for ".$i." time(s) on the ".$valuestor['sent_date']; //email message
sendemail($subject,$message); //trigger the sendemail function
$valuestor['email_sent'] = 0; // set email sent to false
$valuestor['sent_date'] = $datenow; // set email send date to today
$i = 1; // this is the first time the script has run today, so reset i to 1. It gets written to the array later.
// echo $message;
}
} else { // email has not been sent today
$checktime = strtotime($notify); //convert $notify time (for current date) into seconds since the epoch
if (time() >= $checktime) { // are we at or have we gone past checktime
$i++; // increase the number of script iterations by 1
$timestamp = date("m/d/Y H:i:s a", time()); //get the current date and time
$subject = "Web Server Checking Script Health Status"; //set email subject line
$message = "Message created: ".$timestamp."\r\nThe Web Server Checking script has successfully run and completed ".$i." time(s) today."; //email message
sendemail($subject,$message); //trigger the sendemail function
$valuestor['email_sent'] = 1; // set array to show that email has gone
// echo $message;
} else { // we haven't reached the check time yet
$i++; // just increment the iterations
}
}
$valuestor['iterations'] = $i; // update the array with the iterations number
// save the array to the file again
$fp = fopen($healthfile, 'w+'); // open or create the file, clear its contents and write to it
if (!$fp) { // handle the error with an email if the file won't open
$subject = "Web Server Checking Script Error";
$message = "The web server checking script issued an error when trying to open or create the file ".$healthfile." The script was ended without any new information being stored.";
sendemail($subject,$message);
} else {
fwrite($fp, serialize($valuestor)); // write to the file and serialise the array valuestor
fclose($fp); // close the file connection
}
die(); // make sure that script dies and cron job terminates
?>
I found it took me a while to research a good answer to this question. So for the benefit of the community, here's what I came up with after research on Stackoverflow and other forums.
You need two files for this to work. The PHP script that you execute via cron and a ini file that contains detailed descriptions of what the http response codes mean.
I hope this is of use to others.
server-check.php
<?php
// set email server parameters
ini_set('sendmail_from', 'server.status#host.example.com' );
ini_set('SMTP', '127.0.0.1' );
ini_set('smtp_port', '25' );
// define list of webservers to check
$webservers = array('www.example.com', 'www.example2.com');
function sendemail($subject,$message) // email function using standard php mail
{
$wrapmessage = wordwrap($message,70,"\n",true); // mail function can't support a message more than 70 characters per line
$to = 'you#example.com'; // who to send the emails to
// Headers ensure a properly formatted email
$headers = 'From: server.status#host.example.com' . "\r\n" .
'Reply-To: server.status#host.example.com' . "\r\n" .
'X-Mailer: PHP/' . phpversion();
return mail($to, $subject, $wrapmessage, $headers); //send the email
}
function getresponse($url) //queries a url and provides the header returned and header response
{
$ch = curl_init(); // create cURL handle (ch)
if (!$ch) {
$subject = "Web Server Checking Script Error";
$message = "The web server checking script issued an error when it tried to process ".$url."\r\nCouldn't initialize a cURL handle";
sendemail($subject,$message);
die();
}
// set some cURL options
$ret = curl_setopt($ch, CURLOPT_URL, "http://".$url."/");
$ret = curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
$ret = curl_setopt($ch, CURLOPT_HEADER, true);
$ret = curl_setopt($ch, CURLOPT_NOBODY, true);
$ret = curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$ret = curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
$ret = curl_setopt($ch, CURLOPT_TIMEOUT, 30);
// execute
$ret = curl_exec($ch);
if (empty($ret)) {
// some kind of an error happened
$subject = "Web Server Checking Script Error";
$message = "The web server checking script issued an error when it tried to process ".$url."\r\ncurl_error ".$ch;
sendemail($subject,$message);
curl_close($ch); // close cURL handler
die();
} else {
$info = curl_getinfo($ch);
curl_close($ch); // close cURL handler
if (empty($info['http_code'])) {
$subject = "Web Server Checking Script Error";
$message = "The web server checking script issued an error when it tried to process ".$url."\r\nNo HTTP code was returned";
sendemail($subject,$message);
die();
} else {
// load the HTTP codes
$http_codes = parse_ini_file("/server/path/to/http-response-codes.ini");
// results
$result = $info['http_code'] . " " . $http_codes[$info['http_code']];
}
}
return $result;
}
foreach ($webservers as $webserver) { //loop through the array of webservers
$status = getresponse($webserver); //get the status of the webserver
if (strstr($status, "200")) { //search for the error code that means everythings ok
return None; // Don't do anything, just process the next one
} else {
$timestamp = date("m/d/Y H:i:s a", time()); //get the current date and time
$error = $webserver." - ".$status." status error detected"; //set error message with server and response code
$message = "At - ".$timestamp." - a http response error was detected on ".$webserver.".\r\nInstead of a 200 OK response, the server returned ".$status."\r\nThis requires immediate attention!"; //At what time was an error detected on which server and what was the error message
sendemail($error,$message); //trigger the sendemail function
}
}
?>
http-response-codes.ini
[Informational 1xx]
100="Continue"
101="Switching Protocols"
[Successful 2xx]
200="OK"
201="Created"
202="Accepted"
203="Non-Authoritative Information"
204="No Content"
205="Reset Content"
206="Partial Content"
[Redirection 3xx]
300="Multiple Choices"
301="Moved Permanently"
302="Found"
303="See Other"
304="Not Modified"
305="Use Proxy"
306="(Unused)"
307="Temporary Redirect"
[Client Error 4xx]
400="Bad Request"
401="Unauthorized"
402="Payment Required"
403="Forbidden"
404="Not Found"
405="Method Not Allowed"
406="Not Acceptable"
407="Proxy Authentication Required"
408="Request Timeout"
409="Conflict"
410="Gone"
411="Length Required"
412="Precondition Failed"
413="Request Entity Too Large"
414="Request-URI Too Long"
415="Unsupported Media Type"
416="Requested Range Not Satisfiable"
417="Expectation Failed"
[Server Error 5xx]
500="Internal Server Error"
501="Not Implemented"
502="Bad Gateway"
503="Service Unavailable"
504="Gateway Timeout"
505="HTTP Version Not Supported"