I am trying to make sms sending functions in php but it not works from my ends error = env function I can use file_get_contents but this is not good idea to achieve this. I want to learn through bugs and mistakes. So stackoverflow is best for me as I believe.
Please now let me know how I make this correct.
Where I am doing mistake please correct me.
Thank you very much.
function sendMessage($route, $sender, $mobile, $message) {
$message = urlencode($message);
$url = sprintf("https://www.sms4india.com/send_sms?api_token=%s&route=%s&senderid=%s&number=%s&message=%s",
env('MY_API_HERE'), $route, $sender, $mobile, $message);
return $output;
}
sendMessage('4', 'WHTSAP', 'MOBILE_NO', 'HELLO WORLD');
Related
Let me explain, I am doing something like a webservice in which I get information from a platform called Wialon, they use a section called repeaters where they send me a SOAP request to a specific address, I will be honest I have no idea how to use SOAP i never did something like this, so my question is how can i receive that SOAP data in PHP, so I can see it, I want to receive that SOAP request and i don't know save it in DB to see how it works or the structure, because these guys of wialon do not give information about what they send in that soap but I imagine it is an xml, so far I have tried to investigate but the truth is I do not know how soap works, im using this code that I found:
class MyClass {
public function helloWorld() {
require_once 'com.sine.controlador/Controlador.php';
$c = new Controlador();
$xml = $c->insertarResultado('06',func_get_args());
return 'Hello Welt ' . print_r(func_get_args(), true);
}
}
try {
$server = new SOAPServer(
NULL, array(
'uri' => 'http://localhost/WebserviceGLMS2/index.php'
)
);
$server->setClass('MyClass');
$server->handle();
} catch (SOAPFault $f) {
print $f->faultstring;
}
but it doesn't seem to work, hope you can help me, thanks
A soap request is nothing else than a xml post request. In PHP you can get the whole request body with the following code.
<?php
$content = file_get_contents('php://input');
var_dump($content);
You can use this unless it 's not multipart/formdata.
Hello Community
I am trying to replace text in email templates using data from database.
This is my code where %<$receiver>% works and %<$sender>% doesnt.
If you have any knowledge what im doing wrong or hints what i should change i would appreciate it.
public static function getRowValue($type, $receiver, $sender, $job) {
$model = self::where('type', $type)->where('status', DEFAULT_TRUE)->first();
if ($model) {
$subject = $model->subject;
$page = "admin.templates.email.email";
$email = $receiver->email;
$model->content = html_entity_decode($model->content, ENT_COMPAT, 'UTF-8');
$sender_replaced = ($sender) ? str_replace('%<$sender>%',$sender->name, $model->content) : $model->content;
$receiver_replaced = ($receiver) ? str_replace('%<$receiver>%',$receiver->name,$sender_replaced) : $sender_replaced;
$job_replaced = ($job) ? str_replace('%<$job>%',$job->name,$receiver_replaced) : $receiver_replaced;
$message = $job_replaced;
$email_data = [];
$email_data['message'] = $message;
Helper::send_email($page,$subject,$email,$email_data);
return $model->message;
}
return "";
}
If you need additional informations please feel free to ask, hope my example will help someone else who is having hard time solving this issue.
<?= $email_data['message'] ?: "NO MESSAGE" ?></span></p>
Line how i call data in email template.
There was nothing wrong with this part of code, ive missed data flow logic in controllers where i was pulling out $sender and it hasnt been accepted by user.
I have to change data flow logic now to make it work.
Thanks all on help.
I have PHP's mail() using ssmtp which doesn't have a queue/spool, and is synchronous with AWS SES.
I heard I could use SwiftMail to provide a spool, but I couldn't work out a simple recipe to use it like I do currently with mail().
I want the least amount of code to provide asynchronous mail. I don't care if the email fails to send, but it would be nice to have a log.
Any simple tips or tricks? Short of running a full blown mail server? I was thinking a sendmail wrapper might be the answer but I couldn't work out nohup.
You have a lot of ways to do this, but handling thread is not necessarily the right choice.
register_shutdown_function: the shutdown function is called after the response is sent. It's not really asynchronous, but at least it won't slow down your request. Regarding the implementation, see the example.
Swift pool: using symfony, you can easily use the spool.
Queue: register the mails to be sent in a queue system (could be done with RabbitMQ, MySQL, redis or anything), then run a cron that consume the queue. Could be done with something as simple as a MySQL table with fields like from, to, message, sent (boolean set to true when you have sent the email).
Example with register_shutdown_function
<?php
class MailSpool
{
public static $mails = [];
public static function addMail($subject, $to, $message)
{
self::$mails[] = [ 'subject' => $subject, 'to' => $to, 'message' => $message ];
}
public static function send()
{
foreach(self::$mails as $mail) {
mail($mail['to'], $mail['subject'], $mail['message']);
}
}
}
//In your script you can call anywhere
MailSpool::addMail('Hello', 'contact#example.com', 'Hello from the spool');
register_shutdown_function('MailSpool::send');
exit(); // You need to call this to send the response immediately
php-fpm
You must run php-fpm for fastcgi_finish_request to be available.
echo "I get output instantly";
fastcgi_finish_request(); // Close and flush the connection.
sleep(10); // For illustrative purposes. Delete me.
mail("test#example.org", "lol", "Hi");
It's pretty easy queuing up any arbitrary code to processed after finishing the request to the user:
$post_processing = [];
/* your code */
$email = "test#example.org";
$subject = "lol";
$message = "Hi";
$post_processing[] = function() use ($email, $subject, $message) {
mail($email, $subject, $message);
};
echo "Stuff is going to happen.";
/* end */
fastcgi_finish_request();
foreach($post_processing as $function) {
$function();
}
Hipster background worker
Instantly time-out a curl and let the new request deal with it. I was doing this on shared hosts before it was cool. (it's never cool)
if(!empty($_POST)) {
sleep(10);
mail($_POST['email'], $_POST['subject'], $_POST['message']);
exit(); // Stop so we don't self DDOS.
}
$ch = curl_init("http://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'email' => 'noreply#example.org',
'subject' => 'foo',
'message' => 'bar'
]);
curl_exec($ch);
curl_close($ch);
echo "Expect an email in 10 seconds.";
Use AWS SES with PHPMailer.
This way is very fast (hundreds of messages per second), and there isn't much code required.
$mail = new PHPMailer;
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'ssl://email-smtp.us-west-2.amazonaws.com'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'blah'; // SMTP username
$mail->Password = 'blahblah'; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 443;
Not sure if i interpreted your question correctly but i hope this helps.
Pthreads is your friend :)
This is a sample of how i made in my production application
class AsynchMail extends Thread{
private $_mail_from;
private $_mail_to;
private $_subject;
public function __construct($subject, $mail_to, ...) {
$this->_subject = $subject;
$this->_mail_to = $mail_to;
// ...
}
// ...
// you must redefine run() method, and to execute it we must call start() method
public function run() {
// here put your mail() function
mail($this->_mail_to, ...);
}
}
TEST SCRIPT EXAMPLE
$mail_to_list = array('Shigeru.Miyamoto#nintendo.com', 'Eikichi.Kawasaki#neogeo.com',...);
foreach($mail_to_list as $mail_to) {
$asynchMail = new AsynchMail($mail_to);
$asynchMail->start();
}
Let me know if you need further help for installing and using thread in PHP
For logging system, i strongly advice you to use Log4PHP : powerful and easy to use and to configure
For sending mails, i also strongly advice you to use PHPMailer
I'm using asynchronous php execution by using beanstalkd.
It is a simple message queue, really lightweight and easy to integrate.
Using the following php wrapper for php https://github.com/pda/pheanstalk
you can do something as follows to implement a email worker:
use Beanstalk\Client;
$msg="dest_email##email_subject##from_email##email_body";
$beanstalk = new Client();
$beanstalk->connect();
$beanstalk->useTube('flux'); // Begin to use tube `'flux'`.
$beanstalk->put(
23, // Give the job a priority of 23.
0, // Do not wait to put job into the ready queue.
60, // Give the job 1 minute to run.
$msg // job body
);
$beanstalk->disconnect();
Then the job would be done in a code placed into a separate php file.
Something like:
use Beanstalk\Client;
$do=true;
try {
$beanstalk = new Client();
$beanstalk->connect();
$beanstalk->watch('flux');
} catch (Exception $e ) {
echo $e->getMessage();
echo $e->getTraceAsString();
$do = false;
}
while ($do) {
$job = $beanstalk->reserve(); // Block until job is available.
$emailParts = explode("##", $job['body'] );
// Use your SendMail function here
if ($i_am_ok) {
$beanstalk->delete($job['id']);
} else {
$beanstalk->bury($job['id'], 20);
}
}
$beanstalk->disconnect();
You can run separately this php file, as an independent php process. Let's say you save it as sender.php, it would be run in Unix as:
php /path/to/sender/sender.php & && disown
This command would run the file and alsow allow you to close the console or logout current user without stopping the process.
Make sure also that your web server uses the same php.ini file as your php command line interpreter. (Might be solved using a link to you favorite php.ini)
I hope it helps.
Your best bet is with a stacking or spooling pattern. It's fairly simple and can be described in 2 steps.
Store your emails in a table with a sent flag on your current thread.
Use cron or ajax to repeatedly call a mail processing php file that will get the top 10 or 20 unsent emails from your database, flag them as sent and actually send them via your favourite mailing method.
An easy way to do it is to call the code which handles your mails asynchronously.
For example if you have a file called email.php with the following code:
// Example array with e-mailaddresses
$emailaddresses = ['example1#test.com', 'example2#example.com', 'example1#example.com'];
// Call your mail function
mailer::sendMail($emailaddresses);
You can then call this asynchronously in a normal request like
exec('nice -n 20 php email.php > /dev/null & echo $!');
And the request will finish without waiting for email.php to finish sending the e-mails. Logging could be added as well in the file that does the e-mails.
Variables can be passed into the exec between the called filename and > /dev/null like
exec('nice -n 20 php email.php '.$var1.' '.$var2.' > /dev/null & echo $!');
Make sure these variables are safe with escapeshellarg(). In the called file these variables can be used with $argv
Welcome to async PHP
https://github.com/shuchkin/react-smtp-client
$loop = \React\EventLoop\Factory::create();
$smtp = new \Shuchkin\ReactSMTP\Client( $loop, 'tls://smtp.google.com:465', 'username#gmail.com','password' );
$smtp->send('username#gmail.com', 'sergey.shuchkin#gmail.com', 'Test ReactPHP mailer', 'Hello, Sergey!')->then(
function() {
echo 'Message sent via Google SMTP'.PHP_EOL;
},
function ( \Exception $ex ) {
echo 'SMTP error '.$ex->getCode().' '.$ex->getMessage().PHP_EOL;
}
);
$loop->run();
I am trying to figure out the best way to send emails from an external template file, at the moment I have a template file that looks like this:
Thank you, your order has been received, someone will review it and process it. No money has been taken from your account.
<?php
echo date('Y-m-d H:i:s');
?>
<pre>
<?php print_r($this->data); ?>
</pre>
And then my send method looks like this:
public function notify($template) {
// get the template from email folder
$path = $_SERVER['DOCUMENT_ROOT'].'templates/email/'.$template.'.php';
if(file_exists($path)) {
ob_start();
require_once($path);
$body = ob_get_contents();
ob_end_clean();
$subject = 'email send';
foreach($this->emailTo as $email)
new Mail($email,$subject,$body);
}
}
This all works fine when I call it like this:
$notifications = new notifications();
$notifications->setData(array('order' => $order->order));
$notifications->addEmail($order->order->email);
$notifications->notify('orderReceived');
However, if I try to make two calls to the "notify" method then the second email is blank, I know this is because the object buffer, but I cannot think of any other way to do it.
Thanks,
Ian
You are using require_once, so the file will only load once. Try require.
Also consider loading a pure text template and use str_replace to replace the variables in the template like this:
$template = "<pre>%DATA%</pre>";
$text = str_replace('%DATA%', $this->data, $template);
I would do this:
Template file
Thank you, your order has been received, someone will review it and process it. No money has been taken from your account.
%s
<pre>
%s
</pre>
Notify function
public function notify($template) {
// get the template from email folder
$path = $_SERVER['DOCUMENT_ROOT'].'templates/email/'.$template.'.php';
if (!file_exists($path)) {
// Return false if the template is missing
return FALSE;
}
// Create the message body and subject
$body = sprintf(file_get_contents($path), date('Y-m-d H:i:s'), print_r($this->data, TRUE));
$subject = 'email send';
// Send the mail(s)
foreach($this->emailTo as $email) {
new Mail($email, $subject, $body);
}
// Return true for success
return TRUE;
}
This will solve the problem - which could be solved anyway by changing require_once to require.
Using require_once means the template file will only be loaded once (clue's in the function name), so the second call will result in a blank body.
Been having major issues trying to solve this issue, I'll be happy to give a +500 bounty to someone who can help me get this work.
Basically, I'm trying to call this web service using Nusoap:
https://www.eway.com.au/gateway/ManagedPaymentService/managedCreditCardPayment.asmx?op=QueryCustomer
This is what I've got so far:
class Eway
{
var $username = 'test#eway.com.au';
var $pw = 'test123';
var $customerId = '87654321';
private function setHeaders($client)
{
$headers = <<<EOT
<eWAYHeader xmlns="http://www.eway.com.au/gateway/managedPayment">
<eWAYCustomerID>$this->customerId</eWAYCustomerID>
<Username>$this->username</Username>
<Password>$this->pw</Password>
</eWAYHeader>
EOT;
$client->setHeaders($headers);
return $client;
}
function getCustomer($ewayId = 9876543211000)
{
$url = 'https://www.eway.com.au/gateway/ManagedPaymentService/managedCreditCardPayment.asmx?WSDL';
$client = new Nusoap_client($url, true);
$this->setHeaders($client);
$args['QueryCustomer'] = array('managedCustomerID'=>$ewayId);
$result = $client->call('QueryCustomer', $args);
print_r($result);
}
}
When I run this code and do $eway->getCustomer() I get the following error:
Array
(
[faultcode] => soap:Client
[faultstring] => eWayCustomerID, Username and Password needs to be specified in the soap header.
)
What am I doing wrong?
If you could fix my class and give me working code which is able to do the QueryCustomer method using the test customer id and return its info, I'll be glad to give you +500 rep and my eternal gratitude. Obviously it'll be 48 hours before I can start the bounty, but I promise that I will do it.
I could be missing the point, but you never actually assign the returned object to $client:
function getCustomer($ewayId = 9876543211000)
{
$url = 'https://www.eway.com.au/gateway/ManagedPaymentService/managedCreditCardPayment.asmx?WSDL';
$client = new Nusoap_client($url, true);
$client = $this->setHeaders($client);
$args['QueryCustomer'] = array('managedCustomerID'=>$ewayId);
$result = $client->call('QueryCustomer', $args);
print_r($result);
}
You could also set $client as a class variable if desired or by sending the parameter as a reference.
Looking at the data, I do not know if this matters, but you are using var for your class variable declarations and then using private for the function. If you are using php5 I would stay away from the var:
private $username = 'test#eway.com.au';
private $pw = 'test123';
private $customerId = '87654321';
Use the private or public or protected (whichever your class requires) instead to keep consistency. I doubt this will solve your problem, just something to be conscious about.
Possible Solution
Ok, doing some digging of my own, figured this out, you need to encase the actual header you add in a SOAP:Header deal. I tested the below and it was working for me, so give it a try:
private function setHeaders($client)
{
$headers = <<<EOT
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/" >
<SOAP:Header>
<eWAYHeader xmlns="http://www.eway.com.au/gateway/managedPayment">
<eWAYCustomerID>$this->customerId</eWAYCustomerID>
<Username>$this->username</Username>
<Password>$this->pw</Password>
</eWAYHeader>
</SOAP:Header>
EOT;
$client->setHeaders($headers);
return $client;
}
It did not return any errors. So yea, it seems that is the likely culprit. (Note I also implemented the $client = $this->setHeaders($client); I mentioned above as well.
And my Final Answer is:
Alright did a bit of digging and found something that works. Not saying it is right, but yea it works.
private function setHeaders($client)
{
$headers = <<<EOT
<eWAYHeader xmlns="https://www.eway.com.au/gateway/managedpayment">
<eWAYCustomerID>$this->customerId</eWAYCustomerID>
<Username>$this->username</Username>
<Password>$this->pw</Password>
</eWAYHeader>
EOT;
$client->setHeaders($headers);
return $client;
}
function getCustomer($ewayId = 123456789012)
{
$url = 'https://www.eway.com.au/gateway/ManagedPaymentService/managedCreditCardPayment.asmx?WSDL';
$client = new nusoap_client($url);
$client = $this->setHeaders($client);
$args['QueryCustomer'] = array('managedCustomerID'=>$ewayId);
$result = $client->call('QueryCustomer', $args, $namespace='https://www.eway.com.au/gateway/managedpayment', $soapAction='https://www.eway.com.au/gateway/managedpayment/QueryCustomer');
print_r($result);
//echo "\n{$client->request}\n"; // This echos out the response you are sending for debugging.
}
It seems the namespace and soapAction were the key ingredients. I found these using the link you originally posted: https://www.eway.com.au/gateway/ManagedPaymentService/managedCreditCardPayment.asmx?op=QueryCustomer
Basically, I just looked at that response, and then did some searching to figure out the soapAction, and then just messed with it until the request being sent matched the page you posted. It returns a failed login, but yea. That generally means something is working, and is probably due to the test data. But that gives you a baseline to go off of.
And the $client->request is a handy debugging tool for the future.
Update 5:
nusoap actually wraps the request with SOAP-ENV, like:
<SOAP-ENV:Header><eWAYHeader xmlns="https://www.eway.com.au/gateway/managedpayment">
<eWayCustomerID>87654321</eWayCustomerID>
<Username>test#eway.com.au</Username>
<Password>test123</Password>
</eWAYHeader></SOAP-ENV:Header>
While in the docs for EWay soap:Header must be used. I couldn't find a mention of the latter in nusoap headers.
Update 4:
This link has a good tip:
Got it. It was a case issue but not
there, and their PDF is incorrect.
For anyone that gets this in the
future, the PDF says:
<eWAYHeader
xmlns="http://www.eway.com.au/gateway/managedPayment">
It should be:
<eWAYHeader
xmlns="https://www.eway.com.au/gateway/managedpayment">
So this right here:
$client->setHeaders($headers);
The SoapClient class doesn't have that method. Instead, you can create a new SoapHeader.
private function setHeaders($client)
{
$headers = new stdClass;
$headers->eWAYCustomerID = $this->customerId;
$headers->Username = $this->username;
$headers->Password = $this->pw;
$ewayHeader = new SoapHeader(
"http://www.eway.com.au/gateway/managedPayment",
"eWAYHeader",
$headers
);
$client->__setSoapHeaders(array($ewayHeader));
return $client;
}
Edit: Alright, digging deeper:
private function prepHeaders()
{
return array(
'eWAYHeader' => array(
'eWAYCustomerID' => $this->customerId,
'Username' => $this->username,
'Password' => $this->pw
)
);
}
function getCustomer($ewayId = 9876543211000)
{
$url = 'https://www.eway.com.au/gateway/ManagedPaymentService/managedCreditCardPayment.asmx?WSDL';
$client = new nusoap_client($url);
$args['QueryCustomer'] = array('managedCustomerID'=>$ewayId);
$result = $client->call('QueryCustomer', $args, null, null, $this->prepHeaders());
print_r($result);
}
What happens if you do that?
I know this is not a full solution to the issue, but although this question is quite old, my findings may help lead to a concrete resolution.
I've been experiencing a similar error in relation to your mention of the HTTP "SOAPAction" header. (I am, however, dealing with a different eWay API than you. I'm dealing with the "Rapid API", which last week was renamed to from "Merchant Hosted Payments", which was part of the reason why my script wasn't working).
To return to the point, I found that if you don't specify the HTTP "SOAPAction" header, eWay returns a SoapFault with the following error message.
"System.Web.Services.Protocols.SoapException: Unable to handle request without a valid action parameter. Please supply a valid soap action."
If you add the HTTP "SOAPAction" header, you get an error no matter what you set it to.
"System.Web.Services.Protocols.SoapException: Server did not recognize the value of HTTP Header SOAPAction: XXX"
I'm also told by a member of eWay's support staff that they have an issues with an internal redirect, which they are now looking into resolving.
<ME> (2012-05-25 02:50:18)
I had an idea of what it could be. What is the "SOAPAction" HTTP header supposed to be set to?
<ME> (2012-05-25 02:52:05)
I couldn't find it in the documentation.
<EWAY_SUPPORT_STAFF> (2012-05-25 02:53:38)
The only thing that is required typically is the endpoint which is https://au.ewaypayments.com/hotpotato/soap.asmx and the <CreateAccessCode xmlns="https://au.ewaypayments.com/hotpotato/">
<EWAY_SUPPORT_STAFF> (2012-05-25 02:54:10)
In my tests it is working but what is happening is that requests are being redirected to the old URL which does not accept the CreateAccessCode method
<ME> (2012-05-25 02:56:58)
You did say that.
<ME> (2012-05-25 02:57:13)
So is this bug happening in the production environment?
<EWAY_SUPPORT_STAFF> (2012-05-25 02:57:57)
Yes it appears so. I have escalated this to Development and attached our last chat transcript and my own test results. They are looking at it now.