微信支付完成后会有一个支付回调页面,处理支付完成后的事件,V3支付回调的数据形式为XML格式。
1、定义一个WxResponseHandlerV3类,处理一般构造函数,用于解析XML对象;
//xmlMap
private Hashtable xmlMap;
//解析回传参数,将带有指定键和值的元素添加到 System.Collections.Hashtable 中。
public WxResponseHandlerV3(HttpContext _httpContext)
{
xmlMap = new Hashtable();
this.httpContext = _httpContext;
Stream stream = this.httpContext.Request.InputStream;
if (stream.Length > 0)
{
XmlDocument xmlDoc = new XmlDocument();
StreamReader sr = new StreamReader(stream, System.Text.Encoding.UTF8);
string strInputStream = sr.ReadToEnd();
Tools.PublicConfig.log_Append("stream length:" + stream.Length.ToString()
+ "this.httpContext.Request.InputStream string: " + strInputStream, "Pay/Pay_WxV3", DateTime.Now.ToString("yyyyMMdd") + ".log");
xmlDoc.LoadXml(strInputStream);
XmlNode root = xmlDoc.SelectSingleNode("xml");
XmlNodeList xnl = root.ChildNodes;
foreach (XmlNode xnf in xnl)
{
xmlMap.Add(xnf.Name, xnf.InnerText);
}
}
if (stream != null)
{
stream.Close();
}
}
2、验签处理
/** V3支付返回notify签名:按参数名称a-z排序,遇到空值的参数不参加签名。 //全部是 xmlMap 参数
* @return boolean */
public virtual Boolean isNotifySign()
{
StringBuilder sb = new StringBuilder();
ArrayList akeys = new ArrayList(xmlMap.Keys);
akeys.Sort();
foreach (string k in akeys)
{
string v = (string)getXmlMap(k);
if (null != v && "".CompareTo(v) != 0
&& "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0)
{
sb.Append(k + "=" + v + "&");
}
}
sb.Append("key=" + this.getPayKey());
string sign = Wxpay.MD5Util.MD5(sb.ToString()).ToUpper();
//debug信息
return getXmlMap("sign").ToUpper().Equals(sign);
}
/** 获取xmlMap值 */
public string getXmlMap(string parameter)
{
string s = (string)xmlMap[parameter];
return (null == s) ? "" : s;
}
/// <summary>
/// 设置V3 支付密钥
/// </summary>
/// <param name="key"></param>
public void setPayKey(string key)
{
this.paykey = key;
}
/** 获取V3支付密钥 */
public string getPayKey()
{ return this.paykey; }
MD5加密方法
/// <summary>
/// 获得MD5加密字符串
/// </summary>
/// <param name="s">源字符串</param>
/// <returns>目标字符串</returns>
public static String MD5(String s)
{
char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
try
{
byte[] btInput = System.Text.Encoding.UTF8.GetBytes(s);
// 获得MD5摘要算法的 MessageDigest 对象
MD5 mdInst = System.Security.Cryptography.MD5.Create();
// 使用指定的字节更新摘要
mdInst.ComputeHash(btInput);
// 获得密文
byte[] md = mdInst.Hash;
// 把密文转换成十六进制的字符串形式
int j = md.Length;
char[] str = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++)
{
byte byte0 = md[i];
str[k++] = hexDigits[(int)(((byte)byte0) >> 4) & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new string(str);
}
catch
{
// Console.Error.WriteLine(e.StackTrace);
return null;
}
}
3、添加回调页面
public ActionResult WxApplyPayNotify()
{
Response.ContentType = "text/xml";
Response.ContentEncoding = System.Text.Encoding.UTF8;
Response.CacheControl = "no-cache";
bool MyBusiness = false;
try
{
if (Request.InputStream.Length > 0)
{
Wxpay.WxResponseHandlerV3 res = new Wxpay.WxResponseHandlerV3(System.Web.HttpContext.Current);
res.setPayKey("sdjhfksdjhfksdjfhkkjhsdkfjh");//支付秘钥
bool notifySign = res.isNotifySign();//验签
if (notifySign)
{
//分期支付的out_trade_no是分期订单支付请求的requestNo
string requestNo = res.getXmlMap("out_trade_no");
//财付通订单号
String transaction_id = res.getXmlMap("transaction_id");
//金额,以分为单位
String total_fee = res.getXmlMap("total_fee");
// 是否关注公众账号is_subscribe 是String(1) 用户是否关注公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效
string is_subscribe = res.getXmlMap("is_subscribe");
//判断签名及结果
if ("SUCCESS".Equals(result_code.ToUpper()))
{
//支付成功,处理其他事物。。。
}
else
{
//支付失败处理。。。
MyBusiness = true;
}
if (MyBusiness)
{
Response.Write("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");
}
else
{
Response.Write("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[My Business error]]></return_msg></xml>");
}
}
else
{
Response.Write("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名验证失败]]></return_msg></xml>");
}
}
}
catch (Exception ex)
{
//系统异常
}
return View();
}