项目需求:分享一篇微信文章,文章中嵌入图片和文字等。在文章的底部有一个二维码,用于扫描进入另一个页面去采集用户的报名数据。


 

实现步骤如下:

阶段一:微信公众号

1、申请一个微信公众号,由于考虑到是小范围使用,申请的是个人号

2、在‘素材管理’中,导入图片等信息。"图文消息"中去编辑微信文章。编辑完毕后保存

3、在“自定义菜单”项中去定义菜单,并将某个菜单指向为之前保存的“图文消息”

 


 

阶段二:信息采集功能开发

1、搭建一个空网站,安装插件:bootstrap、 jquery、bootstrapValidator。bootstrapValidator用作表单验证。

2、新建一个html页面,布局标签等信息。将提交的标签信息放置在form表单中。在表单标签中指定提交跳转的aciton,本项目指向一个一般处理程序:action="Handler.ashx"   完整代码如下:

supervisor watchdog 信息采集架构 信息采集功能_html

supervisor watchdog 信息采集架构 信息采集功能_html_02

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
    <title>"少年读书说"线上报名</title>
    <meta name="viewport"
          content="width=device-width,initial-scale=1.0,user-scalable=no">
    <link href="Content/bootstrap.min.css" rel="stylesheet" media="screen">
    <link href="Content/bootstrapValidator.min.css" rel="stylesheet" media="screen" />
    <script src="Scripts/jquery-3.1.1.min.js"></script>
    <script src="Scripts/bootstrap.min.js"></script>
    <script src="Scripts/bootstrapValidator.min.js"></script>
    <script>
        $(function () {
            $('#defaultForm').bootstrapValidator({
                message: 'This value is not valid',
                feedbackIcons: {
                    valid: 'glyphicon glyphicon-ok',
                    invalid: 'glyphicon glyphicon-remove',
                    validating: 'glyphicon glyphicon-refresh'
                },
                fields: {
                    username: {
                        message: '用户名验证失败',
                        validators: {
                            notEmpty: {
                                message: '用户名不能为空'
                            }
                        }
                    },
                    sex: {
                        message: '性别验证失败',
                        validators: {
                            notEmpty: {
                                message: '性别不能为空'
                            }
                        }
                    },
                    age: {
                        message: '年龄验证失败',
                        validators: {
                            notEmpty: {
                                message: '年龄不能为空'
                            },
                            between: {
                                min: 3,
                                max: 10,
                                message: '年龄范围3-10岁'
                            }
                        }
                    },
                    phone: {
                        validators: {
                            notEmpty: {
                                message: '手机号码不能为空'
                            },
                            regexp: {
                                regexp: /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/,
                                message: '请输入正确的电话号码'
                            }
                        }
                    },
                    parenter: {
                        message: '家长姓名验证失败',
                        validators: {
                            notEmpty: {
                                message: '家长姓名不能为空'
                            }
                        }
                    }
                },
                submitHandler: function (validator, form, submitButton) {
                    alert("你好");
                }
            });

            //$('#saveMsg').click(function () {
            //           $('#defaultForm').bootstrapValidator('validate');
            //});

            //$("#defaultForm").submit(function (ev) { ev.preventDefault(); });

            //$("#saveMsg").on("click", function () {
            //    var bootstrapValidator = $("#defaultForm").data('bootstrapValidator');
            //    bootstrapValidator.validate();
            //    if (bootstrapValidator.isValid()) {
            //        $("#defaultForm").submit();
            //        alert("成功");
            //    }
            //    else return;

            //});

        });

        //function showPopover(target, msg) {
        //    target.attr("data-original-title", msg);
        //    $('[data-toggle="tooltip"]').tooltip();
        //    target.tooltip('show');
        //    target.focus();
        //    //2秒后消失提示框
        //    var id = setTimeout(
        //      function () {
        //          target.attr("data-original-title", "");
        //          target.tooltip('hide');
        //      }, 2000
        //    );
        //}


    </script>
</head>

<body>
    <div class="panel panel-info">
        <div class="panel-heading">
            <img src="img/mmexport1496838159618.jpg" class="img-responsive center-block" />
        </div>
        <div class="panel-body">
            <form id="defaultForm" class="form-horizontal" role="form" action="Handler.ashx"
                  method="post">
                <div class="form-group">
                    <label for="username" class="col-sm-2 control-label">
                        小选手姓名:
                    </label>
                    <div class="col-sm-10">
                        <input type="text" name="username" class="form-control"
                               placeholder="请输入选手姓名" id="username" />
                    </div>
                </div>
                <div class="form-group">
                    <label for="sex" class="col-sm-2 control-label">
                        小选手性别:
                    </label>
                    <div class="col-sm-10">
                        <select class="form-control" id="sex" name="sex">
                            <option value="男">男</option>
                            <option value="女">女</option>
                        </select>
                    </div>
                </div>
                <div class="form-group">
                    <label for="age" class="col-sm-2 control-label">
                        小选手年龄:
                    </label>
                    <div class="col-sm-10">
                        <input type="text" name="age" class="form-control"
                               placeholder="请输入选手年龄" id="age" />
                    </div>
                </div>
                <div class="form-group">
                    <label for="parenter" class="col-sm-2 control-label">
                        家长姓名:
                    </label>
                    <div class="col-sm-10">
                        <input type="text" name="parenter" class="form-control"
                               placeholder="请输入家长姓名" id="parenter" />
                    </div>
                </div>
                <div class="form-group">
                    <label for="phone" class="col-sm-2 control-label">
                        家长手机号:
                    </label>
                    <div class="col-sm-10">
                        <input type="text" name="phone" class="form-control"
                               placeholder="请输入手机号码" id="phone" />
                    </div>
                </div>
                <div class="form-group">
                    <div class="col-sm-offset-2 col-sm-10">
                        <button id="saveMsg" name="saveMsg" type="submit" class="btn btn-primary btn-block">
                            提交
                        </button>
                    </div>
                </div>
            </form>
        </div>
    </div>
</body>
</html>

View Code

3、一般处理程序中完成信息的获取和提交。需要在该页中引入对数据库的操作代码,信息保存完毕后输出信息成功的提示。完整代码:

supervisor watchdog 信息采集架构 信息采集功能_html

supervisor watchdog 信息采集架构 信息采集功能_html_02

<%@ WebHandler Language="C#" Class="Handler" %>

using System;
using System.Web;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Collections;
using System.Data;
using Oracle.ManagedDataAccess.Client;

public class Handler : IHttpHandler
{

    public void ProcessRequest(HttpContext context)
    {
        //text/plain表示是普通文本,浏览器会原封不动的显示它得到的内容
        //"text/html"表示是超文本内容,浏览器会把它得到的内容按html格式进行处理后显示
        //context.Response.ContentType = "text/plain";
        context.Response.ContentType = "text/html";
        string username = context.Request.Form["username"].ToString();
        string sex = context.Request.Form["sex"].ToString();
        int age = Convert.ToInt32(context.Request.Form["age"].ToString());
        string parenter = context.Request.Form["parenter"].ToString();
        string phone = context.Request.Form["phone"].ToString();

        string connStr = string.Format("Data Source={0}:{1}/{2};User Id={3};Password={4};Connection Timeout =3600",
            "0.0.0.0", "1521","ORCL", "WX", "WX");

        string sql = string.Format(@"INSERT INTO READ_BOOK_USER(USERNAME,SEX,AGE,PARENTER,PHONE) 
                        VALUES('{0}','{1}',{2},'{3}','{4}')", username, sex, age, parenter, phone);
        int rs= ExecuteNonQuery(connStr, CommandType.Text, sql);

        //context.Response.Write("<script type='text/javascript'>alert('123')</script>");

        String output = string.Format("<span style='font-size:25px;'>恭喜您!“少年读书说”报名成功!</span>");

        context.Response.Write(output);
        //context.Response.Write("恭喜您!“少年读书说”报名成功!");
        //context.Response.Redirect("ReadBook.html");
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }

    #region oracle数据库操作
    private static Hashtable parmCache = Hashtable.Synchronized(new Hashtable());

    /// <summary>
    /// Execute a database query which does not include a select
    /// </summary>
    /// <param name="connString">Connection string to database</param>
    /// <param name="cmdType">Command type either stored procedure or SQL</param>
    /// <param name="cmdText">Acutall SQL Command</param>
    /// <param name="commandParameters">Parameters to bind to the command</param>
    /// <returns></returns>
    public static int ExecuteNonQuery(string connectionString, CommandType cmdType, string cmdText, params OracleParameter[] commandParameters)
    {
        // Create a new Oracle command
        OracleCommand cmd = new OracleCommand();
        //Create a connection
        using (OracleConnection connection = new OracleConnection(connectionString))
        {
            //Prepare the command
            PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters);
            //Execute the command
            int val = cmd.ExecuteNonQuery();
            cmd.Parameters.Clear();
            return val;
        }
    }

    /// <summary>
    /// Execute an OracleCommand (that returns no resultset) against an existing database transaction 
    /// using the provided parameters.
    /// </summary>
    /// <remarks>
    /// e.g.:  
    ///  int result = ExecuteNonQuery(trans, CommandType.StoredProcedure, "PublishOrders", new OracleParameter(":prodid", 24));
    /// </remarks>
    /// <param name="trans">an existing database transaction</param>
    /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
    /// <param name="commandText">the stored procedure name or PL/SQL command</param>
    /// <param name="commandParameters">an array of OracleParamters used to execute the command</param>
    /// <returns>an int representing the number of rows affected by the command</returns>
    public static int ExecuteNonQuery(OracleTransaction trans, CommandType cmdType, string cmdText, params OracleParameter[] commandParameters)
    {
        OracleCommand cmd = new OracleCommand();
        PrepareCommand(cmd, trans.Connection, trans, cmdType, cmdText, commandParameters);
        int val = cmd.ExecuteNonQuery();
        cmd.Parameters.Clear();
        return val;
    }

    /// <summary>
    /// Execute an OracleCommand (that returns no resultset) against an existing database connection 
    /// using the provided parameters.
    /// </summary>
    /// <remarks>
    /// e.g.:  
    ///  int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new OracleParameter(":prodid", 24));
    /// </remarks>
    /// <param name="conn">an existing database connection</param>
    /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
    /// <param name="commandText">the stored procedure name or PL/SQL command</param>
    /// <param name="commandParameters">an array of OracleParamters used to execute the command</param>
    /// <returns>an int representing the number of rows affected by the command</returns>
    public static int ExecuteNonQuery(OracleConnection connection, CommandType cmdType, string cmdText, params OracleParameter[] commandParameters)
    {

        OracleCommand cmd = new OracleCommand();

        PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters);
        int val = cmd.ExecuteNonQuery();
        cmd.Parameters.Clear();
        return val;
    }

    /// <summary>
    /// Execute a select query that will return a result set
    /// </summary>
    /// <param name="connString">Connection string</param>
    //// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
    /// <param name="commandText">the stored procedure name or PL/SQL command</param>
    /// <param name="commandParameters">an array of OracleParamters used to execute the command</param>
    /// <returns></returns>
    public static OracleDataReader ExecuteReader(string connectionString, CommandType cmdType, string cmdText, params OracleParameter[] commandParameters)
    {

        //Create the command and connection
        OracleCommand cmd = new OracleCommand();
        OracleConnection conn = new OracleConnection(connectionString);

        try
        {
            //Prepare the command to execute
            PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);

            //Execute the query, stating that the connection should close when the resulting datareader has been read
            OracleDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
            cmd.Parameters.Clear();
            return rdr;

        }
        catch
        {

            //If an error occurs close the connection as the reader will not be used and we expect it to close the connection
            conn.Close();
            throw;
        }
    }

    public static OracleDataReader ExecuteReader(OracleConnection conn, CommandType cmdType, string cmdText, params OracleParameter[] commandParameters)
    {

        //Create the command and connection
        OracleCommand cmd = new OracleCommand();
        try
        {
            //Prepare the command to execute
            PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);

            //Execute the query, stating that the connection should close when the resulting datareader has been read
            OracleDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
            cmd.Parameters.Clear();
            return rdr;

        }
        catch
        {

            //If an error occurs close the connection as the reader will not be used and we expect it to close the connection
            conn.Close();
            throw;
        }
    }

    /// <summary>
    /// Execute an OracleCommand that returns the first column of the first record against the database specified in the connection string 
    /// using the provided parameters.
    /// </summary>
    /// <remarks>
    /// e.g.:  
    ///  Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new OracleParameter(":prodid", 24));
    /// </remarks>
    /// <param name="connectionString">a valid connection string for a SqlConnection</param>
    /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
    /// <param name="commandText">the stored procedure name or PL/SQL command</param>
    /// <param name="commandParameters">an array of OracleParamters used to execute the command</param>
    /// <returns>An object that should be converted to the expected type using Convert.To{Type}</returns>
    public static object ExecuteScalar(string connectionString, CommandType cmdType, string cmdText, params OracleParameter[] commandParameters)
    {
        OracleCommand cmd = new OracleCommand();

        using (OracleConnection conn = new OracleConnection(connectionString))
        {
            PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
            object val = cmd.ExecuteScalar();
            cmd.Parameters.Clear();
            return val;
        }
    }

    public static IDataReader ExecuteDataReader(string connectionString, CommandType cmdType, string cmdText, params OracleParameter[] commandParameters)
    {
        OracleCommand cmd = new OracleCommand();

        using (OracleConnection conn = new OracleConnection(connectionString))
        {
            PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
            IDataReader val = cmd.ExecuteReader();
            cmd.Parameters.Clear();
            return val;
        }
    }

    public static IDataReader ExecuteDataReader(OracleConnection conn, CommandType cmdType, string cmdText, params OracleParameter[] commandParameters)
    {
        OracleCommand cmd = new OracleCommand();

        PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
        IDataReader val = cmd.ExecuteReader();
        cmd.Parameters.Clear();
        return val;

    }

    ///    <summary>
    ///    Execute    a OracleCommand (that returns a 1x1 resultset)    against    the    specified SqlTransaction
    ///    using the provided parameters.
    ///    </summary>
    ///    <param name="transaction">A    valid SqlTransaction</param>
    ///    <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    ///    <param name="commandText">The stored procedure name    or PL/SQL command</param>
    ///    <param name="commandParameters">An array of    OracleParamters used to execute the command</param>
    ///    <returns>An    object containing the value    in the 1x1 resultset generated by the command</returns>
    public static object ExecuteScalar(OracleTransaction transaction, CommandType commandType, string commandText, params OracleParameter[] commandParameters)
    {
        if (transaction == null)
            throw new ArgumentNullException("transaction");
        if (transaction != null && transaction.Connection == null)
            throw new ArgumentException("The transaction was rollbacked    or commited, please    provide    an open    transaction.", "transaction");

        // Create a    command    and    prepare    it for execution
        OracleCommand cmd = new OracleCommand();

        PrepareCommand(cmd, transaction.Connection, transaction, commandType, commandText, commandParameters);

        // Execute the command & return    the    results
        object retval = cmd.ExecuteScalar();

        // Detach the SqlParameters    from the command object, so    they can be    used again
        cmd.Parameters.Clear();
        return retval;
    }

    /// <summary>
    /// Execute an OracleCommand that returns the first column of the first record against an existing database connection 
    /// using the provided parameters.
    /// </summary>
    /// <remarks>
    /// e.g.:  
    ///  Object obj = ExecuteScalar(conn, CommandType.StoredProcedure, "PublishOrders", new OracleParameter(":prodid", 24));
    /// </remarks>
    /// <param name="conn">an existing database connection</param>
    /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
    /// <param name="commandText">the stored procedure name or PL/SQL command</param>
    /// <param name="commandParameters">an array of OracleParamters used to execute the command</param>
    /// <returns>An object that should be converted to the expected type using Convert.To{Type}</returns>
    public static object ExecuteScalar(OracleConnection connectionString, CommandType cmdType, string cmdText, params OracleParameter[] commandParameters)
    {
        OracleCommand cmd = new OracleCommand();

        PrepareCommand(cmd, connectionString, null, cmdType, cmdText, commandParameters);
        object val = cmd.ExecuteScalar();
        cmd.Parameters.Clear();
        return val;
    }

    /// <summary>
    /// Add a set of parameters to the cached
    /// </summary>
    /// <param name="cacheKey">Key value to look up the parameters</param>
    /// <param name="commandParameters">Actual parameters to cached</param>
    public static void CacheParameters(string cacheKey, params OracleParameter[] commandParameters)
    {
        parmCache[cacheKey] = commandParameters;
    }

    /// <summary>
    /// Fetch parameters from the cache
    /// </summary>
    /// <param name="cacheKey">Key to look up the parameters</param>
    /// <returns></returns>
    public static OracleParameter[] GetCachedParameters(string cacheKey)
    {
        OracleParameter[] cachedParms = (OracleParameter[])parmCache[cacheKey];

        if (cachedParms == null)
            return null;

        // If the parameters are in the cache
        OracleParameter[] clonedParms = new OracleParameter[cachedParms.Length];

        // return a copy of the parameters
        for (int i = 0, j = cachedParms.Length; i < j; i++)
            clonedParms[i] = (OracleParameter)((ICloneable)cachedParms[i]).Clone();

        return clonedParms;
    }

    /// <summary>
    /// Internal function to prepare a command for execution by the database
    /// </summary>
    /// <param name="cmd">Existing command object</param>
    /// <param name="conn">Database connection object</param>
    /// <param name="trans">Optional transaction object</param>
    /// <param name="cmdType">Command type, e.g. stored procedure</param>
    /// <param name="cmdText">Command test</param>
    /// <param name="commandParameters">Parameters for the command</param>
    private static void PrepareCommand(OracleCommand cmd, OracleConnection conn, OracleTransaction trans, CommandType cmdType, string cmdText, OracleParameter[] commandParameters)
    {

        //Open the connection if required
        if (conn.State != ConnectionState.Open)
            conn.Open();

        //Set up the command
        cmd.Connection = conn;
        cmd.CommandText = cmdText;
        cmd.CommandType = cmdType;

        //Bind it to the transaction if it exists
        //if (trans != null)
        //    cmd.Transaction = trans;

        // Bind the parameters passed in
        if (commandParameters != null)
        {
            foreach (OracleParameter parm in commandParameters)
                cmd.Parameters.Add(parm);
        }
    }

    /// <summary>
    /// Converter to use boolean data type with Oracle
    /// </summary>
    /// <param name="value">Value to convert</param>
    /// <returns></returns>
    public static string OraBit(bool value)
    {
        if (value)
            return "Y";
        else
            return "N";
    }

    /// <summary>
    /// Converter to use boolean data type with Oracle
    /// </summary>
    /// <param name="value">Value to convert</param>
    /// <returns></returns>
    public static bool OraBool(string value)
    {
        if (value.Equals("Y"))
            return true;
        else
            return false;
    }

    public static DataSet ExecuteDataset(string ConnectionString, CommandType cmdType, string cmdText, params OracleParameter[] commandParameters)
    {
        //Create the command and connection
        OracleConnection conn = new OracleConnection(ConnectionString);
        conn.Open();
        OracleCommand cmd = new OracleCommand();
        cmd.Connection = conn;
        cmd.CommandText = cmdText;
        cmd.CommandType = CommandType.Text;
        OracleDataAdapter oda;
        //DataSet ds = new DataSet();
        DataSet ds;
        try
        {
            oda = new OracleDataAdapter(cmd);
            ds = new DataSet();
            oda.Fill(ds, "temp");

            ////Prepare the command to execute
            //PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);

            ////Execute the query, stating that the connection should close when the resulting datareader has been read
            //OracleDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
            //cmd.Parameters.Clear();
            conn.Close();
            return ds;
        }
        catch (Exception err)
        {

            //If an error occurs close the connection as the reader will not be used and we expect it to close the connection
            conn.Close();
            throw err;
        }
        //return ds;
    }
    #endregion
}

View Code

4、由于返回的信息有显示格式要求,故需要将ContentType 的类型修改为 "text/html"

"text/plain"表示是普通文本,浏览器会原封不动的显示它得到的内容

"text/html"表示是超文本内容,浏览器会把它得到的内容按html格式进行处理后显示

5、数据库的链接串可以写在web.config配置文件中,然后在此处获取。

6、需要在一般处理程序中加入对数据库的操作ado语句,本项目使用的oracle,引入的dll文件名为Oracle.ManagedDataAccess.dll   dll下载

7、将网站发布,部署到已准备好的服务器上面。

 


 

阶段三:网站域名的申请

1、由于在微信端访问无域名的网站(带ip)会提示是否继续访问的环节,使用体检差。故需要将服务器ip申请为域名

2、域名申请方式:买的阿里云域名。我是先在万网上购买了一个域名然后实名认证,再域名备案等等操作之后才可以使用。请自己去搜步骤

3、给域名绑定服务器ip,不支持+端口的绑定。故域名默认指向网站80端口

4、给网站绑定域名。截图如下:

supervisor watchdog 信息采集架构 信息采集功能_System_05

 

5、绑定之后,就可以直接访问域名方式访问到网站

6、在微信公众号后台中去绑定域名

supervisor watchdog 信息采集架构 信息采集功能_bootstrap_06

 

supervisor watchdog 信息采集架构 信息采集功能_bootstrap_07

 

 


 

阶段四:将指定网页生成为二维码

1、复制网站地址,在“草料二维码”生成器中生成自己二维码,保存二维码为图片。

2、在微信素材管理中添加二维码图片,并在“图文消息”那篇文字最后放置二维码然后保存素材

结果:以上阶段完成后,将微信公众号中对应菜单分享给其他朋友就达到我们需求想要的效果.效果如下:

supervisor watchdog 信息采集架构 信息采集功能_bootstrap_08

        

supervisor watchdog 信息采集架构 信息采集功能_bootstrap_09