撸主是一个新手,最近几天在研究微信服务号交互,上网搜了搜C#的代码,再结合自己的习惯,下面把代码解析一下,其中有些代码非本人原创。

首先,你要有个公众服务号,只有服务号才可以自定义菜单,没有条件的可以申请订阅号,然后再申请测试服务号。

微信调用服务端的接口其实分为2个部分,第一,验证此消息是否是微信发出来的,这通过get参数获取,像这样"?signature=eebf87348f23a73debd0e8a4235bb4e798099365&echostr=5964279561876822008&timestamp=1388992504&nonce=1388667053",其中signature是验证签名,我们要做的就是把提交微信网站的token,timestamp和nonce参数通过计算签名与signature参数比对,如果正确则证明这个是微信官方的信息,具体的代码是这样的。

  1. public static bool VerifySignature(string token, string signature, string timeStamp, string nonce)
  2. {
  3. //基本检查
  4. if (string.IsNullOrEmpty(signature))
  5. {
  6. return false;
  7. }
  8. //签名验证
  9. string[] stringArray = { token, timeStamp, nonce };
  10. //排序
  11. Array.Sort(stringArray);
  12. //计算签名
  13. string calculatedSignature = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(
  14. string.Join(string.Empty, stringArray), System.Web.Configuration.FormsAuthPasswordFormat.SHA1.ToString());
  15.  
  16. return calculatedSignature != null && calculatedSignature.ToLower() == signature;
  17. }

如果验证通过的话一定要给微信返回信号,否则微信会认为无响应的。!

  1. /// <summary>
  2. /// 告知微信服务器,已通过验证
  3. /// </summary>
  4. public static void EchoPass()
  5. {
  6. //响应微信验证
  7. HttpContext.Current.Response.Write(HttpContext.Current.Request["echostr"]);
  8. HttpContext.Current.Response.Flush();
  9. }

其中参数echostr是微信服务器随机生成的,直接返回即可。

响应完成后就需要我们的应用程序来处理信息了,首先必须判断返回来的是哪种信息。

微信的信息种类有: 文本消息:text , 图片消息:image ,事件消息:event , 语音消息:voice ,视频消息: video ,地理位置消息:location ,链接消息:link

消息主体就是第二部分了,内容在Request.InputStream中,需要解析成xml文件,xml格式大概是这样的:

    

  1. <xml><ToUserName><![CDATA[收件人]]></ToUserName>
  2. <FromUserName><![CDATA[发件人]]></FromUserName>
  3. <CreateTime>1389084129</CreateTime>
  4. <MsgType><![CDATA[event]]></MsgType>
  5. <Event><![CDATA[CLICK]]></Event>
  6. <EventKey><![CDATA[ceshi1]]></EventKey>
  7. </xml>

上面的是一个事件的消息,事件就是点击服务号的自定义菜单。

接下来就是解析xml成具体的实例了,关于消息的处理我是这样解决的(一部分借鉴别人给的代码,再结合自己的习惯):

1.首先是定义个消息类

  1. /// <summary>
  2. /// 消息的父类
  3. /// </summary>
  4. public abstract class Message
  5. {
  6. /// <summary>
  7. /// 收信人
  8. /// </summary>
  9. public string ToUserName { get; set; }
  10. /// <summary>
  11. /// 发信人
  12. /// </summary>
  13. public string FromUserName { get; set; }
  14. /// <summary>
  15. /// 创建时间
  16. /// </summary>
  17. public long CreateTime { get; set; }
  18. /// <summary>
  19. /// 消息类型
  20. /// </summary>
  21. public string MsgType { get; set; }
  22.  
  23. /// <summary>
  24. /// 消息的类型:Send接收的消息,Reply发送的消息
  25. /// </summary>
  26. public MessageDirection Direction { get; set; }
  27. /// <summary>
  28. /// 将xml文档转换为具体的接收实例
  29. /// </summary>
  30. /// <param name="node"></param>
  31. /// <returns></returns>
  32. protected abstract Message Parse(XmlNode node);
  33.  
  34. public override string ToString()
  35. {
  36. return string.Empty;
  37. }
  38.  
  39. /// <summary>
  40. /// 得到具体的消息处理实例
  41. /// </summary>
  42. /// <param name="xmlStream"></param>
  43. /// <returns></returns>
  44. public static Message GetInstance(Stream xmlStream)
  45. {
  46. if (xmlStream == null || xmlStream.Length == 0)
  47. {
  48. return null;
  49. }
  50. //得到请求的内容
  51. byte[] bytes = new byte[xmlStream.Length];
  52. xmlStream.Read(bytes, 0, (int)xmlStream.Length);
  53. string xml = Encoding.UTF8.GetString(bytes);
  54. return GetInstance(xml);
  55. }
  56. /// <summary>
  57. /// 得到具体的消息处理实例
  58. /// </summary>
  59. /// <param name="xml"></param>
  60. /// <returns></returns>
  61. public static Message GetInstance(string xml)
  62. {
  63. XmlDocument doc = new XmlDocument();
  64. Message message = null;
  65. try
  66. {
  67. doc.LoadXml(xml);
  68. XmlNode firstNode = doc.FirstChild;
  69. if (firstNode == null)
  70. {
  71. return null;
  72. }
  73. //消息类型
  74. XmlNode tempNode = firstNode.SelectSingleNode("MsgType");
  75. if (tempNode == null)
  76. {
  77. return null;
  78. }
  79. message = GetInstance(tempNode);
  80. if (message != null)
  81. {
  82. return message.Parse(doc.FirstChild);
  83. }
  84. return message;
  85. }
  86. catch (Exception ex)
  87. {
  88. return null;
  89. }
  90. }
  91.  
  92. private static Message GetInstance(XmlNode node)
  93. {
  94. switch (node.InnerText)
  95. {
  96. case MessageType.Text: return new TextSendMessage();
  97. case MessageType.Image: return null;
  98. case MessageType.Link: return null;
  99. case MessageType.Location: return null;
  100. case MessageType.Music: return null;
  101. case MessageType.Video: return null;
  102. case MessageType.Voice: return null;
  103. case MessageType.Event: return new EventSendMessage();
  104. default: return null;
  105. }
  106. }
  107.  
  108. }

2.具体的消息类型,我就弄了个文本和事件,首先是文本:

  1. /// <summary>
  2. /// 处理消息类
  3. /// </summary>
  4. public abstract class TextMessage : Message
  5. {
  6. public TextMessage()
  7. {
  8. this.MsgType = MessageType.Text;
  9. }
  10. public string Content { get; set; }
  11.  
  12. protected override Message Parse(System.Xml.XmlNode node)
  13. {
  14. return null;
  15. }
  16.  
  17. }

消息分为接收的和回复的,先是接收的:

  1. /// <summary>
  2. /// 处理消息类
  3. /// </summary>
  4. public class TextSendMessage : TextMessage
  5. {
  6. public TextSendMessage()
  7. {
  8. this.Direction = MessageDirection.Send;
  9. }
  10.  
  11. public string MsgId { get; set; }
  12.  
  13. protected override Message Parse(XmlNode node)
  14. {
  15. //发送者
  16. XmlNode tempNode = node.SelectSingleNode("FromUserName");
  17. if (tempNode == null)
  18. {
  19. return null;
  20. }
  21. this.FromUserName = tempNode.InnerText;
  22. //接收者
  23. tempNode = node.SelectSingleNode("ToUserName");
  24. if (tempNode == null)
  25. {
  26. return null;
  27. }
  28. this.ToUserName = tempNode.InnerText;
  29. //创建时间
  30. tempNode = node.SelectSingleNode("CreateTime");
  31. if (tempNode == null)
  32. {
  33. return null;
  34. }
  35. this.CreateTime = Convert.ToInt64(tempNode.InnerText);
  36.  
  37. //消息内容
  38. tempNode = node.SelectSingleNode("Content");
  39. if (tempNode == null)
  40. {
  41. return null;
  42. }
  43. this.Content = tempNode.InnerText;
  44.  
  45. //消息ID
  46. tempNode = node.SelectSingleNode("MsgId");
  47. if (tempNode == null)
  48. {
  49. return null;
  50. }
  51. this.MsgId = tempNode.InnerText;
  52.  
  53. return this;
  54. }
  55.  
  56. public override string ToString()
  57. {
  58. return string.Format("<xml>" + Environment.NewLine +
  59. "<ToUserName><![CDATA[{0}]]></ToUserName>" + Environment.NewLine +
  60. "<FromUserName><![CDATA[{1}]]></FromUserName>" + Environment.NewLine +
  61. "<CreateTime>{2}</CreateTime>" + Environment.NewLine +
  62. "<MsgType><![CDATA[{3}]]></MsgType>" + Environment.NewLine +
  63. "<Content><![CDATA[{4}]]></Content>" + Environment.NewLine +
  64. "<MsgId>{5}</MsgId>" + Environment.NewLine +
  65. "</xml>", ToUserName, FromUserName, CreateTime, MsgType, Content, MsgId);
  66. }
  67. }

然后是回复的:

  1. public class TextReplyMessage:TextMessage
  2. {
  3. public TextReplyMessage()
  4. {
  5. this.Direction = MessageDirection.Reply;
  6. }
  7. public string FuncFlag { get; set; }
  8.  
  9. public override string ToString()
  10. {
  11. return string.Format("<xml>" + Environment.NewLine +
  12. "<ToUserName><![CDATA[{0}]]></ToUserName>" + Environment.NewLine +
  13. "<FromUserName><![CDATA[{1}]]></FromUserName>" + Environment.NewLine +
  14. "<CreateTime>{2}</CreateTime>" + Environment.NewLine +
  15. "<MsgType><![CDATA[{3}]]></MsgType>" + Environment.NewLine +
  16. "<Content><![CDATA[{4}]]></Content>" + Environment.NewLine +
  17. "<FuncFlag>{5}</FuncFlag>" + Environment.NewLine +
  18. "</xml>", ToUserName, FromUserName, CreateTime, MsgType, Content, FuncFlag);
  19. }
  20. }

接下来是事件处理:

  1. /// <summary>
  2. /// 事件的处理
  3. /// </summary>
  4. public abstract class EventMessage : Message
  5. {
  6. public EventMessage()
  7. {
  8. this.MsgType = MessageType.Event;
  9. }
  10.  
  11. public string Event { get; set; }
  12. public string EventKey { get; set; }
  13.  
  14. protected override Message Parse(XmlNode node)
  15. {
  16. //发送者
  17. XmlNode tempNode = node.SelectSingleNode("FromUserName");
  18. if (tempNode == null)
  19. {
  20. return null;
  21. }
  22. FromUserName = tempNode.InnerText;
  23. //接收者
  24. tempNode = node.SelectSingleNode("ToUserName");
  25. if (tempNode == null)
  26. {
  27. return null;
  28. }
  29. ToUserName = tempNode.InnerText;
  30. //创建时间
  31. tempNode = node.SelectSingleNode("CreateTime");
  32. if (tempNode == null)
  33. {
  34. return null;
  35. }
  36. CreateTime = Convert.ToInt64(tempNode.InnerText);
  37.  
  38. //事件(subscribe/unsubscribe/CLICK)
  39. tempNode = node.SelectSingleNode("Event");
  40. if (tempNode == null)
  41. {
  42. return null;
  43. }
  44. Event = tempNode.InnerText;
  45.  
  46. //事件Key(当Event=CLICK时,使用Key定位具体单击的是哪个菜单项)
  47. tempNode = node.SelectSingleNode("EventKey");
  48. if (tempNode == null)
  49. {
  50. return null;
  51. }
  52. EventKey = tempNode.InnerText;
  53. return this;
  54. }
  55.  
  56. public override string ToString()
  57. {
  58. return string.Format("<xml>" + Environment.NewLine +
  59. "<ToUserName><![CDATA[{0}]]></ToUserName>" + Environment.NewLine +
  60. "<FromUserName><![CDATA[{1}]]></FromUserName>" + Environment.NewLine +
  61. "<CreateTime>{2}</CreateTime>" + Environment.NewLine +
  62. "<MsgType><![CDATA[{3}]]></MsgType>" + Environment.NewLine +
  63. "<Event><![CDATA[{4}]]></Event>" + Environment.NewLine +
  64. "<EventKey>{5}</EventKey>" + Environment.NewLine +
  65. "</xml>", ToUserName, FromUserName, CreateTime, MsgType, Event, EventKey);
  66. }
  67. }

接收的事件信息

  1. public class EventSendMessage:EventMessage
  2. {
  3. public EventSendMessage()
  4. {
  5. this.Direction = MessageDirection.Send;
  6. }
  7. }

现在就弄了这些,上面的只是接收微信的信息,有接收就得有处理回发数据。

定义一个消息处理中心(这个是网上的代码。。。)

  1. /// <summary>
  2. /// 指令处理中心
  3. /// </summary>
  4. public class InstructionHandlingCenter
  5. {
  6. public List<Instruction> InstructionList { get; private set; }
  7. public InstructionHandlingCenter()
  8. {
  9. this.InstructionList = new List<Instruction>();
  10. }
  11. /// <summary>
  12. /// 指令注册
  13. /// </summary>
  14. /// <param name="instruction"></param>
  15. public void RegisterInstruction(Instruction instruction)
  16. {
  17. if (!this.InstructionList.Contains(instruction))
  18. {
  19. this.InstructionList.Add(instruction);
  20. }
  21. }
  22.  
  23. /// <summary>
  24. /// 根据请求获取返回消息
  25. /// </summary>
  26. /// <param name="requestMessage"></param>
  27. /// <returns></returns>
  28. public Message GetReplyMessage(Message requestMessage)
  29. {
  30. foreach (var instruction in InstructionList)
  31. {
  32. if (instruction.MatchWith(requestMessage))
  33. {
  34. return instruction.GetReplyInstance(requestMessage);
  35. }
  36. }
  37. return new TextReplyMessage
  38. {
  39. FromUserName = requestMessage.ToUserName,
  40. ToUserName = requestMessage.FromUserName,
  41. CreateTime = Convert.ToInt64(DateTime.Now.Ticks.ToString(System.Globalization.CultureInfo.InvariantCulture)),
  42. Content = "无效的指令请求!"
  43. };
  44. }
  45.  
  46. }

然后是处理回发数据的父类

  1. /// <summary>
  2. /// 处理回发数据
  3. /// </summary>
  4. public abstract class Instruction
  5. {
  6. public abstract string HelpMessage { get; }
  7. /// <summary>
  8. /// 检查指令是否与消息相匹配
  9. /// </summary>
  10. /// <param name="message"></param>
  11. /// <returns></returns>
  12. public abstract bool MatchWith(Message message);
  13.  
  14. /// <summary>
  15. /// 分析消息内容并返回对应响应值
  16. /// </summary>
  17. /// <param name="message"></param>
  18. /// <returns></returns>
  19. public abstract Message GetReplyInstance(Message message);
  20. }

我只弄了2个,一个文本,一个事件

文本:

  1. public class TextInstruction : Instruction
  2. {
  3. public override string HelpMessage
  4. {
  5. get
  6. {
  7. return "欢迎关注..........";
  8. }
  9. }
  10.  
  11. public override bool MatchWith(Message message)
  12. {
  13. return message is TextSendMessage;
  14. }
  15.  
  16. public override Message GetReplyInstance(Message message)
  17. {
  18. return new TextReplyMessage()
  19. {
  20. FromUserName = message.ToUserName,
  21. ToUserName = message.FromUserName,
  22. CreateTime = Convert.ToInt64(DateTime.Now.Ticks.ToString(System.Globalization.CultureInfo.InvariantCulture)),
  23. Content = HelpMessage,
  24. FuncFlag = ""
  25. };
  26. }
  27. }

事件:

  1. /// <summary>
  2. /// 事件处理
  3. /// </summary>
  4. public class EventInstruction : Instruction
  5. {
  6.  
  7. private string _helMessage = "事件触发";
  8. public override string HelpMessage
  9. {
  10. get { return this._helMessage; }
  11. }
  12.  
  13. public override bool MatchWith(Message message)
  14. {
  15. return message is EventSendMessage;
  16. }
  17.  
  18. public override Message GetReplyInstance(Message message)
  19. {
  20. EventSendMessage esm = message as EventSendMessage;
  21. this._helMessage = esm.EventKey;
  22. return new TextReplyMessage()
  23. {
  24. FromUserName = message.ToUserName,
  25. ToUserName = message.FromUserName,
  26. CreateTime = Convert.ToInt64(DateTime.Now.Ticks.ToString(System.Globalization.CultureInfo.InvariantCulture)),
  27. Content = HelpMessage,
  28. FuncFlag = ""
  29. };
  30. }
  31. }

具体的逻辑自己控制。

这样,整体就基本完成了。

下面是调用:

  1. /// <summary>
  2. /// WeiXinApi 的摘要说明
  3. /// </summary>
  4. public class WeiXinApi : IHttpHandler
  5. {
  6. //微信服务号
  7. protected readonly string WeiXinServerNo = "???";
  8. //注册时指定的Token
  9. protected readonly string Token = "???";
  10.  
  11. //指令处理中心
  12. private readonly InstructionHandlingCenter _instructionHandler = new InstructionHandlingCenter();
  13.  
  14. public void ProcessRequest(HttpContext context)
  15. {
  16. Save("ok", "test.txt");
  17.  
  18. Uri uri = context.Request.Url;
  19. if (uri != null)
  20. {
  21. Save(uri.PathAndQuery + "\r\n", "uri.txt");
  22. }
  23.  
  24. var stream = context.Request.InputStream;
  25. string result = null;
  26. if (stream != null && stream.Length > )
  27. {
  28. var bytes = new byte[stream.Length];
  29. stream.Read(bytes, , (int)stream.Length);
  30. result = Encoding.UTF8.GetString(bytes);
  31. Save(result, "xml.txt");
  32. }
  33.  
  34. //初始化变量
  35. InitializeVariables();
  36.  
  37. //验证签名
  38. if (!WeiXinCommon.VerifySignature(Token))
  39. {
  40. context.Response.Write("验证签名错误");
  41. Save("验证签名错误", "result.txt");
  42. return;
  43. }
  44.  
  45. //响应微信验证
  46. WeiXinCommon.EchoPass();
  47.  
  48. if (context.Request.InputStream == null || context.Request.InputStream.Length == )
  49. {
  50. Save("InputStream没有", "result.txt");
  51. return;
  52. }
  53.  
  54. //获取指令请求
  55. Message requestMessage = Message.GetInstance(result);
  56.  
  57. if (requestMessage == null)
  58. {
  59. context.Response.Write("获取指令请求为null(requestMessage)");
  60. Save("获取指令请求为null(requestMessage)", "result.txt");
  61. return;
  62. }
  63.  
  64. var replyMessage = _instructionHandler.GetReplyMessage(requestMessage);
  65. if (replyMessage == null)
  66. {
  67. context.Response.Write("获取指令请求为null(replyMessage)");
  68. Save("获取指令请求为null(replyMessage)", "result.txt");
  69. return;
  70. }
  71. WeiXinCommon.SendReplyMessage(replyMessage);
  72. Save(replyMessage.ToString(), "result.txt");
  73.  
  74. }
  75.  
  76. public bool IsReusable
  77. {
  78. get
  79. {
  80. return false;
  81. }
  82. }
  83.  
  84. //初始化变量
  85. private void InitializeVariables()
  86. {
  87. //初始化可处理的指令列表
  88. if (_instructionHandler.InstructionList.Count == )
  89. {
  90. _instructionHandler.RegisterInstruction(new TextInstruction());
  91. _instructionHandler.RegisterInstruction(new EventInstruction());
  92. }
  93. }
  94.  
  95. private void Save(string value, string fileName)
  96. {
  97. using (Stream stream = File.Open(HttpContext.Current.Server.MapPath(fileName), FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write))
  98. {
  99. using (StreamWriter writer = new StreamWriter(stream, System.Text.Encoding.UTF8))
  100. {
  101. writer.WriteLine(value);
  102. }
  103. }
  104. }
  105.  
  106. }

大概就这样了,其实处理流程很简单,就是  验证-->通过的话告诉微信--> 接收消息,判断是什么类型的数据-->发给微信-->微信会根据ToUserName推送给指定的用户。

下面是代码附件:

http://files.cnblogs.com/pokemon/WeiXinDemo.rar

小弟只是一个新手,大家多交流才能进步!

微信开发之.Net的更多相关文章

  1. 微信开发之Ngrok环境准备

    一.为什么要使用ngrok? 各位肯定都知道,做微信开发,我们的开发服务器需要和微信服务器做交互,SO,我们需要准备一台放置在公网的服务器,能够使得我们的服务器可以正常访问微信服务器,并且微信服务器也 ...

  2. 微信开发之Author网页授权

     微信开发中,经常有这样的需求:获得用户头像.绑定微信号给用户发信息.. 那么实现这些的前提就是授权!   1.配置安全回调域名: 在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的&q ...

  3. 微信开发之Ngrok环境准备(一)

    一.为什么要使用ngrok? 各位肯定都知道,做微信开发,我们的开发服务器需要和微信服务器做交互,SO,我们需要准备一台放置在公网的服务器,能够使得我们的服务器可以正常访问微信服务器,并且微信服务器也 ...

  4. thinkphp微信开发之jssdk图片上传并下载到本地服务器

    public function test2(){ $Weixin = new \Weixin\Controller\BaseController(); $this->assign('signPa ...

  5. 微信开发之SVN提交代码与FTP同步到apache的根目录

    SVN是协同开发的,版本控制器,就是几个人同时开发,可以提交代码到SVN服务器,这样就可以协同开发,一般是早上上班首先更新下代码,然后自己修改代码 工作一天之后,修改代码之后,下班之前,更新代码,然后 ...

  6. 微信开发之c#下jssdk签名生成

    参考文章 :微信JS-SDK 权限签名算法 C#版 这篇文章讲解的的比较详细,而且算法准确,但是这篇文章有几个错误的地方需要注意; url必须动态生成 url不能写死,否则就算结果和官方检测的一致,也 ...

  7. 微信开发之c#下获取jssdk的access_token

    获取access_token是调用微信JS接口的基础,只有得到了它才能得到我们需要的jsapi_ticket并生成签名,然后注入配置信息config. 微信官方文档我就不多做介绍,反正我是踩了不少坑. ...

  8. 微信开发之SSM环境搭建

    首先,感谢大神的文章,地址:http://blog.csdn.net/zhshulin/article/details/37956105# 第一步:新建maven项目 如有需要,查看之前的文章:从配置 ...

  9. 微信开发之web开发者工具

    web开发者工具. 有任何疑问或建议请私信我,或者在评论区大家一起探讨. 概述 为帮助开发者更方便.更安全地开发和调试基于微信的网页,我们推出了 web 开发者工具.它是一个桌面应用,通过模拟微信客户 ...

随机推荐

  1. spring核心框架体系结构

    很多人都在用spring开发java项目,但是配置maven依赖的时候并不能明确要配置哪些spring的jar,经常是胡乱添加一堆,编译或运行报错就继续配置jar依赖,导致spring依赖混乱,甚至下 ...

  2. Linux(CentOS 6.5)下配置Mono和Jexus并且部署ASP.NET MVC5

    1.开篇说明 a. 首先我在写这篇博客之前,已经在自己本地配置了mono和jexus并且成功部署了asp.net mvc项目,我也是依赖于在网上查找的各种资料来配置环境并且部署项目的,而其在网上也已有 ...

  3. centos install kafka and zookeeper

    1.安装zookeeper ZooKeeper is a distributed, open-source coordination service for distributed applicati ...

  4. js中的console很强大

    今天闲来没事,瞎逛, 发现了淘宝首页的这个: 想起来之前在百度的 页面中也曾看到过.于是乎自己试一试. 于是便见识到了console对象其实很强大,用好它对调试真的有很大帮助. 代码: <!DO ...

  5. appserv中php升级问题

    当前版本为2.1,要升级到2.3.4 那么,首先到http://windows.php.net/downloads/releases/archives/ 找到2.3.4,需要注意的是,一般我们是非nt ...

  6. Linux下Java开发环境搭建—CentOS下Mysql安装教程

    本人学习Linux时使用的是CentOs5.5版本,在该环境中,Mysql的安装方法有很多种,下面我只讲我这次成功了的方法,作为一个记录,供大家参考,同时给自己做一个笔记. MySQL下载 1.进入网 ...

  7. 虚拟化平台cloudstack(8)——从UI开始

    UI ucloudstack采用的是前后端分离的架构,就是说前端可以选择使用web.swing甚至其它的界面,都可以. 我们来看cloudstack的UI信息吧,所有的cloudstack的UI都在{ ...

  8. sql的OUTER APPLY

    今天写一个查询sql,其中涉及到一个银行卡绑定表(表名:BankBind),我要将这个表的开户行字段的值进行分割出省份.支行, 这个开户行字段存储的值如“广东省广东省分行江门市分行恩平市支行”.“招商 ...

  9. Oracle建表脚本记录

    --删除 drop table dianfei; --创建表 create table dianfei ( uon ) not null, mmonth ) not null, ddf ,) not ...

  10. DDD~领域事件应用篇(订单处理变得更清晰)

    回到目录 上一讲主要说了领域事件和领域总线,这并不是一个很容易理解的文章,所以本讲实例篇主要是为了补充上一讲的理论知识,本讲实例关注的是实际中的订单处理模块,我们知道,订单处理是电子商务的核心,往往在 ...