微信公众号最佳实践 ( 8.7)一站到底

一站到底

《一站到底》是一个益智答题类节目。趣味十足,在挑战中挖掘个性。

这里写图片描述

实现方案

首先,我们需要有一个题库,用户答题的内容均从题库中获取。

这里写图片描述
该题库SQL语句如下:

--
-- 表的结构 `questions`
--

DROP TABLE IF EXISTS `questions`;
CREATE TABLE IF NOT EXISTS `questions` (
  `id` int(5) NOT NULL AUTO_INCREMENT,
  `figure` varchar(1) DEFAULT NULL,
  `types` varchar(1) DEFAULT NULL,
  `question` varchar(255) DEFAULT NULL,
  `numbers` int(1) DEFAULT NULL,
  `optionA` varchar(50) DEFAULT NULL,
  `optionB` varchar(60) DEFAULT NULL,
  `optionC` varchar(60) DEFAULT NULL,
  `optionD` varchar(60) DEFAULT NULL,
  `optionE` varchar(60) DEFAULT NULL,
  `optionF` varchar(30) DEFAULT NULL,
  `answer` varchar(6) DEFAULT NULL,
  `classify` varchar(4) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM;

id:表示题目的序号
question:为题目的内容
aoptionA-optionF: 表示该题可选择的答案有A到F 六个选项,但不是每一个题目都有这么多选项,大多数为4个,所以允许答案为空
answer:为该题的正确答案

这里写图片描述

然后,需要有一个保存用户答案记录的表,以便为用户的答案情况记录分数等情况。
记录表结构如下

这里写图片描述

--
-- 表的结构 `record`
--

DROP TABLE IF EXISTS `record`;
CREATE TABLE IF NOT EXISTS `record` (
  `openid` varchar(28) NOT NULL COMMENT '微信ID',
  `question` int(5) DEFAULT '-1' COMMENT '答题偏移',
  `question_y` int(5) DEFAULT '0' COMMENT '答题正确',
  `question_n` int(5) DEFAULT '0' COMMENT '答题错误',
  PRIMARY KEY (`openid`)
) ENGINE=MyISAM;

这里写图片描述这里写图片描述

开发实现:

首先,当我们接收到用户发过来的文字消息的时候,判断是否是答案有关的输入,这里使用 “答题”作为进入答题开始的指令,使用A到F共6个字母(不区分大小写)作为答案的输入指令。

 private function receiveText($object)
    {
        $keyword = trim($object->Content);
        //判断用户输入是否为“答题”,并使用正则表达式判断字母范围
        if ($keyword == "答题" || preg_match("/^[A-Fa-f]$/", $keyword)){
            include("question.php");
            //将字母强制转换成了小写
            $content = getQuestionInfo($object->FromUserName, (($keyword == "答题")?$keyword:strtoupper(trim($object->Content))));
        }
        $result = $this->transmitText($object, $content);
        return $result;
    }
答题部分的程序实现如下:

question.php整体代码

<?php
// var_dump(getQuestionInfo("ollB4jtmI_i8CqYlj-QMiuxx", "A"));

function getQuestionInfo($openid, $answer)
{
    $dbname = "app_dq095";
    $host = "w.rdc.sae.sina.com.cn";
    $port = "3306";
    $user = "4k514n103z";
    $pwd = "2402314li2j1i5im1xy2xizj5y332w2x41k2z203";

    /*接着调用mysql_connect()连接服务器*/
    $db = mysql_connect($host,$user,$pwd);

    if(!$db){
        die("Connect Server Failed: " . mysql_error($db));
    }

    /*连接成功后立即调用mysql_select_db()选中需要连接的数据库*/
    if (!mysql_select_db($dbname)) {
        die("Select Database Failed: " . mysql_error($db));
    }
    mysql_query("set names utf-8",$db); 


    $mysql_table_questions = "questions";

    //查询得到当前数据库中题目的数量,便于下面代码中进行判断
    $mysql_get_rows = "SHOW TABLE STATUS like '".$mysql_table_questions."';";
    $result5 = mysql_query($mysql_get_rows);
    $row = mysql_fetch_array($result5);

    //当前数据库中题目的数量
    $max_question = $row['Rows'];

    $mysql_table_record = "record";
    $finish_question = 0;

    //当用户输入“答题”时,初始化用户答题记录,如果已经有记录,则清零,并且设置当前用户答题数量为0
    if ($answer == "答题"){
        $mysql_insert = "INSERT INTO `".$mysql_table_record."` (`openid`, `question`, `question_y`, `question_n`) VALUES('".$openid."', '0', '0', '0') ON DUPLICATE KEY UPDATE `question` = '0', `question_y` = '0', `question_n` = '0';";
        @mysql_query($mysql_insert);
        $finish_question = 0;
    }else{
        $mysql_select = "SELECT * FROM `".$mysql_table_record."` WHERE `openid` = '".$openid."';";
        $result4 = mysql_query($mysql_select);
        $row = mysql_fetch_array($result4);
        $finish_question = $row['question'];

        //如果用户答题的个数已经为题目数量,那么说明用户已经完成答题,不需要再参加此次答题了。
        if($finish_question == $max_question){
            return "你已经答完了全部题目";
        }

        //如果还不等于题目数量,那么说明没有答玩,这里将用户的答题数增加 1 
        $mysql_update = "UPDATE `".$mysql_table_record."` SET `question` = `question` + 1 WHERE `openid` = '".$openid."';";
        $result3 = mysql_query($mysql_update);
        $finish_question += 1; 
    }

    //根据用户答题个数,定义不同的查询语句

    //当用户答第一题的题目时,取回第一个题目
    if ($finish_question == 0){
        $mysql_state = "SELECT * FROM `".$mysql_table_questions."` LIMIT ".$finish_question.",1";
    //当用户答最后一题的题目时,需要取最后一题
    }else if($finish_question == $max_question){
        $mysql_state = "SELECT * FROM `".$mysql_table_questions."` LIMIT ".($finish_question - 1).",1";
    //其他情况下,需要取回当前题目的答案及下一题的题目。
    }else{
        $mysql_state = "SELECT * FROM `".$mysql_table_questions."` LIMIT ".($finish_question - 1).",2";
    }
    //执行上述查询语句
    $result = @mysql_query($mysql_state);

    $content = "";
    //获取当用户题数为0时的返回内容,表示用户没有参加过答题
    if ($finish_question == 0){
        //如果没有查询到题目,则可能是系统出现异常。
        if (mysql_num_rows($result) < 1){
            $content .= "系统繁忙,请过会重试\n";
        }else{
             //首先加上一段“一站到底在线答题开始”的提示语,再将第一题的题目及选项返回给用户
            $content .= "一站到底在线答题开始\n";
            while($row = mysql_fetch_array($result))
            {
                $content .= "第".$row['id']."题:".$row['question']."\n";
                $content .= empty($row['optionA'])?"":"A. ".$row['optionA']."\n";
                $content .= empty($row['optionB'])?"":"B. ".$row['optionB']."\n";
                $content .= empty($row['optionC'])?"":"C. ".$row['optionC']."\n";
                $content .= empty($row['optionD'])?"":"D. ".$row['optionD']."\n";
                $content .= empty($row['optionE'])?"":"E. ".$row['optionE']."\n";
                $content .= empty($row['optionF'])?"":"F. ".$row['optionF']."\n";
            }
        }
     //这段代码处理用户答到最后一题的情况,这时只需要判断用户答案是否正确,然后将用户的答案情况记录到表中,
     //最后,在统计一下用户的答题情况,包括答题个数,正确个数即正确率。
    }else if($finish_question == $max_question){
        while($row = mysql_fetch_array($result))
        {
            $content .= ($answer == $row['answer'])?"回答正确\n":"回答错误!正确答案为 ".$row['answer']."\n";
            if ($answer == $row['answer']){
                $mysql_update_yesno = "UPDATE `".$mysql_table_record."` SET `question_y` = `question_y` + 1 WHERE `openid` = '".$openid."';";
            }else{
                $mysql_update_yesno = "UPDATE `".$mysql_table_record."` SET `question_n` = `question_n` + 1 WHERE `openid` = '".$openid."';";
            }
            $result_yesno = mysql_query($mysql_update_yesno);

            $mysql_statistics = "SELECT * FROM `".$mysql_table_record."` WHERE `openid` = '".$openid."';";
            $result6 = mysql_query($mysql_statistics);
            $row = mysql_fetch_array($result6);
            $result_all = $row['question'];
            $result_yes = $row['question_y'];
            $content .= "恭喜,您已完成全部题目。"."\n题目个数:".$result_all."\n正确个数:".$result_yes."\n正确率:".round(($result_yes / $result_all) * 100, 2)."%";
        }
     //这里处理既不是第一题,也不是最后一题的情况,这种情况下,SQL查询语句中会返回两条记录,
     //第一条是当前题目,第二条是下一个题目。系统获取当前题目的答案用于判断用户是否回答正确,获取下一条内容及选项返回给用户,以便用户回答下一题。
    }else{
        $first = true;
        while($row = mysql_fetch_array($result))
        {
            if ($first){
                $content .= ($answer == $row['answer'])?"回答正确\n":"回答错误!正确答案为 ".$row['answer']."\n";
                $first = false;
                if ($answer == $row['answer']){
                    $mysql_update_yesno = "UPDATE `".$mysql_table_record."` SET `question_y` = `question_y` + 1 WHERE `openid` = '".$openid."';";
                }else{
                    $mysql_update_yesno = "UPDATE `".$mysql_table_record."` SET `question_n` = `question_n` + 1 WHERE `openid` = '".$openid."';";
                }
                $result_yesno = mysql_query($mysql_update_yesno);
            }else{
                $content .= "第".$row['id']."题:".$row['question']."\n";
                $content .= empty($row['optionA'])?"":"A. ".$row['optionA']."\n";
                $content .= empty($row['optionB'])?"":"B. ".$row['optionB']."\n";
                $content .= empty($row['optionC'])?"":"C. ".$row['optionC']."\n";
                $content .= empty($row['optionD'])?"":"D. ".$row['optionD']."\n";
                $content .= empty($row['optionE'])?"":"E. ".$row['optionE']."\n";
                $content .= empty($row['optionF'])?"":"F. ".$row['optionF']."\n";
            }
        }
    }
    mysql_close($db);
    return trim($content);
}

?>

index.php整体代码如下:

<?php
/*
    CopyRight 2018 All Rights Reserved
*/

define("TOKEN", "weixin");

$wechatObj = new wechatCallbackapiTest();
if (!isset($_GET['echostr'])) {
    $wechatObj->responseMsg();
}else{
    $wechatObj->valid();
}

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

    private function checkSignature()
    {
        $signature = $_GET["signature"];
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];
        $token = TOKEN;
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr);
        $tmpStr = implode($tmpArr);
        $tmpStr = sha1($tmpStr);

        if($tmpStr == $signature){
            return true;
        }else{
            return false;
        }
    }

    public function responseMsg()
    {
        $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
        if (!empty($postStr)){
            $this->logger("R ".$postStr);
            $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
            $RX_TYPE = trim($postObj->MsgType);

            switch ($RX_TYPE)
            {
                case "event":
                    $result = $this->receiveEvent($postObj);
                    break;
                case "text":
                    $result = $this->receiveText($postObj);
                    break;
            }
            $this->logger("T ".$result);
            echo $result;
        }else {
            echo "";
            exit;
        }
    }

    private function receiveEvent($object)
    {
        $content = "";
        switch ($object->Event)
        {
            case "subscribe":
                $content = "欢迎关注方倍工作室 ";
                break;
            case "unsubscribe":
                $content = "取消关注";
                break;
        }
        $result = $this->transmitText($object, $content);
        return $result;
    }

    private function receiveText($object)
    {
        $keyword = trim($object->Content);
        if ($keyword == "答题" || preg_match("/^[A-Fa-f]$/", $keyword)){
            include("question.php");
            $content = getQuestionInfo($object->FromUserName, (($keyword == "答题")?$keyword:strtoupper(trim($object->Content))));
        }
        $result = $this->transmitText($object, $content);
        return $result;
    }

    private function transmitText($object, $content)
    {
        $textTpl = "<xml>
                        <ToUserName><![CDATA[%s]]></ToUserName>
                        <FromUserName><![CDATA[%s]]></FromUserName>
                        <CreateTime>%s</CreateTime>
                        <MsgType><![CDATA[text]]></MsgType>
                        <Content><![CDATA[%s]]></Content>
                    </xml>";
        $result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(), $content);
        return $result;
    }

    private function logger($log_content)
    {
        if(isset($_SERVER['HTTP_BAE_ENV_APPID'])){   //BAE
            require_once "BaeLog.class.php";
            $logger = BaeLog::getInstance();
            $logger ->logDebug($log_content);
        }else if(isset($_SERVER['HTTP_APPNAME'])){   //SAE
            sae_set_display_errors(false);
            sae_debug($log_content);
            sae_set_display_errors(true);
        }else if($_SERVER['REMOTE_ADDR'] != "127.0.0.1"){ //LOCAL
            $max_size = 10000;
            $log_filename = "log.xml";
            if(file_exists($log_filename) and (abs(filesize($log_filename)) > $max_size)){unlink($log_filename);}
            file_put_contents($log_filename, date('H:i:s')." ".$log_content."\r\n", FILE_APPEND);
        }
    }
}


?>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值