必要參數:
1) AppID,AppSecret : 在微信公眾號后台管理—>(菜單欄)開發 —> 基本設置
2)商戶號 :在微信公眾號后台管理—>(菜單欄)微信支付—> 商戶號管理
3)商戶秘鑰 :在微信商戶平台(可直接點擊上圖的“查看”)商戶平台 —> 產品中心 —> 開發配置
基本配置:
1)IP白名單:a.測試電腦的ip地址,b.存放WebApi的服務器電腦ip地址
2)商戶平台-->產品中心-->開發配置-->支付配置-->公眾號支付:支付授權目錄
注: a.前端頁面的地址 b.后台支付方法的地址(都是域名而不是IP)
具體步驟:
1)添加充值按鈕

<div class="mui-content-padded" style="margin-top: 6%;"> <button id='login' class="mui-btn mui-btn-block mui-btn-primary">充值</button> </div>
2)引用js
獲取當前設備的IP地址: <script type="text/javascript" src="http://pv.sohu.com/cityjson?ie=utf-8"></script>
3)獲取code ,openid
注:redirect_uri:是返回當前頁面的 url,code的值會追加在這個地址后面,所以可以根據url的地址截取到需要的code值(如果有需要加的參數,可以直接寫在后面,如標記的一樣)
(function($) { $.init(); var url = location.search; var str = url.substr(1); code = str.split('code=')[1].split('&')[0]; //頁面加載時,判斷code有沒有值,沒有就訪問 獲取if (code == 'null') { var numberurl = cardnumber + "=" + id; window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=(是你的AppID)&redirect_uri=http://llcz.jolinmind.com/taocan.html?number=" + numberurl + "&id=" + id + "&response_type=code&scope=snsapi_base&state=STATE&connect_redirect=1#wechat_redirect"; } else { var codeN = code; mui.ajax({ url: '……/api/pay/get?jsoncallback=?', data: { code: codeN }, async: true, dataType: 'json', crossDomain: true, type: 'get', timeout: 10000, success: function(data) { openid=data; }, }); } })(mui);
后台Webapi:
_appid =AppID ,_secret =AppSecret
public object Get(string code) { string html = string.Empty; string url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+ _appid + "&secret="+ _secret + "&code="+ code + "&grant_type=authorization_code"; HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); request.Method = "GET"; request.ContentType = "text/html;charset=UTF-8"; HttpWebResponse response = request.GetResponse() as HttpWebResponse; Stream ioStream = response.GetResponseStream(); StreamReader sr = new StreamReader(ioStream, Encoding.UTF8); html = sr.ReadToEnd(); sr.Close(); ioStream.Close(); response.Close(); RepParamrepCode rep = JsonConvert.DeserializeObject<RepParamrepCode>(html); return rep.openid; } public class RepParamrepCode { public string access_token { get; set; } public string expires_in { get; set; } public string refresh_token { get; set; } public string openid { get; set; } public string scope { get; set; } }
4)支付
document.getElementById("login").addEventListener('tap', function() { getCode(); });function getCode() { mui.ajax({ url: '……/api/pay/get?jsoncallback=?', data: { openid: openid, motto: returnCitySN.cip,(當前設備的IP地址) xufei: (支付金額) }, async: true, dataType: 'json', crossDomain: true, type: 'get', timeout: 10000, success: function(res) {
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(res) } } }); } } function onBridgeReady(data) {
var list = JSON.parse(data); WeixinJSBridge.invoke( 'getBrandWCPayRequest', { "appId": (你的AppId), "timeStamp": list['timeStamp'], //時間戳,自1970年以來的秒數 "nonceStr": list['nonceStr'], //隨機串 "package": list['package1'], "signType": list['signType'], //微信簽名方式: "paySign": list['paySign'] //微信簽名 }, function(res) { if (res.err_msg == "get_brand_wcpay_request:ok") { 操作成功后,你自己的方法。 } else if (res.err_msg == "get_brand_wcpay_request:cancel") { mui.alert('取消支付!', '提示'); } else { mui.alert('支付失敗!', '提示'); } }); }
后台Webapi:
public string Get(string openid, string motto, int xufei) { return Getprepay_id(_appid, _mch_id, GetRandomString(30),"抬頭", getRandomTime(), xufei, motto, "http://……/api/OM/get(支付成功后驗證數據庫是否有數據的地址)", openid); } //微信統一下單獲取prepay_id & 再次簽名返回數據 private static string Getprepay_id(string appid, string mch_id, string nonce_str, string body,string out_trade_no,int total_fee, string spbill_create_ip ,string notify_url, string openid) { var url = "https://api.mch.weixin.qq.com/pay/unifiedorder";//微信統一下單請求地址 string strA = "appid=" + appid + "&body=" + body + "&mch_id=" + mch_id + "&nonce_str=" + nonce_str + "¬ify_url=" + notify_url + "&openid=" + openid + "&out_trade_no=" + out_trade_no + "&spbill_create_ip=" + spbill_create_ip + "&total_fee=" + total_fee + "&trade_type=JSAPI"; string strk = strA + "&key=" + _key; //key為商戶平台設置的密鑰key(假) string strMD5 = MD5(strk).ToUpper();//簽名 var formData = "<xml>"; formData += "<appid>" + appid + "</appid>";//appid formData += "<body>" + body + "</body>"; formData += "<mch_id>" + mch_id + "</mch_id>";//商戶號 formData += "<nonce_str>" + nonce_str + "</nonce_str>";//隨機字符串,不長於32位。 formData += "<notify_url>" + notify_url + "</notify_url>"; formData += "<openid>" + openid + "</openid>"; formData += "<out_trade_no>" + out_trade_no + "</out_trade_no>"; formData += "<spbill_create_ip>" + spbill_create_ip + "</spbill_create_ip>";//終端IP --用戶ip formData += "<total_fee>" + total_fee + "</total_fee>"; formData += "<trade_type>JSAPI</trade_type>";//交易類型(JSAPI--公眾號支付) formData += "<sign>" + strMD5 + "</sign>"; //簽名 formData += "</xml>"; string v = sendPost(url, formData); string prepay_id = v; //時間戳 string _time = getTime().ToString(); string strB = "appId=" + appid + "&nonceStr=" + nonce_str + "&package=prepay_id=" + prepay_id + "&signType=MD5&timeStamp=" + _time + "&key=" + _key; wx w = new wx(); w.timeStamp = _time; w.nonceStr = nonce_str; w.package1 = "prepay_id=" + prepay_id; w.paySign = MD5(strB).ToUpper(); w.signType = "MD5"; return JsonConvert.SerializeObject(w); } private static string sendPost(string postUrl, string menuInfo) { string returnValue = string.Empty; byte[] byteData = Encoding.UTF8.GetBytes(menuInfo); Uri uri = new Uri(postUrl); HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(uri); webReq.Method = "POST"; webReq.ContentType = "application/x-www-form-urlencoded"; webReq.ContentLength = byteData.Length; //定義Stream信息 Stream stream = webReq.GetRequestStream(); stream.Write(byteData, 0, byteData.Length); stream.Close(); //獲取返回信息 HttpWebResponse response = (HttpWebResponse)webReq.GetResponse(); StreamReader streamReader = new StreamReader(response.GetResponseStream(), Encoding.UTF8); returnValue = streamReader.ReadToEnd(); //關閉信息 streamReader.Close(); response.Close(); stream.Close(); XmlDocument doc = new XmlDocument(); doc.LoadXml(returnValue); XmlNodeList list = doc.GetElementsByTagName("xml"); XmlNode xn = list[0]; string prepay_ids = xn.SelectSingleNode("//prepay_id").InnerText; return prepay_ids; }
/// <summary> /// MD5簽名方法 /// </summary> /// <param name="inputText">加密參數</param> /// <returns></returns> private static string MD5(string inputText) { MD5 md5 = new MD5CryptoServiceProvider(); byte[] fromData = System.Text.Encoding.UTF8.GetBytes(inputText); byte[] targetData = md5.ComputeHash(fromData); string byte2String = null; for (int i = 0; i < targetData.Length; i++) { byte2String += targetData[i].ToString("x2"); } return byte2String; }
/// <summary> /// 生成訂單號 /// </summary> /// <returns></returns> private static string getRandomTime() { Random rd = new Random();//用於生成隨機數 string DateStr = DateTime.Now.ToString("yyyyMMddHHmmssMM");//日期 string str = DateStr + rd.Next(10000).ToString().PadLeft(4, '0');//帶日期的隨機數 return str; }
/// <summary> /// 生成隨機串 /// </summary> /// <param name="length">字符串長度</param> /// <returns></returns> private static string GetRandomString(int length) { const string key = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"; if (length < 1) return string.Empty; Random rnd = new Random(); byte[] buffer = new byte[8]; ulong bit = 31; ulong result = 0; int index = 0; StringBuilder sb = new StringBuilder((length / 5 + 1) * 5); while (sb.Length < length) { rnd.NextBytes(buffer); buffer[5] = buffer[6] = buffer[7] = 0x00; result = BitConverter.ToUInt64(buffer, 0); while (result > 0 && sb.Length < length) { index = (int)(bit & result); sb.Append(key[index]); result = result >> 5; } } return sb.ToString(); }
/// <summary> /// 獲取時間戳 /// </summary> /// <returns></returns> /// private static long getTime() { TimeSpan cha = (DateTime.Now - TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1))); long t = (long)cha.TotalSeconds; return t; }
微信支付接口簽名驗證工具:
https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=20_1