<?php
namespace imcat;

// 手机短信接口类
 
class extSms{

    public  
$cfg_mchar 70// 一条信息,文字个数(小灵通65个字)
    
public  $cfg_mtels 200// 一次发送,最多200个手机号码个数
    
    
public  $api       ''//api接口类型(提供商)
    
public  $smsdo     NULL//api对象
    
public  $cfgs      = array(); //api配置
    
    
public  $cnow      = array('name'=>'-','unit'=>'-'); //now配置
    
public  $amap      = array(); //api列表
    
    //function __destory(){  }
    
function __construct(){ 
        require 
DIR_IMCAT."/adpt/smsapi/api_cfgs.php"// 加载
        
$_cfgs glbConfig::read('sms''ex');
        
$api = @$_cfgs['cfg_api'];
        if(
$api && isset($_apis[$api])){ 
            
$this->api $api;
            
$this->cfgs $_cfgs
            
$this->cnow $_apis[$api];
            
$cfile 'sms'.ucfirst($this->api);
            
// 统一实例化一个 api对象 // load sms libs
            
require DIR_IMCAT."/adpt/smsapi/$cfile.php"// 加载
            
$class "\\imcat\\$cfile";
            
$this->smsdo = new $class($_cfgs); 
        }
        
$this->amap $_apis;
    }
    
    
// 短信接口是否关闭
    
function isClosed(){
        if(empty(
$this->api)){
            return 
true;
        }else{
            return 
false;
        } 
//&&$sms_cfg_api!='(close)'
    
}
    
    
// 余额查询
    // 结果说明:array(1,1234.5): 成功,余额为1234.5;array(-1,'失败原因'): 
    
function getBalance(){ 
        return 
$this->smsdo->getBalance();    
    }
    
    
/** 模板短信发送
     * @param    string    $mobiles     手机号码,参考sendSMS()
     * @param    array     $params      参数:array('code'=>'1234','name'=>'peace',)
     * @param    string    $tid         模版id
     * @param    string    $sign        签名
     **/
    
function sendTid($mobiles$tid=''$params=[], $cfgs=[]){ // , $sign='', $limit=1, $pid=''
        
if(!method_exists($this->smsdo'sendTid')){
            return array(-
1"a:{sendTid}不支持!");
        }
        
$sign = empty($cfgs['sign']) ? '' $cfgs['sign'];
        
$pid = empty($cfgs['pid']) ? $cfgs['pid'];
        
$limit = empty($cfgs['limit']) ? $cfgs['limit'];
        
$res $this->smsdo->sendTid($mobiles$params$tid$sign);
        
$tid || $tid '(def)'$sign || $sign '(def)';
        
$this->loger($mobilesjson_encode($params)."(tid=$tid:sign=$sign)"$res$limit$pid); //写记录-db
        
return $res;
    }

    
/** 短信发送,支持短信模版替换,
     * @param    string    $mobiles     手机号码,参考sendSMS()
     * @param    string    $tpl         支持模版,如:{subject}{name}标记
     * @param    array     $source        替换源:array('subject'=>'hellow corp!','name'=>'peace',)
     * @param    string    $type         发送方式/发送身份,参考sendSMS()
     * @return    array    ---        结果数组,参考sendSMS()
     **/
    
function sendTpl($mobiles$tpl$source$cfgs=array()){
        
$tpl str_replace(array("\r\n","\r","\n"),array(' ',' ',' '),$tpl);
        if(
preg_match_all('/{\s*([a-zA-Z_0-9]\w*)\s*}/i'$tpl$matchs)){
            if(!empty(
$matchs[0])){
                foreach(
$matchs[0] as $v){
                    
$k str_replace(array('{','}'), ''$v);
                    
$val = isset($source[$k]) ? $source[$k] : (isset($GLOBALS[$k]) ? $GLOBALS[$k] : "{\$$k}");
                    
$tpl str_replace($v$val$tpl);
                }
            }
        }
        return 
$this->sendSMS($mobiles$tpl5$cfgs);
    }
    
    
/** 短信发送
     * @param    string    $mobiles     手机号码,array/string(英文逗号分开)
     * @param    string    $content     255个字符以内
     * @param    string    $limit       xxx :
     * @return    array    ---        结果数组,如:array(1,'操作成功'): 
     **/
    
function sendSMS($mobiles$content$limit=1$cfgs=array()){
        
$pid = empty($cfgs['pid']) ? '' $cfgs['pid'];
        if(!
method_exists($this->smsdo'sendSMS')){
            return array(-
1"a:{sendSMS}不支持!");
        }
        
// 格式化 $mobiles,$content, 
        
$atel $this->telFormat($mobiles);
        
$amsg $this->msgCount($content);
        if(empty(
$atel)) return array('-2',basLang::show('sms_errtel'));    
        if(empty(
$amsg[0])) return array('-2',basLang::show('sms_errmsg'));
        
$nmsg count($atel)*$amsg[1];
        
// 需扣费计算条数,检查余额
        
$balance $this->smsdo->getBalance(); 
        if((float)
$balance[1]<=0){
            
$mobiles implode(',',$atel);
            
$this->balanceWarn("--tels:$mobiles\n --cmsg:$content"); //写记录
            
return array('-2',basLang::show('sms_charge0'));        
        } 
        if(
$limit && $limit<$nmsg){
            return array(
'-2',basLang::show('sms_charged'));    
        }
        
// 发送及结果
        
if(count($atel)>$this->cfg_mtels){ // 分组发送
            
$groups array_chunk($atel,$this->cfg_mtels);
            
$res = array('-2',basLang::show('sms_msenderr'));
            
$flag false//成功标记
            
foreach($groups as $group){ 
                
$res_temp $this->smsdo->sendSMS($group$content);
                if(
$res_temp[0]=='1'){ //只要一组发送成功,则都算成功.
                    
$res $res_temp;    
                }
            }
        }else{
            
$res $this->smsdo->sendSMS($atel$content);
        }    
        
$this->loger($atel$amsg[0], $res$nmsg$pid); //写记录-db
        
return $res;
    }
    
    
// 写记录-db
    
function loger($tel$msg$res$nmsg=1$pid=''){
        
// 写记录-db
        
$stel is_array($tel) ? implode(',',$tel) : $tel
        if(
strlen($stel)>255$stel substr($stel,0,240).'...'.substr($stel,strlen($stel)-5,255);
        
$data = array( 
            
'kid'=>basKeyid::kidTemp(), 'pid'=>$pid,
            
'tel'=>$stel'msg'=>basReq::in($msg),
            
'res'=>implode(':',$res),'api'=>$this->api,'amount'=>$nmsg,
        );
        
$data $data basSql::logData();
        
glbDBObj::dbObj()->table('plus_smsend')->data($data)->insert();
        
// 扣钱 for 0test_balance.txt
        
if($this->api=='0test' && $res[0]=='1'){
            
$this->smsdo->deductingCharge($nmsg);
        }
    }


    
/** 余额报警检测,余额报警记录
     * @param    int        $flag     int/string数字/
     *                    数字,多少小时被修改(记录了余额不足)过,
     *                    flag=str,记录信息内容
     * @return    NULL    
     **/
    
function balanceWarn($flag){
        global 
$_cbase;
        
$file "debug/balance_apiwarn.wlog"
        
comFiles::chkDirs($file,'dtmp');
        if(
is_numeric($flag)){ //检查文件,多少时间(day)内修改过
            
return extCache::cfGet("/$file",'24h');
        }else{ 
            
$onlineip $_cbase['run']['userip']; $data ''
            if(
file_exists($file)){
                
$data comFiles::get($file);
            }
            
$fp fopen(DIR_VARS."/$file"'a');
            
$data date('Y-m-d H:i:s')."^ ".'mname'." ^ $onlineip \n $flag\r\n\r\n$data";
            
flock($fp2); fwrite($fp$data); fclose($fp);
        }
    }

    
// 电话号码 格式化/过滤
    // 初始的电话号码array/string
    // 格式化并过滤后的电话号码
    
function telFormat($tel){
        if(
is_string($tel)){
            
$tel str_replace(array("-","("," ",')'), ''$tel);
            
$tel str_replace(array("\r\n","\r","\n",';'), ','$tel);
            
$arr explode(',',$tel);
        }else{
            
$arr $tel;    
        }
        
$arr array_filter($arr);
        
$re = array();
        for(
$i=0;$i<count($arr);$i++){
            
//  手机/^1\d{4,10}$/; 95168合法号码/^[1-9]{1}\d{4,10}$/; 0769-12345678小灵通
            
if(preg_match('/^\d{5,12}$/',$arr[$i])) $re[] = $arr[$i];
        }
        return 
$re;    
    }
    
// 短信内容 截取/计数
    // param    string    $msg     初始的短信内容
    // param    int        $slen     最多截取多少文字
    // return    array    $re        返回array(文字,信息条数,文字个数)
    
function msgCount($msg$slen=255){
        global 
$_cbase;
        
$cset $_cbase['sys']['cset'];
        
$cnt mb_strlen($msg$cset);
        if(
$cnt>255){
            
$msg mb_substr($str0250$cset); 
            
$cnt 250;
        }
        if(
$cnt>$this->cfg_mchar){ // >70字
            
$ncnt ceil($cnt/($this->cfg_mchar-3)); //(70-3)个字算一条信息
        
}else{
            
$ncnt 1;
        }
        return array(
$msg,$ncnt,$cnt); 
    }
    
    
// 部分接口有此方法
    
function chargeUp($charge){
        return 
$this->smsdo->chargeUp($charge);
    }

}