微信公共平台开发入门-通过有道词典实现翻译—位置消息—图片消息处理

本文介绍了一种微信公众号开发的实战案例,通过简单的PHP脚本实现对用户消息的响应功能,包括文字翻译、图片链接反馈及位置信息回应。

昨天开始搞微信公共平台开发,花了半天的时间学习基本的php语法,然后结合了网上的例子,自己做了一个demo,功能如题,下面进行讲解。

(读此文的前提是你已经做好了配置工作)

我的配置:

 url:*************/fan/index.php

 token:test

url中 fan文件夹目录如图所示:(其中index.php是主服务,wechat是我写的一个函数,fanyi.php是我自己测试用的,这里用不到)


下面看源代码:(每一步都讲解一下)

index.php:

<?php

define("DEBUG", true);
define("TOKEN", "fanyitest");
define("KEYFROM", "weixen");//有道词典keyform,需要自己申请
define("APIKEY", 791576090);//有道词典的apikey,需要自己申请

require_once(dirname(__FILE__) . "/wechat.php");//载入wechat.php 

$w = new Wechat(TOKEN, DEBUG);//实例化

//首次验证,验证过以后可以删掉
if (isset($_GET['echostr'])) {
    $w->valid();
    exit();
}

//回复用户
$w->reply("reply_cb"); //从这里开始时本程序的关键所在,这里的参数是reply_cb,阅读完本程序你会发现它是一个函数名称,那么我们先跳转到wechat.php中,因为$w是它实例化的对象,然后再回都继续读本程序

//后续必要的处理...
/* TODO */
exit();

function fanyi($yuanwen,$keyfrom,$apikey)
 {
    	
    	
    $yuanwen=get_utf8_string($yuanwen);//格式转换
    $doc = new DOMDocument();
    $doc->load("http://fanyi.youdao.com/openapi.do?keyfrom=".$keyfrom."&key=".$apikey."&type=data&doctype=xml&version=1.1&q=".$yuanwen); //读取xml文件
  	$youdaos = $doc->getElementsByTagName( "youdao-fanyi" ); //取得humans标签的对象数组
 foreach( $youdaos as $youdao )
  {
    $paragraphs = $youdao->getElementsByTagName( "paragraph" ); //取得name的标签的对象数组
    $paragraph = $paragraphs->item(0)->nodeValue; //取得node中的值,如<name> </name>
    $paragraph=get_utf8_string($paragraph);
    $exs = $youdao->getElementsByTagName( "ex" ); //取得name的标签的对象数组
    $ex = $exs->item(0)->nodeValue; //取得node中的值,如<name> </name>
    $ex=get_utf8_string($ex);

  }
if($paragraph==$ex){
    return $paragraph;
  }else{
	  return $paragraph.";  ".$ex ;
  }
}


function get_utf8_string($content) {    
	//  将一些字符转化成utf8格式   
	 $encoding = mb_detect_encoding($content, array('ASCII','UTF-8','GB2312','GBK','BIG5'));  
	   return  mb_convert_encoding($content, 'utf-8', $encoding);
	   }
	   
function reply_cb($request, $w)//wechat.php会直接跳转到这里执行,参数不在多解释
{
    if ($w->get_msg_type() == "location") {            //对用户输入的信息类型进行判断,如果是位置信息,返回你的坐标
        return sprintf("你的位置:(%s, %s), 地址:%s",
                $request['Location_X'], $request['Location_Y'], $request['Label']);
    }
    else if ($w->get_msg_type() == "image") { //echo back url如果是图片信息,返回图片url
        $PicUrl = $request['PicUrl'];
        return "图片url:" . $PicUrl;
    }
    //else: Text如果是文本信息,进行翻译

    $content = trim($request['Content']);
    if ($content === "hello" or $content === "hi" or $content === "你好"or $content === "好") { //貌似第一次加入会发送这个
        return "兄弟,你是幼儿园毕业的么!这么简单的word!!微信论坛欢迎您(www.weixen.com)";
    }

    if ($content !== "url") //发纯文本
    {
        //$w->set_funcflag(); //如果有必要的话,加星标,方便在web处理
        if(!empty($content)){
          $content = fanyi($content,KEYFROM,APIKEY);//执行翻译函数
            return "小译: " . $content; //返回到wechat
          }
        else
            return "请说点什么..."; //返回到wechat
    }
    else //发图文消息
    {
        //* 单个图文
        return array(
            "title" =>  "hello",
            "description" =>  "world",
            "pic" =>  "http://www.weixen.com/template/eis_d25_031/img/logo.png",
            "url" =>  "http://www.weixen.com",
        );
    
    }
}

?>
wechat.php

<?php

/*
    File: wechat.php
    Author: felix021@gmail.com
    Date: 2012.11.30
    Usage: api封装
    Comment: 详见readme.txt
 */

class Wechat
{
    //似乎没什么用,放着用来自动完成吧。
    static $req_keys = array( "Content", "CreateTime", "FromUserName", "Label", 
            "Location_X", "Location_Y", "MsgType", "PicUrl", "Scale", "ToUserName", );
    public $token;
    public $request = array();

    protected $funcflag = false;
    protected $debug = false;
    //初始化函数
    public function __construct($token, $debug = false)
    {
        $this->token = $token;
        $this->debug = $debug;
    }

    public function get_msg_type()
    {
        return strtolower($this->request['MsgType']);
    }

	public function valid()
    {
        $echoStr = $_GET["echostr"];
        if($this->checkSignature()){
        	echo $echoStr;
        	exit;
        }
    }

    public function set_funcflag()
    {
        $this->funcflag = true;
    }

    public function replyText($message)
    {
        $textTpl = <<<eot
<xml>
    <ToUserName><![CDATA[%s]]></ToUserName>
    <FromUserName><![CDATA[%s]]></FromUserName>
    <CreateTime>%s</CreateTime>
    <MsgType><![CDATA[%s]]></MsgType>
    <Content><![CDATA[%s]]></Content>
    <FuncFlag>%d</FuncFlag>
</xml>
eot;
        $req = $this->request;
        return sprintf($textTpl, $req['FromUserName'], $req['ToUserName'],
                time(), 'text', $message, $this->funcflag ? 1 : 0);

    }

    public function replyNews($arr_item)
    {
        $itemTpl = <<<eot
        <item>
            <Title><![CDATA[%s]]></Title>
            <Discription><![CDATA[%s]]></Discription>
            <PicUrl><![CDATA[%s]]></PicUrl> 
            <Url><![CDATA[%s]]></Url>
        </item>

eot;
        $real_arr_item = $arr_item;
        if (isset($arr_item['title']))
            $real_arr_item = array($arr_item); 

        $nr = count($real_arr_item);
        $item_str = "";
        foreach ($real_arr_item as $item)
            $item_str .= sprintf($itemTpl, $item['title'], $item['description'],
                    $item['pic'], $item['url']);

        $time = time();
        $fun = $this->funcflag ? 1 : 0;

        return <<<eot
<xml>
    <ToUserName><![CDATA[{$this->request['FromUserName']}]]></ToUserName>
    <FromUserName><![CDATA[{$this->request['ToUserName']}]]></FromUserName>
    <CreateTime>{$time}</CreateTime>
    <MsgType><![CDATA[news]]></MsgType>
    <Content><![CDATA[]]></Content>
    <ArticleCount>{$nr}</ArticleCount>
    <Articles>
$item_str
    </Articles>
    <FuncFlag>{$fun}</FuncFlag>
</xml> 
eot;
    }
    这里就是上一个index.php中调用的方法,这里我们将传入的函数名reply_cb保存到callback中
    public function reply($callback)
    {
        //get post data, May be due to the different environments 获取用户输入的信息
        $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
        if ($this->debug)
            file_put_contents("request.txt", $postStr);//将用户输入的信息保存到目录中的request.txt文件中

        if(empty($postStr) || !$this->checkSignature())//判断这次请求是否有效
            die("bad request");

        $this->request = (array)simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);//将xml字符串载入到request中

        $arg = call_user_func($callback, $this->request, $this);//这句是关键所在,call_user_func()是调用用户自定义的函数,第一个代表的是调表要调用哪个函数,第二参数是request(及用户输入的信息的xml格式),第三个参数是那个对象,也可以看index.php中的方法,返回的                                                                //信息保存在arg中,我们现在在回头去看index.php

        if (!is_array($arg))   //判断发送的信息类型
            $ret = $this->replyText($arg);
        else
            $ret = $this->replyNews($arg);

        if ($this->debug)
            file_put_contents("response.txt", $ret);
        echo $ret;
    }

	private function checkSignature()
	{
        $args = array("signature", "timestamp", "nonce");
        foreach ($args as $arg)
            if (!isset($_GET[$arg]))
                return false;

        $signature = $_GET["signature"];
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];	
        		
		$tmpArr = array($this->token, $timestamp, $nonce);
		sort($tmpArr);
		$tmpStr = implode( $tmpArr );
		$tmpStr = sha1( $tmpStr );
		
		if( $tmpStr == $signature ){
			return true;
		}else{
			return false;
		}
	}
}

?>




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值