这周开始又转回了熟悉而又陌生的Unity开发,一年前从Unity转向cocos2dx,这一年里有不少曲折,也有不少的心酸,或许是因为“心”未定,又或许因为其他,有种使不上劲的感觉,曾经的傲气逐渐的被“驱散”,习惯了被训斥和教育。面的各种形形色色的技术,总是经不住诱惑,都想学习一遍,但又无奈精力有限,加上工作的压力,每天都搞的身心疲惫,总之这一年里对自己的评价用“失望”两个字来形容!但从这周开始又重回Unity开发,心里有一丝喜感,或许真的对它期待已久!昨晚看着游戏蛮牛上一些老大们写的关于Unity的技术分享的文章,直到一点还依然没有睡意,深深的陶醉了,迫于第二天要工作的压力才不得不依依不舍的关闭电脑睡觉。接到先前公司的老板的一个需求,他们用Unity做的应用软件,有一个需求:用二维码作为应用激活密钥,一个二维码能激活五台设备,当激活设备数目大于5该密钥失效。鉴于之前老板先前待我还可以,就当还个人情,帮他完成该需求。先前做过Unity的扫码的客户端,也有记录过相关文章(javascript:void(0)/article/details/25086835)。这里就简单记录一下开发流程。

一、数据库表的设计

二维码作激活码(密钥)功能开发_密钥验证

canbeuse bool值标记该二维码密钥是否失效,当然我下面T-SQL写的逻辑是当该密钥失效直接删除该密钥信息,所以该字段就没多大意义,以备有需要时使用!

二、存储过程(T-SQL)设计

-------------------校验qrcode是否可用存储过程----------------------------------
alter PROCEDURE searchproc
@qrcodetext nvarchar(50),
@result bit output
AS
begin
declare @count int, @selectrows int
select * from dbo.QRCodeTB where qrcodetext = @qrcodetext;
set @selectrows = @@ROWCOUNT
if @selectrows > 0
	begin 
		select @count = cast(usednum as int) from dbo.QRCodeTB where qrcodetext = @qrcodetext;
		if @count < 5 
			begin
				set @count = @count + 1
				update dbo.QRCodeTB set usednum = @count where qrcodetext = @qrcodetext
				set @result = 1
			end
		else
			begin
				--update dbo.QRCodeTB set canbeuse = 0 where qrcodetext = @qrcodetext
				delete from dbo.QRCodeTB where qrcodetext = @qrcodetext
				set @result=0
			end
	end
else
	begin
		set @result = 0
	end
end
GO
-----------------------------执行验证-------------------------------------
declare @result bit
exec searchproc 'ED81D6FF-86A3-49C1-BF40-1A05521803DC',@result output;
select @result

select * from dbo.QRCodeTB

--------------------------------添加记录存储过程--------------------
alter PROCEDURE insertoneinfoproc
@num int,
@count int output
AS
begin
while @num > 0
	begin
		insert into dbo.QRCodeTB(qrcodetext,canbeuse,usednum) values(NEWID(),1,0)
		set @num = @num - 1
	end
	set @count = @@ROWCOUNT
end
go
declare @count int
exec insertoneinfoproc 1,@count output ;
select @count;
select * from dbo.QRCodeTB

-------------------------添加数据--------------------------------------------------
insert into dbo.QRCodeTB(qrcodetext,canbeuse,usednum) values(NEWID(),1,0)
-------------------------查询数据------------------------------------------
select * from dbo.QRCodeTB
-------------------------清空数据表--------------------------------------
Truncate Table dbo.QRCodeTB

存储过程执行结果:

二维码作激活码(密钥)功能开发_unity二维码开发_02

连续运行五次之后:

二维码作激活码(密钥)功能开发_二维码_03


显示该密钥不可使用。貌似之前都一直没尝试过写T-QSL,这也算我第一次尝试写这么长的sql,在大神眼里这太小菜了哈!

web端设计

web采用的是.net一般处理程序

1.webconfig数据库信息配置

二维码作激活码(密钥)功能开发_密钥验证_04

2.简单的sqlhelper类

using System.Configuration;
using System.Data;
using System.Data.SqlClient;

namespace SQLHelper
{
    class SQLHelper
    {
        private static readonly string connectstr = ConfigurationManager.ConnectionStrings["SqlConnStr"].ConnectionString;
        public static SqlConnection CreateConnection()
        {
            SqlConnection conn = new SqlConnection(connectstr);
            conn.Open();
            return conn;
        }
        public static int ExecuteNonQuery(SqlConnection conn, string sql, params SqlParameter[] parameters)
        {
            using (SqlCommand cmd = conn.CreateCommand())
            {
                cmd.CommandText = sql;
                cmd.Parameters.AddRange(parameters);
                return cmd.ExecuteNonQuery();
            }
        }
        public static int ExecuteNonQuery(string sql,params SqlParameter[] parameters)
        {
            using (SqlConnection conn = CreateConnection())
            {
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sql;
                    cmd.Parameters.AddRange(parameters);
                    return cmd.ExecuteNonQuery();
                }
            }
        }
        public static int ExecuteNonQuery(string sql, CommandType type, params SqlParameter[] parameters)
        {
            using (SqlConnection conn = CreateConnection())
            {
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sql;
                    cmd.CommandType = type;
                    cmd.Parameters.AddRange(parameters);
                    return cmd.ExecuteNonQuery();
                }
            }
        }
        /// <summary>
        /// 执行带输入输出参数的存储过程
        /// </summary>
        /// <returns></returns>
        public static string ExecuteNonQuery(string procname,  int outputindex, params SqlParameter[] parameters)
        {
            using (SqlConnection conn = CreateConnection())
            {
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = procname;
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddRange(parameters);
                    int executeEffectNum = cmd.ExecuteNonQuery();
                    return parameters[outputindex].Value.ToString(); //返回第一个输出参数
                }
            }
        }
        public static object ExecuteScalar(SqlConnection conn, string sql, params SqlParameter[] parameters)
        {
            using (SqlCommand cmd = conn.CreateCommand())
            {
                cmd.CommandText = sql;
                cmd.Parameters.AddRange(parameters);
                return cmd.ExecuteScalar();
            }
        }
        public static object ExecuteScalar(string sql, params SqlParameter[] parameters)
        {
            using (SqlConnection conn = CreateConnection())
            {
                return ExecuteScalar(conn, sql, parameters);
            }
        }
        public static DataTable ExecuteQuery(SqlConnection conn, string sql, params SqlParameter[] parameters)
        {
            DataTable table = new DataTable();
            using (SqlCommand cmd = conn.CreateCommand())
            {
                cmd.CommandText = sql;
                cmd.Parameters.AddRange(parameters);
                using (SqlDataReader reader = cmd.ExecuteReader())
                {
                    table.Load(reader);
                }
                return table;
            }
        }
        public static DataTable ExecuteQuery(string sql, params SqlParameter[] parameters)
        {
            using (SqlConnection conn = CreateConnection())
            {
                return ExecuteQuery(conn, sql, parameters);
            }
        }
    }
}

3.二维码生成

二维码作激活码(密钥)功能开发_Unity_05

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using SQLHelper;
using System.Data;
using System.Data.SqlClient;
using ThoughtWorks.QRCode.Codec;
using System.IO;
using System.Text;

namespace WebApplication
{
    public partial class CreateQRCode : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// 创建一个二维码密钥
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void CraeteQRCodeBtn_Click(object sender, EventArgs e)
        {
            string path = Server.MapPath("~/images" + "//qrpngfile");
            string name = "QRCode";
            //创建文件夹
            Directory.CreateDirectory(path);
            string sql = "select top 1 qrcodetext from dbo.QRCodeTB";
            string qrcode = SQLHelper.SQLHelper.ExecuteScalar(sql).ToString();
            if (!string.IsNullOrEmpty(qrcode) && !createImage(qrcode, path, name))
            {
                Label1.Text = name + "已经存在";
            }
        }

        /// <summary>
        /// 向数据库添加一条二维码记录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void CreateUIDBtn_Click(object sender, EventArgs e)
        {
            int num = 1;
            SqlParameter[] paras ={  
                                     new SqlParameter("@num",SqlDbType.Int,1){
                                         Value=1
                                     },   new SqlParameter("@count", SqlDbType.Int),
                                 };
            paras[1].Direction = ParameterDirection.Output;
            this.Label1.Text = "开始执行";
            int rowseffect = SQLHelper.SQLHelper.ExecuteNonQuery("insertoneinfoproc", CommandType.StoredProcedure, paras);
            if (rowseffect > 0)
                this.Label1.Text = "插入成功";
            else
                this.Label1.Text = "插入失败";
        }

        #region 生成二维码
        /// <summary>
        /// 生成二维码
        /// </summary>
        /// <param name="path">地址</param>
        /// <param name="name">图片名称</param>
        /// <returns>bool</returns>
        public bool createImage(string value, string path, string name)
        {
            QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();
            //设置背景颜色
            //qrCodeEncoder.QRCodeBackgroundColor = Color.FromArgb(255, 255, 0);
            //设置前景色
            //qrCodeEncoder.QRCodeForegroundColor = Color.GreenYellow;
            //编码格式
            qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;

            //设置每个二维码像素点的大小
            qrCodeEncoder.QRCodeScale = 4;
            //QR码版本
            //QR码所允许规格系列为21×21模块(版本1)~177×177模块(版本40)
            qrCodeEncoder.QRCodeVersion = 8;
            //纠错等级
            //level L : 最大 7% 的错误能够被纠正; 
            //level M : 最大 15% 的错误能够被纠正;  
            //level Q : 最大 25% 的错误能够被纠正;  
            //level H : 最大 30% 的错误能够被纠正;
            qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;

            //自定义的二维码数据
            String data = value;
            //Response.Write(data);
            //画图
            System.Drawing.Bitmap image = qrCodeEncoder.Encode(data);

            System.IO.MemoryStream MStream = new System.IO.MemoryStream();

            image.Save(MStream, System.Drawing.Imaging.ImageFormat.Png);

            //Response.ClearContent();

            Response.ContentType = "image/Png";
            //写图片到页面
            Response.BinaryWrite(MStream.ToArray());
            path = path + "\\" + name + ".png";
            if (!File.Exists(path))
            {
                FileStream fs = new FileStream(path, FileMode.CreateNew, FileAccess.ReadWrite);
                BinaryWriter bw = new BinaryWriter(fs, UTF8Encoding.UTF8);
                byte[] by = MStream.ToArray();
                for (int i = 0; i < MStream.ToArray().Length; i++)
                    bw.Write(by[i]);
                fs.Close();
                return true;
            }
            else
                return false;
        }
        #endregion
    }
}



4.二维码验证

这里采用的是get请求方式,方便测试,安全起见最好用post请求

using System.Data;
using System.Data.SqlClient;
using System.Web;

namespace WebApplication
{
    /// <summary>
    /// CheckCode 的摘要说明
    /// </summary>
    public class CheckCode : IHttpHandler
    {

        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";
            //context.Request.Form["codetext"];//post
            string codetext = context.Request.QueryString["codetext"];  //get
            if (codetext != null)
            {
                SqlParameter[] parameters = {
                    new SqlParameter("@qrcodetext", SqlDbType.NVarChar,50),
                    new SqlParameter("@result", SqlDbType.Bit),
                };
                parameters[0].Value = codetext;
                parameters[1].Direction = ParameterDirection.Output;
                int outputindex = 1;
                string resNum = SQLHelper.SQLHelper.ExecuteNonQuery("searchproc", outputindex, parameters);
                context.Response.Write(resNum);
            }
            else
            {
                context.Response.Write("没有输入二维码信息");
            }
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

web验证


创建密钥二维码:



二维码作激活码(密钥)功能开发_Unity二维码_06



点击生成密钥二维码



二维码作激活码(密钥)功能开发_Unity二维码_07



服务器端密钥验证:



二维码作激活码(密钥)功能开发_Unity二维码_08



当密钥使用五次之后,返回给客户端的是false结果,也就是密钥已失效,同事服务器做的就是从数据库表中删除带密钥信息!

二维码作激活码(密钥)功能开发_Unity二维码_09


关于Unity扫码客户端的就不记录了,之前有过相关记载,就主要用到www提交表单,还有扫码插件制作(请看下面相关连接有记载),其他就没啥了。天色已晚,承诺某人今天早点睡的,貌似又食言了,sorry!貌似这两周都睡的比较晚,明天周末了,好好补一觉!

相关连接:



Unity客户端效果:

二维码作激活码(密钥)功能开发_Unity_10


==================== 迂者 丁小未===============


====================== 相互学习,共同进步 ===================