<?php
/**
 * 微信通用类
 * @Copyright (C) 2016 汉潮 All rights reserved.
 * @License http://www.hanchao9999.com
 * @Author xiaogg <xiaogg@sina.cn>
 */

namespace Common\Vendor;
class WeixinChat {
	/**
	 * 微信推送过来的数据或响应数据
	 * @var array
	 */
	private $data = array();
	/**
	 * 主动发送的数据
	 * @var array
	 */
	private $send = array();
	/**
	 * 获取微信推送的数据
	 * @return array 转换为数组后的数据
	 */
	public function request() {//file_put_contents('wx.txt',var_export($_GET,1));
		$this->auth() || exit;
		if (IS_GET) {
			exit($_GET['echostr']);
		} else {
			$xml = new \SimpleXMLElement(file_get_contents("php://input"));
			$xml || exit;
			foreach ($xml as $key => $value) {
				$this->data[$key] = strval($value);
			}
		}
		return $this->data;
	}
    public function setData($data){
        if(empty($data) || !is_array($data))return false;
        $this->data=empty($this->data)?$data:array_merge($this->data,$data);
    }
	/**
	 * * 被动响应微信发送的信息（自动回复）
	 * @param  string $to      接收用户名
	 * @param  string $from    发送者用户名
	 * @param  array  $content 回复信息，文本信息为string类型
	 * @param  string $type    消息类型
	 * @param  string $flag    是否新标刚接受到的信息
     * @param  int $auto 是否自动输出
	 * @return string          XML字符串
	 */
	public function response($content, $type = 'text', $flag = 0,$auto=1) {
		/* 基础数据 */
		$this->data = array(
			'ToUserName'	 => $this->data['FromUserName'],
			'FromUserName'	 => $this->data['ToUserName'],
			'CreateTime'	 => NOW_TIME,
			'MsgType'		 => $type,
		);
		/* 添加类型数据 */
		$this->$type($content);
		/* 添加状态 */
		$this->data['FuncFlag'] = $flag;
		/* 转换数据为XML */
		$xml = new \SimpleXMLElement('<xml></xml>');
		$this->data2xml($xml, $this->data);
        //        file_put_contents('uploads/PAYreceive_response_'.time().'.txt',var_export($xml->asXML(),1));
        $xmlstr=$xml->asXML();
        if($auto)exit($xmlstr);
        else return $xmlstr;
	}
	/**
	 * * 主动发送消息
	 *
	 * @param string $content   内容
	 * @param string $openid   	发送者用户名
	 * @param string $type   	类型
	 * @return array 返回的信息
	 */
	public function sendMsg($content, $openid = '', $type = 'text') {
		/* 基础数据 */
		$this->send ['touser'] = $openid;
		$this->send ['msgtype'] = $type;
		/* 添加类型数据 */
		$sendtype = 'send' . $type;
		$this->$sendtype($content);
		/* 发送 */
		$sendjson = json_encode($this->send, JSON_UNESCAPED_UNICODE);
		$restr = $this->send($sendjson);
		return json_decode($restr,true);
	}
	/**
	 * 发送文本消息
	 * 
	 * @param string $content
	 *        	要发送的信息
	 */
	private function sendtext($content) {
		$this->send ['text'] = array(
			'content' => $content
		);
	}
	/**
	 * 发送图片消息
	 * 
	 * @param string $content
	 *        	要发送的信息
	 */
	private function sendimage($content) {
		$this->send ['image'] = array(
			'media_id' => $content
		);
	}
	/**
	 * 发送视频消息
	 * @param  string $video 要发送的信息
	 */
	private function sendvideo($video) {
		list (
				$video ['media_id'],
				$video ['title'],
				$video ['description']
				) = $video;
		$this->send ['video'] = $video;
	}
	/**
	 * 发送语音消息
	 * 
	 * @param string $content
	 *        	要发送的信息
	 */
	private function sendvoice($content) {
		$this->send ['voice'] = array(
			'media_id' => $content
		);
	}
	/**
	 * 发送音乐消息
	 * 
	 * @param string $music
	 *        	要发送的信息
	 */
	private function sendmusic($music) {
		list (
				$music ['title'],
				$music ['description'],
				$music ['musicurl'],
				$music ['hqmusicurl'],
				$music ['thumb_media_id']
				) = $music;
		$this->send ['music'] = $music;
	}
	/**
	 * 发送图文消息
	 * @param  string $news 要回复的图文内容
	 */
	private function sendnews($news) {
		$articles = array();
		foreach ($news as $key => $value) {
			list(
					$articles[$key]['title'],
					$articles[$key]['description'],
					$articles[$key]['url'],
					$articles[$key]['picurl']
					) = $value;
			if ($key >= 9) {
				break;
			} //最多只允许10调新闻
		}
		$this->send['articles'] = $articles;
	}
	/**
	 * * 获取微信用户的基本资料
	 * 
	 * @param string $openid   	发送者用户名
	 * @return array 用户资料
	 */
	public function user($openid = '') {
		if ($openid) {
			header("Content-type: text/html; charset=utf-8");
			if(C('BOUND_STATUS') == 2){
				$wx = new \Common\Vendor\Weixinopen;
        		$harr=$wx->getwxuserinfo($openid);
			}else{
				$url = 'https://api.weixin.qq.com/cgi-bin/user/info';
				$params = array();
				$params ['access_token'] = $this->getToken();
				$params ['openid'] = $openid;
				$httpstr = curlget($url, $params);
				$harr = json_decode($httpstr, true);
                if(empty($harr['nickname']))$harr =$this->getuserinfo($openid);
			}
			return $harr;
		} else {
			return false;
		}
	}
    public function getuserinfo($openid){
        if(empty($openid))return;
        $token=S('wx_'.$openid);
        if(empty($token))return;
        $url = 'https://api.weixin.qq.com/sns/userinfo';
		$params = array();
		$params ['access_token'] =$token['access_token'];
		$params ['openid'] = $openid;
		$httpstr = curlget($url, $params);
		$harr = json_decode($httpstr, true);
        return $harr;
    }
	/**
	 * 生成菜单
	 * @param  string $data 菜单的str
	 * @return string  返回的结果；
	 */
	public function setMenu($data = NULL) {
		$access_token = $this->getToken();
		$url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token={$access_token}";
		$menustr = curlget($url, $data, 'POST', array("Content-type: text/html; charset=utf-8"), true);
		return $menustr;
	}
	/**
	 * 回复文本信息
	 * @param  string $content 要回复的信息
	 */
	private function text($content) {
		$this->data['Content'] = $content;
	}
	/**
	 * 回复音乐信息
	 * @param  string $music 要回复的音乐
	 */
	private function music($music) {
		list(
				$music['title'],
				$music['Description'],
				$music['MusicUrl'],
				$music['HQMusicUrl']
				) = $music;
		$this->data['Music'] = $music;
	}
	/**
	 * 回复图文信息
	 * @param  string $news 要回复的图文内容
	 */
	private function news($news) {
		$articles = array();
		foreach ($news as $key => $value) {
			list(
					$articles[$key]['Title'],
					$articles[$key]['Description'],
					$articles[$key]['PicUrl'],
					$articles[$key]['Url']
					) = $value;
			if ($key >= 9) {
				break;
			} //最多只允许10调新闻
		}
		$this->data['ArticleCount'] = count($articles);
		$this->data['Articles'] = $articles;
	}
	/**
	 * 主动发送的信息
	 * @param  string $data    json数据
	 * @return string          微信返回信息
	 */
	private function send($data = NULL) {
		$access_token = $this->getToken();
		$url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token={$access_token}";
		$restr = curlget($url, $data, 'POST', array("Content-type: text/html; charset=utf-8"), true);
		return $restr;
	}
	/**
	 * 数据XML编码
	 * @param  object $xml  XML对象
	 * @param  mixed  $data 数据
	 * @param  string $item 数字索引时的节点名称
	 * @return string
	 */
	private function data2xml($xml, $data, $item = 'item') {
		foreach ($data as $key => $value) {
			/* 指定默认的数字key */
			is_numeric($key) && $key = $item;
			/* 添加子元素 */
			if (is_array($value) || is_object($value)) {
				$child = $xml->addChild($key);
				$this->data2xml($child, $value, $item);
			} else {
				if (is_numeric($value)) {
					$child = $xml->addChild($key, $value);
				} else {
					$child = $xml->addChild($key);
					$node = dom_import_simplexml($child);
					$node->appendChild($node->ownerDocument->createCDATASection($value));
				}
			}
		}
	}
	/**
	 * 对数据进行签名认证，确保是微信发送的数据
	 * @param  string $token 微信开放平台设置的TOKEN
	 * @return boolean       true-签名正确，false-签名错误
	 */
	private function auth() {
	   $wxid=I('request.wxid');
	   $wx_WX_TOKEN=C('WX_TOKEN');
		/* 获取数据 */
		$data = array($wx_WX_TOKEN,I('get.timestamp'),I('get.nonce'));
		$sign = I('get.signature');
		/* 对数据进行字典排序 */
		sort($data, SORT_STRING);
		/* 生成签名 */
		$signature = sha1(implode($data));
		return $signature === $sign;
	}
	/**
	 * 获取保存的accesstoken
	 */
	private function getToken() {
		static $stoken = null;
        $accesstoken='';
        if(C('BOUND_STATUS')==2){//扫码授权
        	$wx = new \Common\Vendor\Weixinopen;
			$accesstoken=$wx->get_access_token(C('appid'));
        }else{
    		// 从缓存获取ACCESS_TOKEN
    		is_null($stoken) && $stoken = S('WX_S_TOKEN');
    		if (is_array($stoken) && $stoken['token']) {
    			$nowtime = time();
    			// 判断缓存里面的TOKEN保存了多久
    			$difftime = $nowtime - $stoken ['tokentime'];
    			// TOKEN有效时间7200 判断超过7000就重新获取;
    			if ($difftime > 7000) {
    				// 去微信获取最新ACCESS_TOKEN
    				$accesstoken = $this->getAcessToken();
    				$stoken ['tokentime'] = time();
    				$stoken ['token'] = $accesstoken;
    				// 放进缓存
    				S('WX_S_TOKEN', $stoken);
    			} else {
    				$accesstoken = $stoken ['token'];
    			}
    		} else {
    			// 去微信获取最新ACCESS_TOKEN
    			$accesstoken = $this->getAcessToken();
    			$stoken ['tokentime'] = time();
    			$stoken ['token'] = $accesstoken;
    			S('WX_S_TOKEN', $stoken); // 放进缓存
    		}
        }
		return $accesstoken;
	}
	/**
	 * 重新从微信获取accesstoken
	 */
	private function getAcessToken() {	
	   $wx = new \Common\Vendor\Jssdk();
       return $wx->getAccessToken();
	}
	public function companypay($openid,$amount='',$desc='',$user_name=''){
        if(emtpy($openid)){$result['msg']='OpenID不能为空!';return $result;}
        if($amount<=0){$result['msg']='金额错误!';return $result;}
        $result=array('status'=>0,'msg'=>'');
        $payinfo=M('Payment')->where("(code='Weixinpay' or code='weixinpay') and status=1")->field(true)->find();
        if(empty($payinfo)){$result['msg']='请先绑定微信支付再使用此功能!';return $result;}
        
$mch_appid=$payinfo['config_account'];
$mchid=$payinfo['config_partner'];//店铺号
$nonce_str=randStr(10);//随机数
$partner_trade_no='HC'.base_order();//店铺订单号
$check_name=empty($user_name)?'NO_CHECK':'OPTION_CHECK';//校验用户姓名选项，NO_CHECK：不校验真实姓名; FORCE_CHECK：强校验真实姓名（未实名认证的用户会校验失败，无法转账）; OPTION_CHECK：针对已实名认证的用户才校验真实姓名（未实名认证用户不校验，可以转账成功）
$re_user_name=$user_name;//用户姓名
$amount=$amount*100;//金额（以分为单位，必须大于100）
$spbill_create_ip=get_client_ip();//请求ip

        //封装成数据
        $dataArr=array();
        $dataArr['amount']=$amount;
        $dataArr['check_name']=$check_name;
        $dataArr['desc']=$desc;
        $dataArr['mch_appid']=$mch_appid;
        $dataArr['mchid']=$mchid;
        $dataArr['nonce_str']=$nonce_str;
        $dataArr['openid']=$openid;
        $dataArr['partner_trade_no']=$partner_trade_no;
        $dataArr['re_user_name']=$re_user_name;
        $dataArr['spbill_create_ip']=$spbill_create_ip;
        
        $sign=getSign($dataArr);
        $data="<xml>
<mch_appid>".$mch_appid."</mch_appid>
<mchid>".$mchid."</mchid>
<nonce_str>".$nonce_str."</nonce_str>
<partner_trade_no>".$partner_trade_no."</partner_trade_no>
<openid>".$openid."</openid>
<check_name>".$check_name."</check_name>
<re_user_name>".$re_user_name."</re_user_name>
<amount>".$amount."</amount>
<desc>".$desc."</desc>
<spbill_create_ip>".$spbill_create_ip."</spbill_create_ip>
<sign>".$sign."</sign>
</xml>";
        $url="https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
        $optsother=array('CURLOPT_SSLCERT'=>'apiclient_cert.pem','CURLOPT_SSLKEY'=>'apiclient_key.pem');
        $result=curlget($url,$data,'POST',array(),false,false,$optsother);
        $result=xml_to_array($result);
        var_dump($result);
        
    }
	private function getSign($Obj,$key)
    {
    	foreach ($Obj as $k => $v){$Parameters[$k] = $v;}    	
    	ksort($Parameters);//签名步骤一：按字典序排序参数
    	$String = format_array2http($Parameters, false);
    	$String = $String."&key=".$key;//签名步骤二：在string后加入KEY    	
    	$String = md5($String);//签名步骤三：MD5加密    	
    	$result_ = strtoupper($String);//签名步骤四：所有字符转为大写
    	return $result_;
    }
	/**
     * * 主动发送消息
     *
     * @param array  $content   内容数组
     * @param string $url   	url
     * @param string $openid   	发送者用户名
     * @param string $template_id   	模板ID
     * @return array 返回的信息
     */
    public function sendTplMsg($content, $path='',$openid = '', $template_id = '') {
        if(strlen($template_id)<16){
            $short_id=$template_id;
            $template_id=$this->get_template_id($short_id);
            if(empty($template_id)){
                return false;
            }else{
                $map=$data=array();
                $map['theme_remark']=$short_id;
                $data['theme_id']=$template_id;
                M('SmsTheme')->where($map)->save($data);
            }
        }
        /* 基础数据 */
        $data=array(
            "touser"=>$openid,
            "template_id"=>$template_id,
            "url"=>$path,
            "topcolor"=>"#FF0000",
            "data"=>$content
        );
        /* 发送 */
        $sendjson = json_encode($data, JSON_UNESCAPED_UNICODE);
        $access_token = $this->getToken();
        $url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={$access_token}";
        $restr = curlget($url, $sendjson, 'POST', array("Content-type: text/html; charset=utf-8"), true);
        return json_decode($restr,true);
    }
    
    /**
     * 获得模板ID
     * @param $short_id 模板库中模板的编号，有“TM**”和“OPENTMTM**”等形式
     */
    public function get_template_id($short_id=''){
        if(empty($short_id))return false;
        $access_token = $this->getToken();
        $param=array('template_id_short'=>$short_id);
		$sendjson = json_encode($param, JSON_UNESCAPED_UNICODE);
		$url = "https://api.weixin.qq.com/cgi-bin/template/api_add_template?access_token={$access_token}";
		$restr = curlget($url, $sendjson, 'POST', array("Content-type: text/html; charset=utf-8"), true);
        $data=json_decode($restr,true);
		return $data['template_id'];
        
    }
	/**
	 * 获取accesstoken
	 */
	public function getdd(){
		$ahuo  = $this->getToken();
		return $ahuo;
	}
}