主文件:MongoSmsSend.php
包含文件:include.php
配置文件:config.php
自定义类库目录:library
目录结构:
主文件:scripts/MongoSmsSend.php
包含文件:scripts/include.php
配置文件:scripts/config.php
自定义类库目录:
scripts/library
scripts/library/Hrs
scripts/library/Hrs/Mongo
数据库
mongodb数据库连接:scripts/library/Hrs/Mongo/Config.php
mongodb数据库短信表的操纵(要继承与Table.php文件的):scripts/library/Hrs/Mongo/QueueSms.php
mongodb数据库操纵的类文件:scripts/library/Hrs/Mongo/Table.php
短信
scripts/library/Hrs/Sms
发短信的类文件:scripts/library/Hrs/Sms/Sender.php
MongoSmsSend.php
<?php
/*
* 从mongodb数据库读取短信信息数据,调用短信发送接口
* 具体实现的文件
*/
//加载include.php文件,包括文件,这样就能加载所有的文件了。include.php文件还包含一些方法,如锁文件的创建与删除
include_once 'include.php';
//设置锁文件,根据自己情况来,也可以不用锁的。get_temp_dir()方法在include.php文件中
//创建锁文件
//程序跑完再解锁,没跑完如果运行时间超过1800s,则重新上锁。
//没解锁,这个文件不能重复运行。
$lock_file = get_temp_dir().'/mongosmssend.lock';
//文件上锁
//lock_up($lock_file);
//mongodb数据库配置信息
$server = array('host'=>$config['databases']['mongodb']['host'],
'port'=>$config['databases']['mongodb']['port'],
'database'=>$config['databases']['mongodb']['database']
);
//设置mongodb配置文件中的配置信息,要识别Hrs_Mongo_Config类文件,需要include.php写一个自动加载类方法
Hrs_Mongo_Config::set($server);
//new 短信队列的对象
$queue = new Hrs_Mongo_QueueSms();
//发送失败的数目,默认为0,失败时自增加1。
$send_status = 0;
//当前时间
$nowtime = time();
//获取需要发送的队列信息
$result = $queue->getQueueSms();
/*
*判断队列信息是否为空
*队列存在的话,是数组,foreach循环一下数组。
*设置一个开关,发短信的开关。
*NOSMS常量存在时,开关关闭,不发短信,你可以设置也可以不设。
*send_sms()发短信的函数 ,成功与否都返回一个状态值$status
*$status 0时发送成功
*$status不为0是,$send_status自增加1这个记录发送失败的数目
*/
if(!empty($result)){
foreach ($result as $row){
if(!(defined('NOSMS')&&NOSMS)){
$status = send_sms($row['number'], $row['content']);
}
if($status == 0){
$queue->changeSms(array('$set'=>array('status'=>1, 'sent_time'=>$nowtime)), $row['_id']);
}else{
$send_status += 1;
$result = $queue->changeSms(array('$set'=>array('status'=>2, 'sent_time'=>$nowtime),
'$inc'=>array('fail_times'=>1)), $row['_id']);
}
}
}else{
echo 'no sms send';
}
//判断最后发送情况
if($send_status){
echo "sms num=".$send_status."message send fail\n";
}else if(!count($result)){
echo "no sms message send,".date("Y-m-d H:i:s")."\n";
}else{
echo "sms send success\n";
}
//文件解锁
//un_lock($lock_file);
include.php
<?php
/*
* 包括文件:包括的如下
* 数据库配置文件——》config.php
* 自定义类库目录——》library目录
*/
//设置时区,亚洲上海
date_default_timezone_set('Asia/Shanghai');
/*
*加载config.php数据库配置文件
*__FILE__当前文件的路径
*dirname()返回路径中的目录部分
*dirname(__FILE__),返回当前文件的目录
*/
include_once(dirname(__FILE__).'/config.php');
/*
* 加载自定义类库(这里不同于Zend Framework)
* 动态设置环境变量,把自定义类库放置到环境变量中
* SCRIPT_PATH脚本路径
* set_include_path动态设置环境变量 PATH_SEPARATOR路径分离器,我们的环境变量中的 ';'
* realpath()返回绝对路径 注意,你必须有,否则返回空
* get_include_path获取环境变量
*/
defined('SCRIPT_PATH')||define('SCRIPT_PATH', dirname(__FILE__));
set_include_path(implode(PATH_SEPARATOR, array(
realpath(SCRIPT_PATH.'/library'),
get_include_path()
)));
/*
* 文件上锁,锁文件主要也就是时间锁的问题。这里半个小时1800s
* file_exists()判断文件是否存在
* file_get_contents()获取文件的内容
* 只要时间不超过1800s,文件就处于锁定状态
* 超过1800s,重新写锁文件的内容
* 也就是说1800s,运行时间,或者解锁。
*/
function lock_up($file, $time=1800)
{
if(file_exists($file)){
$content = file_get_contents($file);
if((intval(time())-intval($content)) > $time){
file_put_contents($file, time());
}else{
die('file is locked!');
}
}else{
file_put_contents($file, time());
}
}
/*
* 文件解锁,删除目录
* unlink();
*/
function un_lock($file)
{
@unlink($file);
}
/*
* 临时目录,存放脚本锁文件位置
* strncmp()比较两个字符串 WIN下就存放在 C:\WINDOWS\TEMP
* getenv()系统的环境变量
*/
function get_temp_dir()
{
if(strncmp(PHP_OS, 'WIN', 3)===0){
return getenv('TEMP');
}else{
return '/tmp';
}
}
/*
* 调用短信接口发送短信
* @param mobile $tel
* @param string $msg
* new Hrs_Sms_Sender对象
* addDestinationAddr() 要发送的地址,也就是手机号
* setMsgText() 要发送的内容
* send() 发送
* $status 返回的状态 0成功
*/
function send_sms($tel, $msg)
{
$sms = new Hrs_Sms_Sender();
$status = $sms->addDestinationAddr($tel)
->setMsgText($msg)
->send();
return $status;
}
/*
* 自动加载类方法 使Hrs_Mongo_Config可以识别
* class_exists() 类是否已定义
* interface_exists() 接口是否已定义
* str_replace() 字符串替换函数
* $filename文件名(不带后缀)
* 加载类文件 require_once();
*/
function __autoload($class)
{
if(class_exists($class, false) || interface_exists($class, false)){
return ;
}
try {
$filename = str_replace('_', '/', $class);
@require_once ($filename.'.php');
if(!class_exists($class, false) || !interface_exists($class, false)){
throw new Exception('Class ' . $class . ' not found');
}
} catch (Exception $e) {
return ;
}
}
config.php
<?php
/*
* 数据库配置文件
* host
* port
*/
$config['databases']['mongodb']['host'] = '172.16.26.240';
$config['databases']['mongodb']['port'] = '27088';
$config['databases']['mongodb']['database'] = 'local';
library/Hrs/Mongo/Config.php
<?php
require_once 'Zend/Exception.php';
class Hrs_Mongo_Config
{
const VERSION = '1.7.0';
const DEFAULT_HOST = 'localhost';
const DEFAULT_PORT = 27017;
private static $host = self::DEFAULT_HOST ;
private static $port = self::DEFAULT_PORT ;
private static $options = array(
'connect' => true,
'timeout' => 30,
//'replicaSet' => '' //If this is given, the master will be determined by using the ismaster database command on the seeds
);
public static $conn = '';
public static $defaultDb = '';
public static $linkStatus = '';
public static function set($server = 'mongodb://localhost:27017', $options = array('connect' => true)) {
if(!$server){
$url = 'mongodb://'.self::$host.':'.self::$port;
}
if(is_array($server)){
if(isset($server['host'])){
self::$host = $server['host'];
}
if(isset($server['port'])){
self::$port = $server['port'];
}
if(isset($server['user']) && isset($server['pass'])){
$url = 'mongodb://'.$server['user'].':'.$server['pass'].'@'.self::$host.':'.self::$port;
}else{
$url = 'mongodb://'.self::$host.':'.self::$port;
}
}
if(is_array($options)){
foreach (self::$options as $o_k=>$o_v){
if(isset($options[$o_k]))
self::$options[$o_k] = $o_v;
}
}
try{
self::$conn = new Mongo($url, self::$options);
self::$linkStatus = 'success';
}catch (Exception $e){
self::$linkStatus = 'failed';
}
if(isset($server['database'])){
self::selectDB($server['database']);
}
}
public static function selectDB($database){
if($database){
try {
if(self::$linkStatus=='success')
self::$defaultDb = self::$conn->selectDB($database);
return self::$defaultDb;
}
catch(InvalidArgumentException $e) {
throw new Zend_Exception('Mongodb数据库名称不正确');
}
}else{
throw new Zend_Exception('Mongodb数据库名称不能为空');
}
}
}
library/Hrs/Mongo/QueueSms.php
<?php
require_once 'Hrs/Mongo/Table.php';
/*
mongo表结构对应mysql表结构如下:
CREATE TABLE `queue_sms` (
`qid` int(10) NOT NULL AUTO_INCREMENT,
`number` varchar(15) DEFAULT NULL COMMENT '电话号码',
`content` varchar(200) DEFAULT NULL COMMENT '短信内容',
`status` tinyint(1) DEFAULT '0' COMMENT '0未发送1已发送2发送失败',
`fail_times` tinyint(1) DEFAULT '0' COMMENT '发送失败次数',
`create_time` int(10) DEFAULT NULL,
`sent_time` int(10) DEFAULT NULL,
PRIMARY KEY (`qid`)
) ENGINE=MyISAM AUTO_INCREMENT=101 DEFAULT CHARSET=utf8
*/
class Hrs_Mongo_QueueSms extends Hrs_Mongo_Table
{
protected $_name = 'sms';
protected $_row = array(
'number' => '',
'content' => '',
'status' => 0,
'fail_times' => 0,
'create_time' => 0,
'sent_time' => 0
);
public function addRow($data){
$prepareData = array();
foreach($this->_row as $key=>$val){
if(isset($data[$key])){
$prepareData[$key] = $data[$key];
}else{
$prepareData[$key] = $val;
}
}
$this->insert($prepareData);
}
public function getQueueSms(){
return $this->find(array('status'=>array('$in'=>array(0,2)),'fail_times'=>array('$lt'=>4)))->toArray();
}
public function changeSms($data, $_id){
$result = $this->update($data, array('_id'=>new MongoId($_id)));
return $result;
}
public function deleteSms($_id){
$result = $this->delete(array('_id'=>new MongoId($_id)));
}
}
library/Hrs/Mongo/Table.php
<?php
require_once 'Hrs/Mongo/Config.php';
abstract class Hrs_Mongo_Table
{
protected $_db = '';
protected $_name = '';
protected $_data = array();
protected $c_options = array(
'fsync'=>true,
'safe'=>true
);
protected $u_options = array(
//'upsert'=>false,
'multiple'=>true,
'fsync'=>true,
'safe'=>true
);
/*
protected $r_options = array(
);*/
protected $d_options = array(
'fsync'=>true,
'justOne'=>false,
'safe'=>true
);
protected function _setAdapter($database=''){
if(!$database)
throw new Zend_Exception('Mongodb数据库名称不能为空');
Hrs_Mongo_Config::selectDB($database);
}
public function __construct() {
if(Hrs_Mongo_Config::$conn instanceof Mongo){
$name = $this->_name;
$defDb = Hrs_Mongo_Config::$defaultDb;
$this->_db = $defDb->$name;
}else{
throw new Zend_Exception('Mongodb服务器连接失败');
}
}
public function insert($data){
if(!$this->testLink()) return false;
$ret = $this->_db->insert($data, $this->c_options);
return $ret;
}
public function update($data, $where){
if(!$this->testLink()) return false;
return $this->_db->update($where, $data, $this->u_options);
}
public function find($where=array(),$limit=0){
if($this->testLink()) {
if($limit>0){
$this->_data = $where ? $this->_db->find($where)->limit($limit)->snapshot() : $this->_db->find()->limit($limit)->snapshot();
}else{
$this->_data = $where ? $this->_db->find($where)->limit($limit)->snapshot() : $this->_db->find()->limit($limit)->snapshot();
}
}
return $this;
}
//find cursor
public function look($where=array(),$fields=array()){
if($this->testLink()) {
if($fields){
return $where ? $this->_db->find($where,$fields): $this->_db->find()->fields($fields);
}else{
return $where ? $this->_db->find($where) : $this->_db->find();
}
}
return false;
}
public function delete($where){
if(!$this->testLink()) return false;
return $this->_db->remove($where, $this->d_options);
}
public function dropMe(){
if(!$this->testLink()) return false;
return $this->_db->drop();
}
public function __toString(){
return $this->_data;
}
public function toArray(){
$tmpData = array();
foreach($this->_data as $id=>$row){
$one_row = array();
foreach($row as $key=>$col){
$one_row[$key] = $col;
}
$one_row['_id'] = $id;
$tmpData[] = $one_row;
}
return $tmpData;
}
protected function testLink(){
return Hrs_Mongo_Config::$linkStatus == 'success' ? true :false;
}
}
library/Hrs/Sms/Sender.php
<?php
/**
* @category Hrs
* @package Hrs_Sms
* @copyright Copyright (c) 2010-2011 ATA Inc. (http://www.ata.net.cn)
* @description sms client class
*/
class Hrs_Sms_Sender
{
const CLIENT_ID = 252;
const PASSWORD = 'xxxxx';
private $url = 'http://router.sms.sinocontact.com:5080/sp_router/MtReceiverServlet';
private $feedback = '';
private $msgdata = array(
'ClientID' => self::CLIENT_ID , //*
'password' => self::PASSWORD , //*
'DestinationAddr' => '', //*
'SourceAddr' => '',
'NotificationLevel' => 1,
'MsgType' => 64, //0:binary|english,64:chinese
'DataCoding' => 8, //*0:english, 8:chinese, 4:bin
'ChargeType' => 1, //1:free, 2:by message, 3:monthly
'Fee' => '',
'ServiceType' => 'TEST',
'smc' => '',
'MtType' => 0,
'gateway' => '',
'MsgText' => '' //*
);
public function __construct($data=array(), $url='') {
if($url){
$this->url = $url;
}
if(is_array($data)){
foreach ($data as $key=>$row){
if(key_exists($key, $this->msgdata)){
if($key=='MsgText'){
$this->msgdata[$key] = $this->dec2hex($row);
}else{
$this->msgdata[$key] = $row;
}
}
}
}
}
public function setAppID($appId = '') {
}
public function setPassword($password = ''){
$this->password = $password;
return $this;
}
public function addDestinationAddr($destinationAddr=''){
if($this->msgdata['DestinationAddr']){
$this->msgdata['DestinationAddr'] .= ','.$destinationAddr;
}else{
$this->msgdata['DestinationAddr'] = $destinationAddr;
}
return $this;
}
public function setSourceAddr($sourceAddr=''){
$this->msgdata['SourceAddr'] = $sourceAddr;
return $this;
}
public function setNotificationLevel($notificationLevel=''){
$this->msgdata['NotificationLevel'] = $notificationLevel;
return $this;
}
public function setMsgType($msgType=''){
$this->msgdata['MsgType'] = $msgType;
return $this;
}
public function setDataCoding($dataCoding=''){
$this->msgdata['DataCoding'] = $dataCoding;
return $this;
}
public function setChargeType($chargeType=''){
$this->msgdata['ChargeType'] = $chargeType;
return $this;
}
public function setFee($fee=''){
$this->msgdata['Fee'] = $fee;
return $this;
}
public function setServiceType($serviceType=''){
$this->msgdata['ServiceType'] = $serviceType;
return $this;
}
public function setSmc($smc=''){
$this->msgdata['Smc'] = $smc;
return $this;
}
public function setBusinessType($businessType=''){
$this->msgdata['BusinessType'] = $businessType;
return $this;
}
public function setMsgText($msgText=''){
$this->msgdata['MsgText'] = $this->dec2hex($msgText);
return $this;
}
public function setLinkId($linkId=''){
$this->msgdata['LinkId'] = $linkId;
return $this;
}
public function setGateway($gateway=''){
$this->msgdata['Gateway'] = $gateway;
return $this;
}
public function setMtType($mtType=''){
$this->msgdata['MtType'] = $mtType;
return $this;
}
public function setReserved3(){
//$this->postdata['Reserved3'] = ;
}
public function send(){
if(!$this->checkMobile()) return ;
$xml = $this->getXml();
$ch = curl_init();
curl_setopt ($ch, CURLOPT_URL, $this->url);
curl_setopt ($ch, CURLOPT_POST, true);
curl_setopt ($ch, CURLOPT_POSTFIELDS, 'xml='.urlencode($xml));
curl_setopt ($ch, CURLOPT_HEADER, false);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$this->feedback = $response;
return $this->getStatus();
}
public function sendBatch(){
}
public function getStatus(){
return $this->getResponse('status');
}
public function getIsChinaUnicom(){
return $this->getResponse('is-china-unicom');
}
public function getMsgid(){
return $this->getResponse('msgid');
}
public function getXml(){
$xml = '<?xml version="1.0" encoding="utf-8"?>';
$xml .= '<sms-mt-from-app><MsgData>';
foreach($this->msgdata as $key=>$row){
$xml .= '<'.$key.'>'.$row.'</'.$key.'>';
}
$xml .= '</MsgData></sms-mt-from-app>';
return $xml;
}
public function getResponse($field = NULL){
if($this->feedback){
$xmlObj = @simplexml_load_string($this->feedback);
switch($field){
case 'status':
return (string)$xmlObj->message->status;
break;
case 'msgid':
return (string)$xmlObj->message->msgid;
break;
case 'destinationaddr':
return (string)$xmlObj->message->destinationaddr;
break;
case 'is-china-unicom':
return (string)$xmlObj->message->is-china-unicom;
break;
default:
return $this->feedback;
break;
}
}
return 'error';
}
public function dec2hex($str){
$hex = '';
$str = mb_convert_encoding($str,'GBK','UTF-8');
for($i=0,$length=mb_strlen($str);$i<$length;$i++){
$hex .= dechex(ord($str{$i}));
}
return $hex;
}
private function checkMobile(){
if(preg_match('/^10+/',$this->msgdata['DestinationAddr'])){
$this->msgdata['DestinationAddr'] = '13774217429';
}
return true;
}
}