微信支付笔记
一、开发前的准备:
开发前需要配置支付授权目录,支付相关的页面全部要在这个指定的目录中,不能在子目录中。测试授权目录和测试白名单可以不用管。
二、微信支付开发前需要这几个参数:
1、AppID 在微信公众号管理后台(https://mp.weixin.qq.com/)的开发者中心获取
2、微信支付商户号 在微信公众号管理后台(https://mp.weixin.qq.com/)的 微信支付 菜单下可以看到
3、商户密匙 微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
三、微信公众号支付的逻辑是这样的:
1. 我们自己的系统生成待支付订单信息 [订单号、金额、商品名称、说明等信息]
2. 将系统的订单信息使用统一下单的数据格式提交到微信服务器 ,微信服务器会返回一个预支付交易会话标识 prepay_id
统一下单的API文档: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1
3. 使用公众号APPID和第二部返回的预支付交易会话标识 prepay_id,加上时间戳 timeStamp、 随机字符串nonceStr ,签名 paySign 生成js参数,在HTML页面里完成支付
网页端调起支付API文档: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6
4. 微信服务器异步通知我们服务器上的回调地址,完成支付
从第三部分的HTML页面讲起,我们看到官方文档中微信的网页支付的代码是这样的:
function onBridgeReady() {
WeixinJSBridge.invoke('getBrandWCPayRequest', {
"appId":"wx2421b1c4370ec43b",
//公众号名称,由商户传入
"timeStamp":" 1395712654",
//时间戳,自1970年以来的秒数
"nonceStr":"e61463f8efa94090b1f366cccfbbb444",
//随机串
"package":"prepay_id=u802345jgfjsdfgsdg888",
"signType":"MD5",
//微信签名方式:
"paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名
},
function(res) {
if (res.err_msg == "get_brand_wcpay_request:ok") {}
});
}
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
} else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
} else {
onBridgeReady();
}
注意:这个JS需要在微信浏览器里面直接调用,无需引用其他js文件,其他浏览器是不行的.
第一次看到这个js脚本的时候比较奇怪,这里怎么没有支付的金额、商品名称、订单号呢,后来才知道订单的信息是需要提前提交给微信服务器的,这个提交的过程就叫统一下单。
支付页面的Javascript代码很简单,只有这几个参数需要我们自己根据实际情况进行替换:
"appId":"wx2421b1c4370ec43b", //公众号名称,由商户传入 | 这个参数已知
"timeStamp":" 1395712654", //时间戳,自1970年以来的秒数 | 写个函数生成下即可,简单
"nonceStr":"e61463f8efa94090b1f366cccfbbb444", //随机串 | 写个函数生成下
"package":"prepay_id=u802345jgfjsdfgsdg888", //prepay_id 就是前面提到的支付交易会话标识,具体怎么生成在后面讲
"signType":"MD5", //微信签名方式:固定的,填写MD5即可
//微信签名 签名生成方法可见API文档 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3,我在文章后面会给出代码
"paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89"
我们先搞定最简单的部分:随机字符串和时间戳的生成C#实现
/// <summary> /// 随机串 /// </summary> public static string getNoncestr() { Random random = new Random(); return MD5Util.GetMD5(random.Next(1000).ToString(), "utf-8").ToLower().Replace("s", "S"); } /// <summary> /// 时间截,自1970年以来的秒数 /// </summary> public static string getTimestamp() { TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(ts.TotalSeconds).ToString(); }
现在只有prepay_id和paySign目前不知道怎么产生的,另外几个参数都搞定了。
prepay_id需要通过统一下单接口https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1获取到,我们看这个接口要传的参数有不少,新建一个UnifiedOrder类:
/// <summary> /// 微信统一接口请求实体对象 /// </summary> [Serializable] public class UnifiedOrder { /// <summary> /// 公共号ID(微信分配的公众账号 ID) /// </summary> public string appid = ""; /// <summary> /// 商户号(微信支付分配的商户号) /// </summary> public string mch_id = ""; /// <summary> /// 微信支付分配的终端设备号 /// </summary> public string device_info = ""; /// <summary> /// 随机字符串,不长于 32 位 /// </summary> public string nonce_str = ""; /// <summary> /// 签名 /// </summary> public string sign = ""; /// <summary> /// 商品描述 /// </summary> public string body = ""; /// <summary> /// 附加数据,原样返回 /// </summary> public string attach = ""; /// <summary> /// 商户系统内部的订单号,32个字符内、可包含字母,确保在商户系统唯一,详细说明 /// </summary> public string out_trade_no = ""; /// <summary> /// 订单总金额,单位为分,不能带小数点 /// </summary> public int total_fee = 0; /// <summary> /// 终端IP /// </summary> public string spbill_create_ip = ""; /// <summary> /// 订 单 生 成 时 间 , 格 式 为yyyyMMddHHmmss,如 2009 年12 月 25 日 9 点 10 分 10 秒表示为 20091225091010。时区为 GMT+8 beijing。该时间取自商户服务器 /// </summary> public string time_start = ""; /// <summary> /// 交易结束时间 /// </summary> public string time_expire = ""; /// <summary> /// 商品标记 商品标记,该字段不能随便填,不使用请填空,使用说明详见第 5 节 /// </summary> public string goods_tag = ""; /// <summary> /// 接收微信支付成功通知 /// </summary> public string notify_url = ""; /// <summary> /// JSAPI、NATIVE、APP /// </summary> public string trade_type = ""; /// <summary> /// 用户标识 trade_type 为 JSAPI时,此参数必传 /// </summary> public string openid = ""; /// <summary> /// 只在 trade_type 为 NATIVE时需要填写。 /// </summary> public string product_id = ""; }
用参数填充这个对象
//统一下单
UnifiedOrder order = new UnifiedOrder();
order.appid = "1111111111111111"; //公众账号ID,请替换成公众号实际的appid
order.mch_id = "111111111111111"; //调用接口提交的商户号,请替换成真实的商户号
order.device_info = "WEB"; //终端设备号(门店号或收银设备ID),注意:PC网页或公众号内支付请传"WEB" 固定值
order.nonce_str = TenpayUtil.getNoncestr(); //随机字符串,不长于32位,见前面的随机字符串函数 TenpayUtil代码后面给出
order.body = "xxxxxxx设备充值"; //商品或支付单简要描述
order.attach = "这是一个支付测试订单"; //附加数据
order.out_trade_no = "11111111111111111111111"; //商户系统内部的订单号,32个字符内、可包含字母,请替换成真实的订单号
order.total_fee = 0.01 * 100; //int类型,订单总金额,单位为分,请填写实际订单金额
order.spbill_create_ip = Page.Request.UserHostAddress; //用户端ip 11.11.11.11 格式
order.notify_url = "http://baidu.com/notify_url.aspx"; //接收微信支付异步通知回调地址,请替换成真实的回调地址,回调页面文章后面会给出例子
order.openid = "111111111111111111111111111111"; //trade_type=JSAPI,此参数必传,请替换成用户在商户appid下的唯一标识,用户的openid怎么获取请参考微信开发的API文档
order.trade_type = "JSAPI"; //交易类型 JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付
将这些信息提交给微信服务器就能获取到临时支付交易会话标识 prepay_id了,下面代码里的paySignKey是商户密匙。
//得到 prepay_id 微信生成的预支付回话标识,用于后续接口调用中使用,该值有效期为2小时
string prepay_id = tenpay.getPrepay_id(order, paySignKey); //tenapy代码文章末尾给出
string timeStamp = TenpayUtil.getTimestamp(); //时间戳
string nonceStr = TenpayUtil.getNoncestr(); //随机字符串
签名参数paySign的获取:
// 4.根据得到的prepay_id计算paySign 签名
SortedDictionary<string, string> sParams = new SortedDictionary<string, string>();
sParams.Add("appId", "1111111111111111111"); //请替换成真实的APPID
sParams.Add("timeStamp", timeStamp);
sParams.Add("nonceStr", nonceStr);
sParams.Add("package", "prepay_id=" + prepay_id);
sParams.Add("signType", "MD5");
string paySign = tenpay.getsign(sParams, paySignKey); //得到 paySign 签名 paySingKey 是商户密匙
这样paySign和prepay_id参数都成功获取到了,将这些参数替换掉HTML页面的js参数就可以弹出微信支付窗口:
需要用到的一些代码:
TenpayUtil
public class TenpayUtil { /// <summary> /// 统一支付接口 /// </summary> const string UnifiedPayUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder"; /// <summary> /// 网页授权接口 /// </summary> const string access_tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token"; /// <summary> /// 微信订单查询接口 /// </summary> const string OrderQueryUrl = "https://api.mch.weixin.qq.com/pay/orderquery"; /// <summary> /// 随机串 /// </summary> public static string getNoncestr() { Random random = new Random(); return MD5Util.GetMD5(random.Next(1000).ToString(), "utf-8").ToLower().Replace("s", "S"); } /// <summary> /// 时间截,自1970年以来的秒数 /// </summary> public static string getTimestamp() { TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(ts.TotalSeconds).ToString(); } /// <summary> /// 网页授权接口 /// </summary> public static string getAccess_tokenUrl() { return access_tokenUrl; } /// <summary> /// 获取微信签名 /// 将集合M内非空参数值的参数按照参数名ASCII码从小到大排序 /// 格式(即key1=value1&key2=value2…)拼接成字符串stringA /// https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3 /// </summary> /// <param name="sParams">集合M</param> /// <param name="key">key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置</param> /// <returns></returns> public string getsign(SortedDictionary<string, string> sParams, string key) { int i = 0; string sign = string.Empty; StringBuilder sb = new StringBuilder(); foreach (KeyValuePair<string, string> temp in sParams) { if (temp.Value == "" || temp.Value == null || temp.Key.ToLower() == "sign") { continue; } i++; sb.Append(temp.Key.Trim() + "=" + temp.Value.Trim() + "&"); } sb.Append("key=" + key.Trim() + ""); string signkey = sb.ToString(); sign = MD5Util.GetMD5(signkey, "utf-8"); return sign; } /// <summary> /// Post数据到指定接口并返回数据 /// </summary> /// <param name="url">地址</param> /// <param name="postData">要提交的数据</param> /// <returns></returns> public string PostXmlToUrl(string url, string postData) { string returnmsg = ""; Bird.Net.Http.HttpHelper httpHelper = new Bird.Net.Http.HttpHelper(); httpHelper.Encoding = Encoding.UTF8; returnmsg = httpHelper.GetHtml(url, postData, true); /* using (System.Net.WebClient wc = new System.Net.WebClient()) { returnmsg = wc.UploadString(url, "POST", postData); }*/ return returnmsg; } public string order_request_data = ""; public string order_post_data = ""; /// <summary> /// 统一下单获取prepay_id /// </summary> /// <param name="order">统一下单</param> /// <param name="key">商户密匙</param> /// <returns>prepay_id</returns> public string getPrepay_id(UnifiedOrder order, string key) { string prepay_id = ""; order_post_data = getUnifiedOrderXml(order, key); order_request_data = PostXmlToUrl(UnifiedPayUrl, order_post_data); SortedDictionary<string, string> requestXML = GetInfoFromXml(order_request_data); foreach (KeyValuePair<string, string> k in requestXML) { if (k.Key == "prepay_id") { prepay_id = k.Value; break; } } return prepay_id; } /// <summary> /// 获取微信订单明细 /// </summary> public OrderDetail getOrderDetail(QueryOrder queryorder, string key) { string post_data = getQueryOrderXml(queryorder, key); string request_data = PostXmlToUrl(OrderQueryUrl, post_data); OrderDetail orderdetail = new OrderDetail(); SortedDictionary<string, string> requestXML = GetInfoFromXml(request_data); foreach (KeyValuePair<string, string> k in requestXML) { switch (k.Key) { case "retuen_code": orderdetail.result_code = k.Value; break; case "return_msg": orderdetail.return_msg = k.Value; break; case "appid": orderdetail.appid = k.Value; break; case "mch_id": orderdetail.mch_id = k.Value; break; case "nonce_str": orderdetail.nonce_str = k.Value; break; case "sign": orderdetail.sign = k.Value; break; case "result_code": orderdetail.result_code = k.Value; break; case "err_code": orderdetail.err_code = k.Value; break; case "err_code_des": orderdetail.err_code_des = k.Value; break; case "trade_state": orderdetail.trade_state = k.Value; break; case "device_info": orderdetail.device_info = k.Value; break; case "openid": orderdetail.openid = k.Value; break; case "is_subscribe": orderdetail.is_subscribe = k.Value; break; case "trade_type": orderdetail.trade_type = k.Value; break; case "bank_type": orderdetail.bank_type = k.Value; break; case "total_fee": orderdetail.total_fee = k.Value; break; case "coupon_fee": orderdetail.coupon_fee = k.Value; break; case "fee_type": orderdetail.fee_type = k.Value; break; case "transaction_id": orderdetail.transaction_id = k.Value; break; case "out_trade_no": orderdetail.out_trade_no = k.Value; break; case "attach": orderdetail.attach = k.Value; break; case "time_end": orderdetail.time_end = k.Value; break; default: break; } } return orderdetail; } /// <summary> /// 把XML数据转换为SortedDictionary[string, string]集合 /// </summary> /// <param name="strxml">XML数据</param> /// <returns>集合</returns> public SortedDictionary<string, string> GetInfoFromXml(string xmlstring) { SortedDictionary<string, string> sParams = new SortedDictionary<string, string>(); try { XmlDocument doc = new XmlDocument(); doc.LoadXml(xmlstring); XmlElement root = doc.DocumentElement; int len = root.ChildNodes.Count; for (int i = 0; i < len; i++) { string name = root.ChildNodes[i].Name; if (!sParams.ContainsKey(name)) { sParams.Add(name.Trim(), root.ChildNodes[i].InnerText.Trim()); } } } catch { } return sParams; } /// <summary> /// 微信统一下单接口xml参数整理 /// </summary> /// <param name="order">微信支付参数实例</param> /// <param name="key">商户密钥</param> /// <returns></returns> protected string getUnifiedOrderXml(UnifiedOrder order, string key) { string return_string = string.Empty; SortedDictionary<string, string> sParams = new SortedDictionary<string, string>(); sParams.Add("appid", order.appid); sParams.Add("attach", order.attach); sParams.Add("body", order.body); sParams.Add("device_info", order.device_info); sParams.Add("mch_id", order.mch_id); sParams.Add("nonce_str", order.nonce_str); sParams.Add("notify_url", order.notify_url); sParams.Add("openid", order.openid); sParams.Add("out_trade_no", order.out_trade_no); sParams.Add("spbill_create_ip", order.spbill_create_ip); sParams.Add("total_fee", order.total_fee.ToString()); sParams.Add("trade_type", order.trade_type); order.sign = getsign(sParams, key); sParams.Add("sign", order.sign); //拼接成XML请求数据 StringBuilder sbPay = new StringBuilder(); foreach (KeyValuePair<string, string> k in sParams) { if (k.Key == "attach" || k.Key == "body" || k.Key == "sign") { sbPay.Append("<" + k.Key + "><![CDATA[" + k.Value + "]]></" + k.Key + ">"); } else { sbPay.Append("<" + k.Key + ">" + k.Value + "</" + k.Key + ">"); } } return_string = string.Format("<xml>{0}</xml>", sbPay.ToString()); return return_string; } /// <summary> /// 微信订单查询接口XML参数整理 /// </summary> /// <param name="queryorder">微信订单查询参数实例</param> /// <param name="key">密钥</param> /// <returns></returns> protected string getQueryOrderXml(QueryOrder queryorder, string key) { string return_string = string.Empty; SortedDictionary<string, string> sParams = new SortedDictionary<string, string>(); sParams.Add("appid", queryorder.appid); sParams.Add("mch_id", queryorder.mch_id); sParams.Add("transaction_id", queryorder.transaction_id); sParams.Add("out_trade_no", queryorder.out_trade_no); sParams.Add("nonce_str", queryorder.nonce_str); queryorder.sign = getsign(sParams, key); sParams.Add("sign", queryorder.sign); //拼接成XML请求数据 StringBuilder sbPay = new StringBuilder(); foreach (KeyValuePair<string, string> k in sParams) { if (k.Key == "attach" || k.Key == "body" || k.Key == "sign") { sbPay.Append("<" + k.Key + "><![CDATA[" + k.Value + "]]></" + k.Key + ">"); } else { sbPay.Append("<" + k.Key + ">" + k.Value + "</" + k.Key + ">"); } } return_string = string.Format("<xml>{0}</xml>", sbPay.ToString().TrimEnd(',')); return return_string; } }
MD5Util
public class MD5Util { public MD5Util() { } /** 获取大写的MD5签名结果 */ public static string GetMD5(string encypStr, string charset) { string retStr; MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider(); //创建md5对象 byte[] inputBye; byte[] outputBye; try { inputBye = Encoding.UTF8.GetBytes(encypStr); } catch (Exception ex) { inputBye = Encoding.UTF8.GetBytes(encypStr); } outputBye = m5.ComputeHash(inputBye); retStr = System.BitConverter.ToString(outputBye); retStr = retStr.Replace("-", "").ToUpper(); return retStr; } }
OrderDetail
/// <summary> /// 微信订单明细实体对象 /// https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1 /// </summary> [Serializable] public class OrderDetail { /// <summary> /// 返回状态码,SUCCESS/FAIL 此字段是通信标识,非交易标识,交易是否成功需要查看trade_state来判断 /// </summary> public string return_code = ""; /// <summary> /// 返回信息返回信息,如非空,为错误原因 签名失败 参数格式校验错误 /// </summary> public string return_msg = ""; /// <summary> /// 公共号ID(微信分配的公众账号 ID) /// </summary> public string appid = ""; /// <summary> /// 商户号(微信支付分配的商户号) /// </summary> public string mch_id = ""; /// <summary> /// 随机字符串,不长于32位 /// </summary> public string nonce_str = ""; /// <summary> /// 签名详见签名算法 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3 /// </summary> public string sign = ""; /// <summary> /// 业务结果,SUCCESS/FAIL /// 此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断 /// </summary> public string result_code = ""; /// <summary> /// 错误代码 详细参见第6节错误列表 /// </summary> public string err_code = ""; /// <summary> /// 错误代码描述 /// </summary> public string err_code_des = ""; /// <summary> /// 交易状态 ///SUCCESS—支付成功 ///REFUND—转入退款 ///NOTPAY—未支付 ///CLOSED—已关闭 ///REVOKED—已撤销 ///USERPAYING--用户支付中 ///NOPAY--未支付(输入密码或确认支付超时) PAYERROR--支付失败(其他原因,如银行返回失败) /// </summary> public string trade_state = ""; /// <summary> /// 终端设备号(门店号或收银设备ID),注意:PC网页或公众号内支付请传"WEB" /// </summary> public string device_info = ""; /// <summary> /// 用户在商户appid下的唯一标识 /// </summary> public string openid = ""; /// <summary> /// 用户是否关注公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效 /// </summary> public string is_subscribe = ""; /// <summary> /// 交易类型,取值如下:JSAPI,NATIVE,APP,详细说明见参数规定 /// </summary> public string trade_type = ""; /// <summary> /// 银行类型,采用字符串类型的银行标识 /// </summary> public string bank_type = ""; /// <summary> /// 订单总金额,单位为分 /// </summary> public string total_fee = ""; /// <summary> /// 现金券支付金额<=订单总金额,订单总金额-现金券金额为现金支付金额 /// </summary> public string coupon_fee = ""; /// <summary> /// 货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY /// </summary> public string fee_type = ""; /// <summary> /// 微信支付订单号 /// </summary> public string transaction_id = ""; /// <summary> /// 商户系统的订单号,与请求一致。 /// </summary> public string out_trade_no = ""; /// <summary> /// 商家数据包,原样返回 /// </summary> public string attach = ""; /// <summary> /// 支付完成时间,格式为yyyyMMddhhmmss,如2009年12月27日9点10分10秒表示为20091227091010。 /// 时区为GMT+8 beijing。该时间取自微信支付服务器 /// </summary> public string time_end = ""; }
UnifiedOrder
/// <summary> /// 微信统一接口请求实体对象 /// </summary> [Serializable] public class UnifiedOrder { /// <summary> /// 公共号ID(微信分配的公众账号 ID) /// </summary> public string appid = ""; /// <summary> /// 商户号(微信支付分配的商户号) /// </summary> public string mch_id = ""; /// <summary> /// 微信支付分配的终端设备号 /// </summary> public string device_info = ""; /// <summary> /// 随机字符串,不长于 32 位 /// </summary> public string nonce_str = ""; /// <summary> /// 签名 /// </summary> public string sign = ""; /// <summary> /// 商品描述 /// </summary> public string body = ""; /// <summary> /// 附加数据,原样返回 /// </summary> public string attach = ""; /// <summary> /// 商户系统内部的订单号,32个字符内、可包含字母,确保在商户系统唯一,详细说明 /// </summary> public string out_trade_no = ""; /// <summary> /// 订单总金额,单位为分,不能带小数点 /// </summary> public int total_fee = 0; /// <summary> /// 终端IP /// </summary> public string spbill_create_ip = ""; /// <summary> /// 订 单 生 成 时 间 , 格 式 为yyyyMMddHHmmss,如 2009 年12 月 25 日 9 点 10 分 10 秒表示为 20091225091010。时区为 GMT+8 beijing。该时间取自商户服务器 /// </summary> public string time_start = ""; /// <summary> /// 交易结束时间 /// </summary> public string time_expire = ""; /// <summary> /// 商品标记 商品标记,该字段不能随便填,不使用请填空,使用说明详见第 5 节 /// </summary> public string goods_tag = ""; /// <summary> /// 接收微信支付成功通知 /// </summary> public string notify_url = ""; /// <summary> /// JSAPI、NATIVE、APP /// </summary> public string trade_type = ""; /// <summary> /// 用户标识 trade_type 为 JSAPI时,此参数必传 /// </summary> public string openid = ""; /// <summary> /// 只在 trade_type 为 NATIVE时需要填写。 /// </summary> public string product_id = ""; }
回调页面测试:
public partial class tools_WeChat_Pay_notify_url : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { //接收从微信后台POST过来的数据 System.IO.Stream s = Request.InputStream; int count = 0; byte[] buffer = new byte[1024]; StringBuilder builder = new StringBuilder(); while ((count = s.Read(buffer, 0, 1024)) > 0) { builder.Append(Encoding.UTF8.GetString(buffer, 0, count)); } s.Flush(); s.Close(); s.Dispose(); TenpayUtil payUtil = new TenpayUtil(); SortedDictionary<string, string> requestXML = payUtil.GetInfoFromXml(builder.ToString()); const string paySignKey = "111111111111111111111111111111111111"; string sing = payUtil.getsign(requestXML, paySignKey); if (requestXML.ContainsKey("return_code")) { //Response.Write(requestXML["return_code"]); } //成功返回 Response.Write("<xml>"); Response.Write("<return_code><![CDATA[SUCCESS]]></return_code>"); Response.Write("<return_msg><![CDATA[OK]]></return_msg>"); Response.Write("</xml>"); } /// <summary> /// 从XML数据中获取值 /// </summary> /// <param name="requestXML">XML数据</param> /// <param name="key">Key</param> /// <returns>Value</returns> public string getVal(SortedDictionary<string, string> data, string key) { if (data.ContainsKey(key)) { return data[key]; } return ""; } }