您的位置:首页 > 移动开发 > 微信开发

微信支付接口之心酸

2016-05-26 16:03 651 查看
微信接口,对于某些人来说,很容易,宝宝自己尝试了一下,瞬间感觉泪奔呀,唉。

首先,统一下单接口

[HttpPost]
[Route("~/api/WXPay/UnifiedOrder")]
public HttpResponseMessage UnifiedOrder()
{
try
{
NameValueCollection param = Request.Content.ReadAsFormDataAsync().Result;
string body = param["body"].ToString();//简单描述
string out_trade_no = param["out_trade_no"].ToString();
string total_fee = param["total_fee"].ToString();
string spbill_create_ip = param["spbill_create_ip"].ToString();
var stringADict = new Dictionary<string, string>();
stringADict.Add("appid", "这里是公众号ID");
stringADict.Add("mch_id", "商户号");
stringADict.Add("device_info", device_info);
stringADict.Add("nonce_str", CreateNonce_str());
stringADict.Add("body", body);
stringADict.Add("out_trade_no", out_trade_no);
stringADict.Add("total_fee", total_fee);
stringADict.Add("spbill_create_ip", spbill_create_ip);
stringADict.Add("notify_url", "回调函数");
stringADict.Add("trade_type", "APP");
var sign = Sign(stringADict, "签名字符串");//生成签名字符串
var postdata = GeneralPostdata(stringADict, sign);
var url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
var client = new HttpClient();
var result = client.PostAsync(url, new StringContent(postdata)).Result;
if (!result.IsSuccessStatusCode) return null;
dynamic doc = new DynamicXml(result.Content.ReadAsStringAsync().Result);
JObject obj = new JObject();
var a = doc.return_code.Value;
var c = doc.return_msg.Value;
if (doc.return_code.Value == "SUCCESS" && doc.result_code.Value == "SUCCESS")
{
obj.Add("prepay_id", doc.prepay_id.Value);
obj.Add("trade_type", doc.trade_type.Value);
obj.Add("sign", doc.sign.Value);
obj.Add("nonce_str", doc.nonce_str.Value);

obj.Add("result_code", doc.result_code.Value);
obj.Add("return_code", doc.return_code.Value);
obj.Add("return_msg", doc.return_msg.Value);
obj.Add("RetCode", 0);
obj.Add("RetMsg", "");
}
else
{
obj.Add("RetCode", -1);
obj.Add("doc", doc.return_code.ToString() + doc.return_msg.ToString());
}
return Request.CreateResponse(obj);
}
catch (Exception e)
{
JObject obj = new JObject();
obj.Add("RetCode", "-1");
obj.Add("ErrorDescription", e.ToString());
obj.Add("RetMsg", "错误代码:" + Guid.NewGuid().ToString());
return Request.CreateResponse(obj);
}
}


  在这里,必须要说明的是DynamicXml,在这个动态读取XML的时候,可坑死宝宝了。

public class DynamicXml : DynamicObject, IEnumerable
{
private readonly List<XElement> _elements;
public DynamicXml(string text)
{
var doc = XDocument.Parse(text);
_elements = new List<XElement> { doc.Root };
}

protected DynamicXml(XElement element)
{
_elements = new List<XElement> { element };
}

protected DynamicXml(IEnumerable<XElement> elements)
{
_elements = new List<XElement>(elements);
}

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = null;
if (binder.Name == "Value")
result = _elements[0].Value;
else if (binder.Name == "Count")
result = _elements.Count;
else
{
var attr = _elements[0].Attribute(XName.Get(binder.Name));
if (attr != null)
result = attr;
else
{
var items = _elements.Descendants(XName.Get(binder.Name));
if (items == null || items.Count() == 0) return false;
result = new DynamicXml(items);
}
}
return true;
}

public IEnumerator GetEnumerator()
{
foreach (var element in _elements)
yield return new DynamicXml(element);
}

/// <summary>
///
/// </summary>
/// <param name="binder"></param>
/// <param name="indexes"></param>
/// <param name="result"></param>
/// <returns></returns>
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
{
int ndx = (int)indexes[0];
result = new DynamicXml(_elements[ndx]);
return true;
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public override string ToString()
{
StringWriter message = new StringWriter();
foreach (var item in _elements)
message.WriteLine("{0}:\t{1}", item.Document,
item.Value);
return message.ToString();
}
}


  因为刚开始没有加上ToString和TryGetIndex的重写,然后呢,解析了一天,都不知道哪里的错。唉

OK,微信回调接口

[HttpPost]
[Route("~/api/WXPay/Notify")]
public HttpResponseMessage Notify()
{
try
{

byte[] a = Request.Content.ReadAsByteArrayAsync().Result;
string b = Encoding.UTF8.GetString(a);
var sParam = GetRequestPost(b);

if (sParam.Count <= 0)
{
throw new ArgumentNullException();
}
JObject obj = new JObject();
obj.Add("RetCode", 0);
obj.Add("RetMsg", "");

if (sParam["return_code"] == "SUCCESS" && sParam["result_code"] == "SUCCESS")
{
var sign = sParam["sign"];
var signValue = Sign(sParam, "签名字符串");
bool isVerify = sign == signValue;
if (isVerify)
{
var out_trade_no = sParam["out_trade_no"];
//具体的后期业务操作
}
obj.Add("return_code", "success");
}
else
{
obj.Add("return_code", "fail");
}
return Request.CreateResponse(HttpStatusCode.OK, obj);
}
catch (ArgumentNullException e)
{
JObject obj = new JObject();
obj.Add("RetCode", "-1");
obj.Add("RequestMsg", "暂无参数!");

return Request.CreateResponse(obj);
}
catch (Exception e)
{
JObject obj = new JObject();
obj.Add("RetCode", "-1");
obj.Add("ErrorDescription", e.ToString());
obj.Add("RetMsg", "错误代码:" + Guid.NewGuid().ToString());
return Request.CreateResponse(obj);
}
}


  对于这里的GetRequestPost方法,其实就是组合生成一个标准的xml字符串。

private SortedDictionary<string, string> GetRequestPost(string xml)
{
SortedDictionary<string, string> sArray = new SortedDictionary<string, string>();

dynamic resultXml = new DynamicXml(xml);

sArray.Add("appid", resultXml.appid.Value);
sArray.Add("bank_type", resultXml.bank_type.Value);
sArray.Add("cash_fee", resultXml.cash_fee.Value);
sArray.Add("fee_type", resultXml.fee_type.Value);

sArray.Add("is_subscribe", resultXml.is_subscribe.Value);
sArray.Add("mch_id", resultXml.mch_id.Value);
sArray.Add("nonce_str", resultXml.nonce_str.Value);
sArray.Add("openid", resultXml.openid.Value);

sArray.Add("out_trade_no", resultXml.out_trade_no.Value);
sArray.Add("time_end", resultXml.time_end.Value);
sArray.Add("total_fee", resultXml.total_fee.Value);
sArray.Add("transaction_id", resultXml.transaction_id.Value);

sArray.Add("trade_type", resultXml.trade_type.Value);
sArray.Add("sign", resultXml.sign.Value);
sArray.Add("result_code", resultXml.result_code.Value);
sArray.Add("return_code", resultXml.return_code.Value);

return sArray;
}


  附,后面的辅助方法,包含签名生成工具等。

public static string GeneralPostdata(IDictionary<string, string> postdataDict, string sign)
{
var sb2 = new StringBuilder();
sb2.Append("<xml>");
foreach (var sA in postdataDict.OrderBy(x => x.Key))
{
sb2.Append("<" + sA.Key + ">")
.Append(Transfer(sA.Value))
.Append("</" + sA.Key + ">");
}
sb2.Append("<sign>").Append(sign).Append("</sign>");
sb2.Append("</xml>");
return sb2.ToString();
}

public static string Transfer(string instr)
{
if (instr == null) return "";
return instr.Replace("&", "&").Replace("<", "<")
.Replace(">", ">").Replace("\"", """);
}

/// <summary>
/// 生成签名
/// 签名在线验证工具:
/// http://mch.weixin.qq.com/wiki/tools/signverify/ /// </summary>
/// <param name="stringADict">参与签名生成的参数列表</param>
/// <param name="partnerKey">商家私钥</param>
/// <returns></returns>
public static string Sign(IDictionary<string, string> stringADict, string partnerKey)
{
var sb = new StringBuilder();
foreach (var sA in stringADict.OrderBy(x => x.Key))
{
if (string.IsNullOrEmpty(sA.Value)) continue;
if (string.Compare(sA.Key, "sign", true) == 0) continue;
sb.Append(sA.Key).Append("=").Append(sA.Value).Append("&");
}
var string1 = sb.ToString();
sb.Append("key=").Append(partnerKey);
var stringSignTemp = sb.ToString();
var sign = MD5(stringSignTemp, "UTF-8").ToUpper();
return sign;
}

public static string MD5(string encypStr, string charset = "UTF-8")
{
string retStr;
MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider();
byte[] inputBye;
byte[] outputBye;
try
{
inputBye = Encoding.GetEncoding(charset).GetBytes(encypStr);
}
catch
{
inputBye = Encoding.GetEncoding("GB2312").GetBytes(encypStr);
}
outputBye = m5.ComputeHash(inputBye);

retStr = System.BitConverter.ToString(outputBye);
retStr = retStr.Replace("-", "").ToUpper();
return retStr;
}


  OK,只是一个简单的记录,可以直接套用的,当然,对于.net来说,特别注意的就是那个DynamicXML那个类,太尼玛坑爹了,百毒了半天,然后看了半天,终于晓得问题了,唉。不喜勿喷。谢谢

其中,很多包含借鉴网上的东西,如有版权牵扯,请及时联系本人,谢谢。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: