微信支付 v 3.3.6
文字说明;
前提:注册、申请服务号,开通微信支付。
涉及到的参数:AppId、AppSecret、原始ID(自动回复)、mch_id(商户号)、Key(商户密钥:自己设定。)
统一规范:
- 要求
-
认证方式:HTTPS 认证,退款和冲正接口调用需要商户证书(证书在审核邮件附件中)。
- 请求采用POST 方式。
- 提交和返回结果采用XML格式。
- 字符集默认使用UTF-8,请勿使用其它字符集。
- 商户与微信之间的交互(特别是Native 回调和支付通知回调),都需要验证签名。
- 处理返回时先判断协议返回错误码,再判断业务返回错误码,最后判断交易状态。
- 统一加密方式:MD5。
- 统一签名生成方式:
- 传入参数按字段名ascii码从小到大排序,使用url键值对的格式(key1=value1&key2=value2...)拼接成字符串(注:值为空的参数不参与签名)。在字符串最后再拼接上&key=Key(商户密钥),然后进行MD5加密处理,最后得到的字符串转换为大写。
微信支付:
- jsapi支付和native支付都需要调用统一支付接口(URL 地址:https://api.mch.weixin.qq.com/pay/unifiedorder)
- jsapi支付
-
- jsapi 调用统一支付接口需要参数openid(通过Oath2.0授权获取)。
- 统一支付接口返回参数需要先验证签名,然后获取prepay_id。
-
document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() { //公众号支付 jQuery('#wxPay').click(function(e){ WeixinJSBridge.invoke('getBrandWCPayRequest',{ "appId" : appId, //公众号名称,由商户传入 "timeStamp" : timeStamp, //时间戳 "nonceStr" : nonceStr, //随机串 "package" : package, //格式:prepay_id=xxxx "signType" : signType, //签名方式:MD5 "paySign" : paySign //签名:生成签名参数appId、timeStamp、nonceStr、package、signType、key 注意参数名大小写。 },function(res){ if(res.err_msg == "get_brand_wcpay_request:ok" ) { window.location.href=url; //支付成功后跳转到的页面用于展示 } // else { // alert(res.err_code+res.err_desc+res.err_msg); // } }); }); }, false)
-
- 注:jsapi页面点击了两次“微信支付”,生成了两笔订单,需要在页面微信支付按钮上增加防二次点击的机制。
- native支付
- 参数product_id必须的
- 调用统一支付接口获取code_url,并生成二维码图片。
微信支付回调notify_url:
获取xml格式参数,验证签名,处理逻辑(通知后台会多次回调,先检查是否处理过,在执行)。
代码区:
- 生成Sign公共方法:
-
public string CreateSign(Dictionary<string, string> collection) { //排序 List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>(collection); list.Sort(delegate(KeyValuePair<string, string> pair1, KeyValuePair<string, string> pair2) { return pair1.Key.CompareTo(pair2.Key); }); StringBuilder sb = new StringBuilder(); foreach (KeyValuePair<string, string> pair in list) { sb.Append(pair.Key); sb.Append("="); sb.Append(pair.Value); sb.Append("&"); } string str = sb.Append("key=value").ToString(); string signValue = MD5(str).ToUpper(); //md5加密并转换成大写 return signValue ; }
- xml 和 Dictionary 转换方法:
-
public string DictionaryToXml(Dictionary<string, string> collection) { StringBuilder sb = new StringBuilder(); sb.Append("<xml>"); foreach (KeyValuePair<string, string> pair in collection) { sb.Append("<" + pair.Key + ">"); sb.Append("<![CDATA[" + pair.Value + "]]>"); sb.Append("</" + pair.Key + ">"); } sb.Append("</xml>"); return sb.ToString(); } public Dictionary<string, string> XmlToDictionary(XmlDocument doc) { Dictionary<string, string> collection = new Dictionary<string, string>(); foreach (XmlElement element in doc.DocumentElement.ChildNodes) { string key = element.Name; string value = element.InnerText; if (value != "") { collection.Add(key, value); } } return collection; }
- 获取Json某一key值:
-
public string GetJosnValue(string jsonStr, string key) { string result = string.Empty; if (!string.IsNullOrEmpty(jsonStr)) { key = "\"" + key.Trim('"') + "\""; int index = jsonStr.IndexOf(key) + key.Length + 1; if (index > key.Length + 1) { //先截逗号,若是最后一个,截“}”号,取最小值 int end = jsonStr.IndexOf(',', index); if (end == -1) { end = jsonStr.IndexOf('}', index); } //index = json.IndexOf('"', index + key.Length + 1) + 1; result = jsonStr.Substring(index, end - index); //过滤引号或空格 result = result.Trim(new char[] { '"', ' ', '\'' }); } } return result; }
请随手写下你的想法!!!