前两篇已把相应的准备工作和功能说明列了一下,今天就把详细的实现写一下,以后的将把13800138000的语音拨号系统,和手机短信群发的的实现也发上。
开始这次的内容。
首先就是需要用到模拟提交的两个类
HttpHead.cs 这个类(其实是结构)它的主要功能就是封装了Http请求的一个头信息
using System;
using System.Net;using System.Drawing;namespace NetHelper {
/// <summary> /// Http头信息设置 /// </summary> public struct HttpHead { public String Host; //主机 public String Referer; //引用 public CookieCollection Cookies; //cookies容器 public String PostData; //请求的传给服务器的参数 public String Method; //请求方式常见的POST,GET public String ContentType; public String Html; //响应的html代码 public String AbsoluteUri; public Bitmap Image; //如果请求的是图片,这里返回一个Bitmap对象 public Boolean IsImage; //是否为图片 }}HttpRequest.cs //用来发起提交的
namespace NetHelper {
using System; using System.Drawing; using System.IO; using System.Net; using System.Text;/// <summary>
/// Http请求封装类,包括 POST,GET请求 /// 幸福海 /// </summary> public class HttpRequest { private CookieContainer cookies; public CookieContainer Cookies { get { return this.cookies; } set { this.cookies = value; } } /// <summary> /// Http请求 /// 幸福海 /// </summary> public HttpRequest() { this.Cookies = new CookieContainer(); } /// <summary> /// 发送HTTP请求 /// </summary> /// <param name="Head">HTTP头结构</param> /// <returns></returns> public String Send(ref HttpHead Head) { HttpWebResponse Response = null; String val = ""; try { HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create(Head.Host); Request.ProtocolVersion = new Version("1.1"); Request.Referer = Head.Referer; Request.Accept = "*/*"; Request.CookieContainer = this.Cookies; Request.Timeout = 100000; Request.Headers.Add("Accept-Language", "zh-CN"); Request.KeepAlive = true; Request.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1;.NET CLR 2.0.50727)";if (Head.Method.ToLower() == "post") {
Request.Method = "POST"; if (String.IsNullOrEmpty(Head.ContentType)) { Request.ContentType = "application/x-www-form-urlencoded"; } else { Request.ContentType = Head.ContentType; } if (Head.PostData != null && Head.PostData.Length > 0) { Byte[] byteData = Encoding.Default.GetBytes(Head.PostData); Request.ContentLength = byteData.Length; Stream WriteStream = Request.GetRequestStream(); WriteStream.Write(byteData, 0, byteData.Length); WriteStream.Close(); } } try { Response = (HttpWebResponse)Request.GetResponse(); } catch (WebException ex) { if (ex.Response != null) { Response = (HttpWebResponse)ex.Response; } else { return "网络异常"; } } foreach (Cookie cookie in Request.CookieContainer.GetCookies(Request.RequestUri)) { this.Cookies.Add(cookie); } Stream dataStream = Response.GetResponseStream(); if (Head.IsImage) { Bitmap img = new Bitmap(dataStream); Head.Image = img; return ""; } else { String encode = Response.CharacterSet; if (encode == null) encode = "gb2312"; if (encode.ToLower() == "iso-8859-1") encode = "gb2312"; StreamReader reader = new StreamReader(dataStream, Encoding.GetEncoding(encode)); val = reader.ReadToEnd(); Head.AbsoluteUri = Response.ResponseUri.AbsoluteUri; reader.Close(); dataStream.Close(); Response.Close(); Head.Html = val; } } catch { return "未知错误"; } return val; } }}这个类中最关键的是那个关联cookie,这里不详细说明,具体看代码,如果有不明白的地方,请提出来。
//开始提交联通卡密,这就是那个按钮对应的事件
private void BtnOk_Click(object sender, EventArgs e) { String strTel = tbTel.Text.Trim(); String strPass = tbPass.Text.Trim(); String Result = UnionCardPay(strTel, strPass); lblMsg.Text = BuilderErrMsg(Result); //显示充值信息 }
//重填输入框,重置按钮事件
private void BtnReset_Click(object sender, EventArgs e) { tbTel.Text = tbPass.Text = String.Empty; }
//字符串中获取指定开始和结束的子串
private String GetValue(string str, string s, string e) { Regex regex = new Regex("(?<=(" + s + "))[.\\s\\S]*?(?=(" + e + "))", RegexOptions.Multiline | RegexOptions.Singleline); return regex.Match(str).Value; }//对错误编码进行处理
private String BuilderErrMsg(String errCode) { String val = ""; switch (errCode) { case "001": val = "充值卡已使用"; break; case "002": val = "您输入的充值卡密码有误"; break; case "003": val = "您输入的交费充值号码不存在"; break; case "004": val = "请正确输入手机号码"; break; case "005": val = "验证码5次匹配不成功"; break; case "006": val = "充值卡已过期"; break; case "007": val = "充值失败"; break; case "008": val = "异常,或无法连接服务器"; break; case "888": val = "充值成功"; break; } return val; }//联通卡密提交
String UnionCardPay(String tel, String pass) { try { String result = ""; NetHelper.HttpHead head = new NetHelper.HttpHead(); NetHelper.HttpRequest request = new NetHelper.HttpRequest(); request.Cookies = new System.Net.CookieContainer();//充值初始化页
head.Host = ""; head.Method = "GET"; request.Send(ref head); result = head.Html; String state = GetValue(result, "name=\"secstate.state\" value=\"", "\" id=\"secstate.state\"/>");//自动过验证码
Int16 index = 1; while (1 == 1) { head.Host = "=" + DateTime.Now.ToString("yyyyMMddhhmmss"); head.IsImage = true; head.Method = "GET"; request.Send(ref head); Bitmap img = head.Image; CheckImage imgChk = new CheckImage(); String chk = imgChk.GetCheckCode(img);//提交充值号码和卡密
String para = "numbean.userNumBean.userSelNum=1&numbean.userNumBean.otherNum=" + tel + "&cardPwd=" + pass + "&verifyCode=" + chk; para += "&numbean.cityCodeBean.provinceId=&numbean.cityCodeBean.cityId=&numbean.cityCodeBean.cityCode=&numbean.userNumBean.telNum="; para += "&secstate.state=" + state; head.Host = ""; head.PostData = para; head.IsImage = false; head.Method = "POST"; head.Referer = ""; request.Send(ref head); result = head.Html; state = GetValue(result, "name=\"secstate.state\" value=\"", "\" id=\"secstate.state\"/>"); result = GetValue(result, "<div id='ecs_err_msg_div' class='ceng_jinshi' cssStyle='' align='left'>", "</div>");//提交状态 //状态处理 if (result.Contains("验证码不正确")) { // 验证码匹配5次不正确。 if (index++ >= 5) { return "005"; } else { continue; //重新跳转到验证码识别 } } break; }if (result.Contains("输入的充值卡已充值")) { //尊敬的用户您好,您输入的充值卡已充值,无法再次使用,请更换充值卡重新操作
return "001"; }if (result.Contains("您输入的充值卡密码有误")) { //尊敬的用户您好,您输入的充值卡密码有误,请重新输入。
return "002"; }if (result.Contains("您输入的交费充值号码不存在")) { // 尊敬的用户您好,您输入的交费充值号码不存在,请重新输入。
return "003"; }if (result.Contains("请正确输入手机号码")) { //请正确输入手机号码。
return "004"; }if (result.Contains("过期")) { //充值卡已过期。
return "006"; } //确认充值结果 head.Host = ""; head.Method = "POST"; head.PostData = "secstate.state=" + state; head.Cookies = request.Cookies.GetCookies(new Uri(head.Host)); head.Referer = ""; request.Send(ref head); result = head.Html; if (!result.Contains("<td>成功</td>")) { //最后一步没有完成,即充值失败 return "009"; } return "888"; } catch { return "009"; } }
全部代码就这些,这里主要是给大家整理思路,主要是通过C#向服务器提交数据
现把联通卡密提交的顺序说一下
1,当我们启动抓包工具,开始提交数据的时候,我们会看到,有几个参数提到了服务器端
这几个,名称看上去怪怪的,原因很简单,主是因为联通这个站是JAVA来写到了,用了Bean,所有看上去名称就比较上
其实对我们来说无所谓
numbean.userNumBean.userSelNum 如果是给手机充值这个是1,固话小灵通,宽带就为2
numbean.userNumBean.otherNum 手机号码cardPwd 卡密verifyCode 验证码,下面四个我们可以不管他了
numbean.cityCodeBean.provinceIdnumbean.cityCodeBean.cityIdnumbean.cityCodeBean.cityCodenumbean.userNumBean.telNum这个参数非常重要,也就是一个隐藏域的东西,估计是一个加密字符串充,如果错了,就提交不上了。
secstate.state
最后当我们点提交的时候,就可以得到相应的信息,假如你还要获取订单号,和充值的金额,你只对html源进行分析,截取就行了
OK,这个联通的卡密就写到这里,由于第一次写东西,没有什么思路,呵呵,想到哪就写到哪了,毕竟文学功底有限,希望以后写文章这方面的功能加强些,
如果大家对这个联通卡密自动提交还不是很清楚的话,可以随你给我发信息.
--幸福海
博客地址: