微信支付之微信模板消息推送
 

        
        今天我要跟大家分享的是“模板消息”的推送,这玩意呢,你说用途嘛,那还是真真的牛逼呐。原因在哪?就是因为它是依赖微信生存的呀,所以他能不牛逼吗?现在的社会,人多多少少都有或轻或重的“强迫症”。就是,看到有未读消息,都要去看一下。特别是现在的微信,大部分可以几个小时不看手机QQ有没有新消息来,但是这大部分人绝对做不到一个小时不看微信有没有消息来。现在的微信,真特么是神一样的存在,几乎人人手机上都会有微信。而且,如果你的公众号是服务号的话,这个推送消息会显示在首页列表中(如果有新的消息,会把公众号显示在最顶端,并提示有新消息),不像订阅好,会放在一个小盒子里面。成熟的例子也有许多,例如一些商业银行的刷卡消费提醒这些。好,这方面是他微信的优势,就是,you can't miss it.另外一个优势就是:只要你给他推送了,他的到达率是非常的高,几乎可以保证,100%送达(鉴于天朝的相关法规,这种100%的东西,是没人敢说的,所以,一般都和谐的说99.97%的样子)。所以,以这样的送达率,秒杀传统的短信通知。更有甚者,就是,他的推送,完全免费,完全免费,完全免费!而且,速度极快,速度极快,速度极快。。。好了,再说下去,估计等下你们以为我是腾讯的员工了。好了,这些我就不多说了,下面,我们进入主题吧。
 
        首先,新建一个MVC的项目,如下图(在第二个页面里面,身份认证,改为不需要身份验证):
 
 
        然后我们去把官方demo(demo地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1)中的business和lib拷贝到我们的项目中,并新建一个文件夹WxLib,放到里面去,如下图:
 
 
        然后我们再“重新生成”以下项目,或者快捷键:ctrl+shift+b,这时候,会提下如下错误:
 
 
这时候,我们去添加引用,把WxLib/lib文件夹中的LitJson.dll 添加上即可,如下图:
 
 
 
到这里,我们就基本把官方的demo的环境给搭建好了,接下来,我们就要开始编写代码了。
 
首先,我们来看看官方文档,怎么介绍这个模板消息的,查看步骤(这个是需要登录公众平台才能看到的),如下图:
 
 
 
        通过API文档,我们得知,我们推送模板消息,有三个必须要获取到的参数,他们分别是:ACCESS_TOKEN和OPENID,以及template_id,
ACCESS_TOKEN和OPENID,我们前面的额公众号支付已经演示过如何获取,如果忘了,可以回头看看(微信支付教程系列之公众号支付),
        
        下面,我来讲讲怎么获取这个template_id。template_id是模板消息的ID,我们推送消息,不像我们发短信一样,可以随意编辑内容,想说啥就说啥,必须要符合模板消息的规则。例如,我们这次选择一个“帐户资金变动提醒”,添加操作如下:
点击”添加“之后,就会在”我的模板”里面出现,如下图:
 
 
这个“lypG1jYyOEfYsr*********jOK7-LhEwpPeVNHHxemSI”就是我们的模板ID了,也就是:template_id。
 
        好,现在,我们知道ACCESS_TOKEN和OPENID以及template_id了,理论上,我们就有了可以发送推送消息的前提了。下面,我们来进入代码部分,如下:
 
 
        首先,新建一个HomeController.cs,代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace 微信支付之模板消息推送.Controllers
{
public class HomeController : Controller
{
// GET: Home
public ActionResult Index()
{
return View();
}
}
}
 
 
        然后添加一个View,代码如下:
         
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>
</div>
</body>
</html>
 
 
 
 
        再说多几句,我们这次选的是一个“帐户资金变动提醒”,他的传参类型如下:
 
在此之前:由于我们这里面的文字,还可以设定颜色,我们从这里(模板里面看不到,但是可以从官方的demo)可以看出来:
但是,我们本次用的模板不是这个,是“帐户资金变动提醒”,但是道理相同,所以,我们也要新建一个类,文件名字就叫做:DataFontStyle.cs吧,代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace 微信支付之模板消息推送.Models
{
public class DataFontStyle
{
public string value { get; set; }
public string color { get; set; }
}
}
再分析他的参数,分别有:first,date,adCharge,type,cashBalance以及remark,所以,我们给他新建一个Model,到时候会用到的,新建的Model的文件名字就叫做:CashModel.cs,代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web; namespace 微信支付之模板消息推送.Models
{
/// <summary>
/// 帐户资金变动提醒Model
/// </summary>
public class CashModel
{
public DataFontStyle first { get; set; }
public DataFontStyle date { get; set; }
public DataFontStyle adCharge { get; set; }
public DataFontStyle type { get; set; }
public DataFontStyle cashBalance { get; set; }
public DataFontStyle remark { get; set; }
}
}
 
 
 
 
此外,还有最后一个,那就是这个推送的Model,也要新建一个类,文件名,我们就叫做PushMess.cs吧,代码如下:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace 微信支付之模板消息推送.Models
{
public class PushMessage
{
public string touser { get; set; }
public string template_id { get; set; }
public string url { get; set; }
public string topcolor { get; set; }
/// <summary>
/// 注意,这里是CashModel,你如果要通用,有多个推送模板要用,那你就用object
/// </summary>
public CashModel data { get; set; } }
}
漏了一个类,现在补回来,我们命名为:WxResult.cs,代码如下:

   public class WxResult
{
public int? errcode { get; set; }
public string errmsg { get; set; }
public int? msgid { get; set; }
}
 
 
文件物理路径逻辑如下,检查一下,看看有无偏差,如下图:
 
        说明一下:一些推送必须的代码,我就直接贴出(例如后去Access_token和推送代码),不再说明了,因为在前面几篇都有说明,如果看不懂,请翻阅前面的教程。
 
        现在,我们来编辑一下前后端的代码,前端的代码的逻辑,还是跟往常一样,我代码尽量精简,本次,那个推送,我只传一个参数到后台,那就是first,其他的,都是在后台固定,实际项目中应用,到时候,你们再行修改即可,前台代码:
 
 
@{
Layout = null;
} <!DOCTYPE html> <html>
<head>
<meta name="viewport" content="width=device-width" />
<title>身份认证</title>
<link href="~/Scripts/jquery-easyui-1.4.5/themes/bootstrap/easyui.css" rel="stylesheet" />
<link href="~/Scripts/jquery-easyui-1.4.5/themes/mobile.css" rel="stylesheet" />
<link href="~/Scripts/jquery-easyui-1.4.5/themes/icon.css" rel="stylesheet" />
<style type="text/css"> .line {
width: 100%;
float: left;
height: auto;
text-align: center;
margin-top: 15pt;
font-size: x-large;
} .lineText {
width: 100%;
float: left;
height: auto;
text-indent: 5%;
text-align: left;
font-size: x-large;
margin: 0;
} a {
text-decoration: none;
color: white;
} .input {
height: 30pt;
width: 90%;
font-size: x-large;
border-radius: 10px;
margin: 0;
padding: 0;
} .btn {
width: 90%;
height: 35pt;
font-size: x-large;
background-color: green;
color: white;
border: none;
border-radius: 10px;
}
</style>
</head>
<body>
<div style="width: 100%; text-align: center;">
<form id="form1">
<div class="line">
<div class="lineText">*接收者openid:</div>
</div>
<div class="line">
<input type="text" id="openid" name="openid" class="input" />
</div>
<div class="line">
<div class="lineText">*first.DATA:</div>
</div>
<div class="line">
<input type="text" id="first" name="first" class="input" />
</div>
</form> </div>
<div class="line">
<input type="button" id="btnSave" class="btn" value="推送" onclick="fPush()" />
</div>
<script src="~/Scripts/jquery-easyui-1.4.5/jquery.min.js"></script>
<script src="~/Scripts/jquery-easyui-1.4.5/jquery.easyui.min.js"></script>
<script src="~/Scripts/jquery-easyui-1.4.5/jquery.easyui.mobile.js"></script>
<script src="~/Scripts/jquery-easyui-1.4.5/easyloader.js"></script>
<script type="text/javascript">
$(function () {
var vCode = getQueryString("code");
if (vCode != "" && vCode != null) {
$.ajax({
type: 'post',
data: {
code: vCode
},
url: '/Home/getWxInfo',
success: function (sjson) {
$.messager.show({
title: '提示',
msg: '欢迎您的到来(看到这个提示,代表已经成功获取openid和access_token了)。'
});
$("#openid").val(sjson.openid);
}
})
}
else {
$.ajax({
type: 'post',
url: '/Home/getCode',
success: function (sjson) {
location.href = sjson;
}
})
}
})
//获取url的参数
function getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]); return null;
} //推送
function fPush() {
var vTtile = $("#first").val();
$.ajax({
type: 'post',
data: {
first: vTtile
},
url: '/Home/Push',
success: function (sjson) {
if (sjson.result) {
$.messager.alert("提示", sjson.msg, 'info');
}
else {
$.messager.alert("提示", sjson.msg, 'warning');
}
}
})
}
</script>
</body>
</html>
 
 
后台代码:
 
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using WxPayAPI;
using 微信支付之模板消息推送.Models; namespace 微信支付之模板消息推送.Controllers
{
public class HomeController : Controller
{
JsApiPay jsApiPay = new JsApiPay(); JavaScriptSerializer JsonHelper = new JavaScriptSerializer();
/// <summary>
/// 最后更新Access_token的时间
/// </summary>
public static DateTime dtAccess_token;
/// <summary>
/// Access_token的值
/// </summary>
public static string strAccess_token;
// GET: Home
public ActionResult Index()
{
if (Session["openid"] == null)
{
try
{
//调用【网页授权获取用户信息】接口获取用户的openid和access_token
GetOpenidAndAccessToken(); }
catch (Exception ex)
{
//Response.Write(ex.ToString());
//throw;
}
}
return View();
} /**
*
* 网页授权获取用户基本信息的全部过程
* 详情请参看网页授权获取用户基本信息:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
* 第一步:利用url跳转获取code
* 第二步:利用code去获取openid和access_token
*
*/
public void GetOpenidAndAccessToken()
{
if (Session["code"] != null)
{
//获取code码,以获取openid和access_token
string code = Session["code"].ToString();
Log.Debug(this.GetType().ToString(), "Get code : " + code);
jsApiPay.GetOpenidAndAccessTokenFromCode(code);
}
else
{
//构造网页授权获取code的URL
string host = Request.Url.Host;
string path = Request.Path;
string redirect_uri = HttpUtility.UrlEncode("http://" + host + path);
WxPayData data = new WxPayData();
data.SetValue("appid", WxPayConfig.APPID);
data.SetValue("redirect_uri", redirect_uri);
data.SetValue("response_type", "code");
data.SetValue("scope", "snsapi_base");
data.SetValue("state", "STATE" + "#wechat_redirect");
string url = "https://open.weixin.qq.com/connect/oauth2/authorize?" + data.ToUrl();
Log.Debug(this.GetType().ToString(), "Will Redirect to URL : " + url);
Session["url"] = url;
}
} /// <summary>
/// 获取code
/// </summary>
/// <returns></returns>
[HttpPost]
public ActionResult getCode()
{
object objResult = "";
if (Session["url"] != null)
{
objResult = Session["url"].ToString();
}
else
{
objResult = "url为空。";
}
return Json(objResult);
} /// <summary>
/// 通过code换取网页授权access_token和openid的返回数据
/// </summary>
/// <returns></returns>
[HttpPost]
public ActionResult getWxInfo()
{
object objResult = "";
string strCode = Request.Form["code"];
string strAccess_Token = "";
string strOpenid = "";
if (Session["access_token"] == null || Session["openid"] == null)
{
jsApiPay.GetOpenidAndAccessTokenFromCode(strCode);
strAccess_Token = Session["access_token"].ToString();
strOpenid = Session["openid"].ToString();
}
else
{
strAccess_Token = Session["access_token"].ToString();
strOpenid = Session["openid"].ToString();
}
objResult = new { openid = strOpenid, access_token = strAccess_Token };
return Json(objResult);
} /// <summary>
/// 推送
/// </summary>
/// <returns></returns>
[HttpPost]
public ActionResult Push()
{
object objResult = "";
string strFirst = Request.Form["first"];
string strMsg = "";
bool bResult = false;
//这个是推送消息的类
PushMessage aPushMessage = new PushMessage()
{
template_id = "lypG1jYyOEfY********OK7-LhEwpPeVNHHxemSI",//模板ID
//data=,//暂时不赋值
topcolor = "#FF0000",//头部颜色
touser = Session["openid"].ToString(),//用户的Openid
url = "http://www.baidu.com"//用途是当用户点击推送消息的时候,会进入这个页面,具体用途,自己拓展
}; //构造要推送的内容
CashModel aCachData = new CashModel()
{
adCharge = new DataFontStyle()
{
color = "#589E63",
value = "对应变动金额"
},
cashBalance = new DataFontStyle()
{
color = "#589E63",
value = "对应帐户余额"
},
date = new DataFontStyle()
{
color = "#589E63",
value = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
},
first = new DataFontStyle()
{
color = "#589E63",
value = strFirst
},
remark = new DataFontStyle()
{
color = "#589E63",
value = "对应:点击“查看详情“立即查阅您的帐户财务记录。"
},
type = new DataFontStyle()
{
color = "#589E63",
value = "对应“现金”"
}
};
//这时候,把要推送的内容,赋值给push,这样,我们要推送的内容就完成了。
aPushMessage.data = aCachData; string strUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + GetLatestAccess_token(); string strJsonData = JsonHelper.Serialize(aPushMessage);
string strResult = HttpPost(strUrl, strJsonData);
WxResult aResult = JsonHelper.Deserialize<WxResult>(strResult);
if (aResult != null)
{
if (aResult.errcode == )
{
bResult = true;
}
else
{
bResult = false;
strMsg = aResult.errmsg;
}
}
else
{
bResult = false;
strMsg = "通讯失败,请重试。";
} objResult = new { result = bResult, msg = strMsg };
return Json(objResult);
} /// <summary>
/// HttpPost
/// </summary>
/// <param name="Url"></param>
/// <param name="postDataStr"></param>
/// <returns></returns>
public static string HttpPost(string Url, string postDataStr)
{
byte[] postData = Encoding.UTF8.GetBytes(postDataStr);//编码,尤其是汉字,事先要看下抓取网页的编码方式
WebClient webClient = new WebClient();
webClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded");//采取POST方式必须加的header,如果改为GET方式的话就去掉这句话即可
byte[] responseData = webClient.UploadData(Url, "POST", postData);//得到返回字符流
string srcString = Encoding.UTF8.GetString(responseData);//解码
return srcString; } /// <summary>
/// 返回最新的Access_token
/// </summary>
/// <returns></returns>
public string GetLatestAccess_token()
{
if (dtAccess_token == null || dtAccess_token <= DateTime.Now.AddHours(-) || string.IsNullOrWhiteSpace(strAccess_token))
{
string strUrl = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", WxPayConfig.APPID, WxPayConfig.APPSECRET);
string strAccess_tokenData = HttpGet(strUrl, "");
ModelForAccess_token aToken = JsonHelper.Deserialize<ModelForAccess_token>(strAccess_tokenData);
dtAccess_token = DateTime.Now;
strAccess_token = aToken.access_token;
return strAccess_token;
}
else
{
return strAccess_token;
}
} /// <summary>
/// WebGet
/// </summary>
/// <param name="Url"></param>
/// <param name="postDataStr"></param>
/// <returns></returns>
public static string HttpGet(string Url, string postDataStr)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url + (postDataStr == "" ? "" : "?") + postDataStr);
request.Method = "GET";
request.ContentType = "text/html;charset=UTF-8"; HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream myResponseStream = response.GetResponseStream();
StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
string retString = myStreamReader.ReadToEnd();
myStreamReader.Close();
myResponseStream.Close(); return retString;
} public class ModelForAccess_token
{
public string access_token { get; set; }
public int? expires_in { get; set; }
}
}
}
 
 
代码已完整提供,如果有缺漏的,请在评论中指出或者进群来告诉我。如果代码提供正常,应该就能推送到的了,目前这个代码,只能给自己推送。实际应用中,可以通过这个页面,然后绑定用户,这样,我们就可以通过用户名字,给他们的openid推送消息。下面贴出推送的截图
 
 
 
对了,忘记了一点,这个要发布到IIS上,然后你发布的域名,要在公众平台里面,那个获取用户权限(前面博文提及到)的网址里面,改成你发布的网址,例如:push.lmx.ren ,否则是获取不到用户信息的。
 
 
 
 
      到这里,就大功告成啦,接下来的东西,就由大家自己去展开拓展了,本次经验分享到此结束,写过博客的人都知道,好好写一个博客,需要自己从头重新走一遍代码,所以,各种辛苦,只有自己能体会。所以您如果觉得写得不错,或者对你有帮助,请点“好文要顶”或者“关注我”,顺带也可以评论一两句,大家互相交流交流,转载请保留原作者地址以及姓名
 
 

需要实时测试的,可以关注公众号,测试相关功能(根据实际情况,可能会不定时更新程序,如果需要最新程序的,可以加群联系,QQ群号在上面):
 
 
 
 
我新建一个QQ群,如果有问题,可以在群里提。如果合适,也会根据大家提的比较多的问题,来写篇博文,帮助更多的人,群号:275523437
点击链接加入群【.Net,MVC,EasyUI,MUI,Html,JS】:http://jq.qq.com/?_wv=1027&k=2A0RbLd
 
 
(如果有私活,或者一起合作的,也可以私信找我呀,嘿嘿);
 
 
作者:南宫萧尘  
E-mail:314791147@qq.com
QQ:314791147
日期:2016-05-31
 
 
 
 

鉴于网页篇幅较小,有些代码,我修改过后,有可能会漏贴到博文上,所以,为了让错误减值最少,我把代码包上传到QQ群了。
如果园友在开发过程中,有发现问题,可以到群里来下载相关的代码来校对,造成不便,请谅解。
 
最新动态,我已把代码上传到GitHub,其中一些敏感参数,就是config.cs里面的参数已删去,如果需要直接运行测试,请根据自身公众号信息,自行补全。
 
地址:https://github.com/Jeffrey9061/WeChatPush
 

【原创分享·微信支付】C# MVC 微信支付之微信模板消息推送的更多相关文章

  1. C# MVC 微信支付之微信模板消息推送

    微信支付之微信模板消息推送                    今天我要跟大家分享的是"模板消息"的推送,这玩意呢,你说用途嘛,那还是真真的牛逼呐.原因在哪?就是因为它是依赖微信 ...

  2. 前后端分离djangorestframework—— 接入微信模板消息推送

    微信 什么是微信也不多说,跟前面的支付宝一样的 微信支付 微信支付也有个沙箱环境,沙箱环境官方文档 由文档中那句很显眼的话所得,即使是测试环境也需要真实的商户号,所以这个就没法想支付宝那样用沙箱账号来 ...

  3. java开发微信模板消息推送

    发布时间:2018-12-12   技术:springboot+maven   概述 该demo主要涉及微信模板消息推送功能, 详细 代码下载:http://www.demodashi.com/dem ...

  4. ASP.NET 微信公众平台模板消息推送功能完整开发

    最近公众平台的用户提出了新需求,他们希望当收到新的邮件或者日程的时候,公众平台能主动推送一条提醒给用户.看了看平台提供的接口,似乎只有[模板消息]能尽量满足这一需求,但不得不说微信提供的实例太少,而且 ...

  5. 微信小程序之模板消息推送

    最近在用sanic框架写微信小程序,其中写了一个微信消息推送,还挺有意思的,写了个小demo 具体见官方文档:https://developers.weixin.qq.com/miniprogram/ ...

  6. qhfl-9 微信模板消息推送

    开发中用的是测试号 微信公众号认证流程 用户登陆 <!DOCTYPE html> <html lang="en"> <head> <met ...

  7. Java对接微信公众号模板消息推送

    内容有点多,请耐心! 最近公司的有这个业务需求,又很凑巧让我来完成: 首先想要对接,先要一个公众号,再就是开发文档了:https://developers.weixin.qq.com/doc/offi ...

  8. 微信小程序:模板消息推送提示{“errcode”:41030,”errmsg”:”invalid page hint: [gP1eXXXXXX]”}

    在开发小程序 模板消息定时推送功能时,在开发版测试程序功能运行正常,但提交到线上后提示报错{“errcode”:41030,”errmsg”:”invalid page hint: [gP1eXXXX ...

  9. C#微信公众号开发系列教程五(接收事件推送与消息排重)

    微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...

随机推荐

  1. 从RPC开始(一)

    这是一篇关于纯C++RPC框架的文章.所以,我们先看看,我们有什么? 1.一个什么都能干的C++.(前提是,你什么都干了) 2.原始的Socket接口,还是C API.还得自己去二次封装... 3.C ...

  2. ASP.NET Core应用的错误处理[3]:ExceptionHandlerMiddleware中间件如何呈现“定制化错误页面”

    DeveloperExceptionPageMiddleware中间件利用呈现出来的错误页面实现抛出异常和当前请求的详细信息以辅助开发人员更好地进行纠错诊断工作,而ExceptionHandlerMi ...

  3. PHP数据类型之间的强制转换

    1.实型数据强制转换为整型数据 $float1=2.7; $int1=(int)$float1; echo var_dump($int1),"<br>"; 输出: in ...

  4. ASP.NET MVC5+EF6+EasyUI 后台管理系统(63)-Excel导入和导出-自定义表模导入

    系列目录 前言 上一节使用了LinqToExcel和CloseXML对Excel表进行导入和导出的简单操作,大家可以跳转到上一节查看: ASP.NET MVC5+EF6+EasyUI 后台管理系统(6 ...

  5. EditText 基本用法

    title: EditText 基本用法 tags: EditText,编辑框,输入框 --- EditText介绍: EditText 在开发中也是经常用到的控件,也是一个比较必要的组件,可以说它是 ...

  6. iOS开发之Masonry框架源码深度解析

    Masonry是iOS在控件布局中经常使用的一个轻量级框架,Masonry让NSLayoutConstraint使用起来更为简洁.Masonry简化了NSLayoutConstraint的使用方式,让 ...

  7. Android如何制作漂亮的自适布局的键盘

    最近做了个自定义键盘,但面对不同分辨率的机型其中数字键盘不能根据界面大小自已铺满,但又不能每种机型都做一套吧,所以要做成自适应,那这里主讲思路. 这里最上面的titlebar高度固定,下面输入的金额高 ...

  8. 无法访问org.springframework.core.NestedRuntimeException 找不到org.springframework.core.NestedRuntimeException的类文件

    在学习springAOP时,出现如下异常: 无法访问org.springframework.core.NestedRuntimeException 找不到org.springframework.cor ...

  9. Eclipse使用Git教程

    A:点击Window--->Show view--->other..--->Git Repositories--->[OK] B:克隆码云上的代码仓库 C:选择对应目录存储你的 ...

  10. Oracle常用SQL函数整理

    --返回ASCII码select  ASCII('A') "A的ASCII码" ,ASCII('a') "a的ASSCII码" from dual ; --反向 ...