一、在支付前期,我們需要獲取用戶的OpenId,此塊內容只針對於JSAPI(微信中直接支付)才需要,如果生成二維碼(NATIVE)掃描支付,請跳過此步驟
思路大致是:獲取用戶的code值 > 根據code值再獲取用戶的OpenId
1、先綁定授權域名:開發者中心>網頁服務>基礎接口>網頁授權獲取用戶基本信息>修改>設置網站的域名 。點擊查看
2、獲取用戶的code值時,方式如下:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=&redirect_uri=&response_type=code&scope=&state=STATE#wechat_redirect
其中APPId不用多說,redirect_uri為網站的回調地址,回調地址必須UrlEncode處理,其中返回的參數就有code值
關於網頁授權的兩種scope的區別說明:snsapi_base和snsapi_userinfo,scope只有這2種方式
snsapi_base是不需要用戶同意的,但是回調地址中獲取到的code,根據這個code只能獲取用戶的OpenId,像:昵稱,性別等是無法獲取的,但是對於微信支付足夠了
snsapi_userinfo是需要用戶同意才能獲取code,通過code能夠獲取用戶的基本信息,這個做微信登錄比較好,但是如果客戶不同意就沒辦法進行下邊的環節了,所以微信支付不要用這個參數。
3、根據2中返回的code值,獲取用戶的OpenId,方法如下:
方式:POST,Url:https://api.weixin.qq.com/sns/oauth2/access_token?appid=&secret=&code=&grant_type=authorization_code"
其中code值是從2中獲取到的,返回參數為json,其中有一個參數為openid。
//1.獲取Code值 string v = HttpContext.Current.Server.UrlEncode("http://****"); string url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=&redirect_uri=" + v + "&response_type=code&scope=snsapi_base#wechat_redirect"; Response.Redirect(url); string Code = base.QueryString("code"); //2.獲取OpenId string urls = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=&secret=&code=" + Code + "&grant_type=authorization_code"; string openid = PostWebRequest(urls, ""); /// <summary> /// 獲取OpenId方法 /// </summary> /// <param name="postUrl"></param> /// <param name="menuInfo"></param> /// <returns></returns> public string PostWebRequest(string postUrl, string menuInfo) { string returnValue = string.Empty; try { 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.Default); returnValue = streamReader.ReadToEnd(); //關閉信息 streamReader.Close(); response.Close(); stream.Close(); JsonTextParser parser = new JsonTextParser(); JsonObjectCollection obj = parser.Parse(returnValue) as JsonObjectCollection; JsonUtility.GenerateIndentedJsonText = false; string openid = obj["openid"].GetValue().ToString(); return openid; } catch (Exception ex) { return ex.ToString(); } }
二、微信支付
大致思路:微信支付>開發配置>支付授權目錄 設置一個支付頁面所在文件夾 點擊查看相應位置
登錄商戶平台 > API安全 > 設置一個32位由數字和字母組成的密鑰。 以上內容設置好后才可以進行支付參數的設置
1、引用微信JS http://res.wx.qq.com/open/js/jweixin-1.0.0.js
2、設置config參數
3、設置chooseWXPay參數
4、支付
這里需要強調的是,下邊config和chooseWXPay中的參數名為:nonceStr、timestamp要一直,否則就會一直報錯:paySign加密錯誤
其中package的prepay_id參數內容的獲取內容為可以根據官網的要求來,但傳參字段一定要小寫,一定要小寫!
paySign 的加密方式為chooseWXPay的參數內容:timestamp、nonceStr、package、signType、key的組合加密,加密方式 和獲取prepay_id的方式一樣,具體操作看代碼。但是這里的加密的參數的大小寫要前后台對應一直,否則加密一定錯誤!
加密的方式如:把所有的參數首字母從小到大傳參的形式組成字符串后,把key值再拼接上,具體內容請參考微信的簽名算法和微信下單的參數列表
<script src="../js/jquery.js" type="text/javascript"></script> <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js" type="text/javascript"></script> <script type="text/javascript"> wx.config({ debug: false, // 開啟調試模式,調用的所有api的返回值會在客戶端alert出來,若要查看傳入的參數,可以在pc端打開,參數信息會通過log打出,僅在pc端時才會打印。 appId: '<%=appids %>', // 必填,公眾號的唯一標識 timestamp: "<%=Timer %>", // 必填,生成簽名的時間戳 nonceStr: "<%=RdCode %>", // 必填,生成簽名的隨機串 signature: "<%=GetSignature() %>", // 必填,簽名,見附錄1 jsApiList: ['chooseWXPay'] // 必填,需要使用的JS接口列表,所有JS接口列表見附錄2 }); wx.ready(function () { wx.chooseWXPay({ appId: '<%=appids %>', timestamp: '<%=Timer %>', nonceStr: '<%=RdCode %>', package: 'prepay_id=<%=prepay_id %>', signType: 'MD5', paySign: '<%=paySign %>', success: function (res) { window.location.href = "cart4.aspx?Code=<%=Code %>"; }, cancel: function () { window.location.href = "cart3.aspx?Code=<%=Code %>"; }, error: function (e) { window.location.href = "cart3.aspx?Code=<%=Code %>"; } }); }); </script>
public string appids = "";//這里是公眾號的AppId public string Code = ""; //訂單號 public string Timer = "";//1970年到現在的秒數 public string OpenId = "";//用戶的OpenId public string paySign = "";//paySign public string RdCode = "";//隨機數 public string prepay_id = "";//package中prepay_id的值
public string AppSecret = "";//公眾號的AppSecret protected void Page_Load(object sender, EventArgs e) { GetTiks();
RdCode = getNoncestr().ToLower(); TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); Timer = Convert.ToInt64(ts.TotalSeconds).ToString(); BindString(); }
/// <summary>
/// 獲取jsapi_ticket的值
/// </summary>
public void GetTiks()
{
string value = "";
Stream outstream = null;
Stream instream = null;
StreamReader sr = null;
HttpWebResponse response = null;
HttpWebRequest request = null;
Encoding encoding = Encoding.UTF8;
try
{
request = (HttpWebRequest)WebRequest.Create("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + Get_Access_Token(appids, AppSecret) + "&type=jsapi");
CookieContainer cookieContainer = new CookieContainer();
request.CookieContainer = cookieContainer;
request.AllowAutoRedirect = true;
request.Method = "GET";
request.ContentType = "application/x-www-form-urlencoded";
response = request.GetResponse() as HttpWebResponse;
request.GetResponse();
instream = response.GetResponseStream();
sr = new StreamReader(instream, encoding);
JsonTextParser parser = new JsonTextParser();
JsonObjectCollection obj = parser.Parse(sr.ReadToEnd().Replace("[]", "null")) as JsonObjectCollection;
JsonUtility.GenerateIndentedJsonText = false;
Tiks = obj["ticket"].GetValue().ToString();
}
catch (Exception ex)
{
Tiks = "";
}
}
/// <summary>
/// 獲取Access_Token值
/// </summary>
/// <param name="appid">AppId</param>
/// <param name="secret">AppSecret</param>
/// <returns></returns>
public static string Get_Access_Token(string appid, string secret)
{
string value = "";
Stream outstream = null;
Stream instream = null;
StreamReader sr = null;
HttpWebResponse response = null;
HttpWebRequest request = null;
Encoding encoding = Encoding.UTF8;
try
{
request = (HttpWebRequest)WebRequest.Create("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret + "");
CookieContainer cookieContainer = new CookieContainer();
request.CookieContainer = cookieContainer;
request.AllowAutoRedirect = true;
request.Method = "GET";
request.ContentType = "application/x-www-form-urlencoded";
response = request.GetResponse() as HttpWebResponse;
request.GetResponse();
instream = response.GetResponseStream();
sr = new StreamReader(instream, encoding);
JsonTextParser parser = new JsonTextParser();
JsonObjectCollection obj = parser.Parse(sr.ReadToEnd().Replace("[]", "null")) as JsonObjectCollection;
JsonUtility.GenerateIndentedJsonText = false;
value = obj["access_token"].GetValue().ToString();
}
catch (Exception ex)
{
value = "";
}
return value;
}
/// <summary>
/// config簽名
/// </summary>
/// <returns></returns>
public string GetSignature()
{
string tmpStr = "jsapi_ticket=" + Tiks + "&noncestr=" + RdCode + "×tamp=" + Timer + "&url=" + Request.Url.ToString();
return FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1");
}
/// <summary>
/// 客戶端IP
/// </summary>
/// <param name="hc"></param>
/// <returns></returns>
public string GetIP(HttpContext hc)
{
string ip = string.Empty;
try
{
if (hc.Request.ServerVariables["HTTP_VIA"] != null)
{
ip = hc.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();
}
else
{
ip = hc.Request.ServerVariables["REMOTE_ADDR"].ToString();
}
if (ip == string.Empty)
{
ip = hc.Request.UserHostAddress;
}
return ip;
}
catch
{
return "";
}
}
public static string getNoncestr()
{
Random random = new Random();
return GetMD5(random.Next(1000).ToString(), "GBK");
}
protected string getCharset()
{
return Request.ContentEncoding.BodyName;
}
/// <summary>
/// 獲取prepay_id
/// </summary>
/// <param name="postUrl"></param>
/// <param name="menuInfo"></param>
/// <returns></returns>
public string PostWebRequests(string postUrl, string menuInfo)
{
string returnValue = string.Empty;
try
{
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;
//如果是二維碼掃描,請返回下邊的code_url,然后自己再更具內容生成二維碼即可
//string code_url = xn.SelectSingleNode("//prepay_id").InnerText;
//return code_url;
}
catch (Exception ex)
{
return "";
}
}
/// <summary>
/// MD5
/// </summary>
/// <param name="encypStr"></param>
/// <param name="charset"></param>
/// <returns></returns>
public static string GetMD5(string encypStr, string charset)
{
string retStr;
MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider();
//創建md5對象
byte[] inputBye;
byte[] outputBye;
//使用GB2312編碼方式把字符串轉化為字節數組.
try
{
inputBye = Encoding.GetEncoding(charset).GetBytes(encypStr);
}
catch (Exception ex)
{
inputBye = Encoding.GetEncoding("GB2312").GetBytes(encypStr);
}
outputBye = m5.ComputeHash(inputBye);
retStr = System.BitConverter.ToString(outputBye);
retStr = retStr.Replace("-", "").ToUpper();
return retStr;
}
public void BindString()
{
//公眾賬號ID
string appid = appids;
//商品描述
string body = "訂單號:" + order.Code;
//商戶號
string mch_id = "***";
//隨機字符串
string nonce_str = RdCode;
//通知地址-接收微信支付成功通知
string notify_url = "http://***/weixinnotify_url.aspx";
//用戶標識 -用戶在商戶appid下的唯一標識
string openid = OpenId;
//商戶訂單號
string out_trade_no = order.Code;
//下單IP
string spbill_create_ip = GetIP(this.Context);
//總金額 分為單位
int total_fee = int.Parse(order.PayPrice.Value.ToString("0.00").Replace(".", ""));
//交易類型 -JSAPI、NATIVE、APP,如果是二維碼掃描,請填寫NATIVE,而且客戶的OpenId可以不用傳
string trade_type = "JSAPI";
//微信簽名
string tmpStr = "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=" + trade_type + "&key=abc5465ouds65478dsaqw364879324ad";
string Getprepay_idSign = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "MD5").ToUpper();
string url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
string xml = "<xml>";
xml += "<appid>" + appid + "</appid>";
xml += "<body>" + body + "</body>";
xml += "<mch_id>" + mch_id + "</mch_id>";
xml += "<nonce_str>" + nonce_str + "</nonce_str>";
xml += "<notify_url>" + notify_url + "</notify_url>";
xml += "<openid>" + openid + "</openid>";
xml += "<out_trade_no>" + out_trade_no + "</out_trade_no>";
xml += "<spbill_create_ip>" + spbill_create_ip + "</spbill_create_ip>";
xml += "<total_fee>" + total_fee + "</total_fee>";
xml += "<trade_type>" + trade_type + "</trade_type>";
xml += "<sign>" + Getprepay_idSign + "</sign>";
xml += "</xml>";
string v = PostWebRequests(url, xml);
//獲取的prepay_id
prepay_id = v;
paySign = "";
string v_tmpStr = "appId=" + appid + "&nonceStr=" + RdCode + "&package=prepay_id=" + v + "&signType=MD5&timeStamp=" + Timer + "&key=abc5465ouds65478dsaqw364879324ad";
paySign = FormsAuthentication.HashPasswordForStoringInConfigFile(v_tmpStr, "MD5").ToUpper();
}
