您的位置:首页 > 其它

[置顶] 二维码作激活码(密钥)功能开发

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



连续运行五次之后:



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

web端设计

web采用的是.net一般处理程序
1.webconfig数据库信息配置



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.二维码生成



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验证

创建密钥二维码:


点击生成密钥二维码


服务器端密钥验证:


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



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

扫描二维码客户端:http://blog.csdn.net/dingxiaowei2013/article/details/25086835
Unity跟服务器交互(表单提交):http://blog.csdn.net/dingxiaowei2013/article/details/17115489

Unity客户端效果:



==================== 迂者 丁小未 CSDN博客专栏=================MyBlog:http://blog.csdn.net/dingxiaowei2013             MyQQ:1213250243Unity QQ群:375151422         cocos2dx QQ群:280818155====================== 相互学习,共同进步 ===================
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐