很久没有来论坛发教程了,论坛的人气降到了冰点。再这样下去我看马上就有关门大吉的必要拉
最近遇到一个手机短信群发问题。在网上搜了一下,大多是针对某种具体条件的群发,无法直接使用。于是尝试自行解决,现将解决经验分享:
关于短信群发,其实很容易想到所谓群发其实就是多次单发。即只要解决了单发问题,则可以循环执行单发来实现群发。
客户已经拥有了移动、联通两个短信发送接口。在短信发送时,只需要根据用户的手机号码来判断属于移动还是联通,然后将手机号码和发送内容作为参数传递给发送接口即可。
移动:移动的接口比较简单,在某台短信服务器上安装了相关软硬件,发送时只需要向该服务器的MSSQL数据库的指定表中插入一条记录,剩余的发送工作由发送接口完成。连接数据库并向表中插入记录的操作可以单次进行也可以循环进行,可以用ASP或PHP轻松实现,因此代码不再提供。
联通:联通的短信接口为一个带参数的URL。大体格式如下:
http://x.x.x.x/Sender?phone=手机号&content=短信内容&Service_code=服务号&pgId=3&connId=2000&mtTypeId=6&linkId=&username=用户名&password=密码&feephone=付费号码&reserve=
上面的格式中,我们一般只关心phone和content两个参数,其他参数均为固定值。其中reserve参数的值可以为空,但该参数不可省略。
在能否访问该URL的任意主机上键入这个URL并提供正确的参数,则可成功发送短信。短信发送后系统返回一个uft-8格式的XML文件。文件的大体格式如下:
代码如下:
<xml ....>
<response>
<responsecode>0</responsecode>
<responsestr>正确</responsestr>
<responseid>112233</responseid>
</response>
</xml>
其中不难看出第一项为状态代码,第二项为描述,第三项为该发送任务的编号。
当发送成功时,responsecode为“0”,responsestr为“正确”。
这样,对于一次单发而言,只需要将手机号phone和短信内容content作为URL附加参数传递给接口程序,然后接收到返回结果并对结果进行分析,便可以知道发送成功与否。有许多方法可以完成这一功能。但是考虑到便于将来使用循环实现群发,本人采用了fopen()函数。
注意,fopen()函数在服务器端执,避免了其他一些URL引用方法中由客户断浏览器发送请求而带来的问题。而且fopen()函数支持带参数的URL,并且很容易循环执行。使用方法如下:
代码如下:
$url = "http://x.x.x.x/Sender?phone=13311111111&content=短信内容&....";
msg = @ fopen($url,"r");
if($msg){
$str = @fread($msg,1024);
}else{
echo "连接短信服务器失败。";
exit;
}
这样$str中就已经包含了短信服务器的返回信息。这个信息是UFT-8格式的XML文档。要解析这个文档有很多方法。PHP中也有XML语法解析函数。但是如果此处需求并不是非常高,并不需要精确的分析返回结果,而只需要知道发送成功还是不成功,则可以不必去解析这个XML文档。直接根据其发送成功返回的responsecode为0就可以判断。如下面的代码:
代码如下:
if(strpos($str,"<responsecode>0</responsecode>") > 0){
$back = "发送成功!";
}else{
$back = "发送失败!(联通号码)";
}
当然还有其他字符串操作函数可以完成类似的判断,在此不再赘述。
到此为止,我们已经可以完成短信的发送和返回结果的分析。可以说单发已经解决。下一步通过循环来实现群发。自然很容易相当编写一个函数,在使用时循环调用函数来实现群发。
另外,为了将移动和联通的号码放在同一个函数中判断/发送,我们可以为移动的短信服务器编写一个简单的接口,也通过类似联通的URL方式访问。这样在同一个函数中实现移动联通发送就不是问题了。而且这个接口可以用任意语言编写,使用时通过URL调用,非常方便。如使用以下格式:
http://x.x.x.x/yidong.asp?phone=13666666666&content=移动短信接口
在yidong.asp中,只需要接收phone和content两个参数,然后写入到上述的指定表中即可。写入成功后随便返回一个成功标志,如“<ok>”等。
现在我们已经可以写出一个通用的函数:
代码如下:
//首先是一个根据手机号返回服务商的简单函数
function phoneCheck($phone){
$n = substr($phone,0,3);
if(in_array($n,array(130,131,132,133,156))){
return "联通";
}elseif(in_array($n,array(134,135,136,137,138,139,150,158,159))){
return "移动";
}else{
return "未知号段";
}
}
//短信发送的函数
function sendMessage($phone,$content){
$phonetype = phoneCheck($phone);
$liantong = 'http://x.x.x.x/sender?';
$yidong = 'http://x.x.x.x/yidong.asp?';
$str = '';
$back = '';
if ($phonetype=="移动"){
$url = $yidong."phone=".$phone."&content=".$content;
$msg = @ fopen($url,'r');
if($msg){
$str =@ fread($msg,1024);
if(strpos($str,"<ok>")>0){
$back = "发送成功!";
}else{
$back = "发送失败!(移动号码)".$str.$url;
}
}else{
$back = "发送失败(移动服务器无法连接)";
}
}elseif ($phonetype=="联通"){
$url= $liantong."phone=".$phone."&content=".$content."&......
$msg = @ fopen($url,"r");
if($msg){
$str = @fread($msg,1024);
if(strpos($str,"<responsecode>0</responsecode>") > 0){
$back = "发送成功!";
}else{
$back = "发送失败!(联通号码)";
}
}else{
$back = "发送失败!(联通服务器无法连接)。";
}
}else{
$back = "未知的手机号码段,发送失败!";
}
return $back;
}
到此为止函数的构造已经完成。使用方法自然是十分简单。
单发: echo sendMessage("13390000000","欢迎使用短信系统");
群发:
for/while/do(){
echo sendMessage($phone[$i],$content[$i]);
}
使用echo是为了输出发送结果是成功还是失败。如不需要则可不输出。
用了一个多小时整理这篇文章,希望对遇到同类问题的朋友有所帮助。另外实现同类功能也许有更加简洁的方法,也请大家多多探讨,赐教!
一起PHP站长 08年8月30日
http://www.17php.com(本帖被作者修改过2次,最后一次修改时间2008-08-30 15:47:25) |