微信公眾號付款asp.net版本
阿新 • • 發佈:2019-01-09
1.在需要支付的頁面先獲取code
protected void Page_Load(object sender, EventArgs e)
{
code = "" + HttpContext.Current.Request.Params["code"];
if (string.IsNullOrEmpty(code))
{
string appid = “你的appid”;
var uri = “需要回傳引數的url,可以是當前頁面”;
string url = GetCodeUrl(appid, uri, null);
Response.Redirect(url);
} } public string GetCodeUrl(string Appid, string redirect_uri, string formId) { return string.Format("https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope=snsapi_userinfo&state={2}#wechat_redirect", Appid, redirect_uri, formId); }
2.寫前端支付按鈕的js事件
<input type="button" id="btnPay" onclick="pay();" value="立即支付" runat="server" /> <script type="text/javascript"> function getParam(name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); var r = window.location.search.substr(1).match(reg); if (r != null) return unescape(r[2]); return null; } function pay() { if (typeof WeixinJSBridge == "undefined") { alert("請在微信中開啟"); return; } var code = getParam("code"); //獲取 code 回撥的頁面獲取Code var orderid = ”訂單號“; var totalprice = 訂單價格; var url = "處理引數的後臺頁面"; $.post(url, { code: code, orderid: orderid, total: totalprice }, function (data) { if (data.err_msg) { alert(data.err_msg); return; } //alert(data.appId); var invokeData = { "appId": data.appId, //公眾號名稱,由商戶傳入 "timeStamp": data.timeStamp, //時間戳,自1970年以來的秒數 "nonceStr": data.nonceStr, //隨機串32個位元組以下 "package": data.package, //訂單詳情擴充套件字串字串型別,4096個位元組以下是商戶將訂單資訊組成該字串,具體組成方案參見介面使用說明中package組包幫劣;由商戶按照規範拼接後傳入; "signType": data.signType, //微信簽名方式:目前只支援MD5 "paySign": data.paySign//微信簽名 }; WeixinJSBridge.invoke( 'getBrandWCPayRequest', invokeData, function (res) { if (res.err_msg == "get_brand_wcpay_request:ok") { alert("支付完成"); } // 使用以上方式判斷前端返回,微信團隊鄭重提示:res.err_msg將在使用者支付成功後返回 ok,但並不保證它絕對可靠。 else if (res.err_msg == "get_brand_wcpay_request:cancel") { alert("使用者取消支付!"); } else { alert("支付失敗!" + res.err_msg); } }); }, "json"); } </script>”
3.第2個步驟中提到的後臺處理引數的頁面根據2中獲取的code引數獲取openid
public void ProcessRequest(HttpContext context)
{
try
{
string code = "" + context.Request.Params["code"];
JavaScriptSerializer ser = new JavaScriptSerializer();
if (string.IsNullOrEmpty(code))
{
var json = ser.Serialize(new { err_msg = "非法操作" });
context.Response.Write(json);
}
string orderid = context.Request.Params["orderid"];
string totalprice = context.Request.Params["total"];
//獲取openId
string openId = GetOpenId(code);
string resultXml;
try
{
OrderSuccCallbackData callbackData =new WXGZPay().WXOrder(openId, orderid, totalprice, out resultXml);
string responseStr = ser.Serialize(callbackData);
HttpContext.Current.Response.Write(responseStr);
}
catch
{
insertlog("微信支付開始封包!new WXGZPay().WXOrder失敗");
}
}
catch (Exception e)
{
JavaScriptSerializer ser = new JavaScriptSerializer();
HttpContext.Current.Response.Write(ser.Serialize(new { err_msg = e.Message }));
}
}
private string GetOpenId(string code)
{
string appid = "你的appid";
string secret = "你的secret";
string url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appid + "&secret=" + secret + "&code=" + code + "&grant_type=authorization_code";
string result = HttpGet(url);
JavaScriptSerializer ser = new JavaScriptSerializer();
TokenCls cls = ser.Deserialize<TokenCls>(result);
return cls.openid;
}
private string HttpGet(string Url, string postDataStr = "")
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url + (postDataStr == "" ? "" : "?") + postDataStr);
request.Method = "GET";
request.ContentType = "text/html;charset=UTF-8";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream myResponseStream = response.GetResponseStream();
StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
string retString = myStreamReader.ReadToEnd();
myStreamReader.Close();
myResponseStream.Close();
return retString;
}
[Serializable]
class TokenCls
{
public string access_token { get; set; }
public int expires_in { get; set; }
public string refresh_token { get; set; }
public string openid { get; set; }
public string scope { get; set; }
public string unionid { get; set; }
}
4.第3步驟中WXGZPay().WXOrder頁面引數處理
public OrderSuccCallbackData WXOrder(string openId, string orderid,string totalprice,out string resultXml)
{
//訂單號加隨機數,因為微信介面不允許同一個訂單號處理兩次以上
string orderNum = orderid + new Random().Next(1000,10000).ToString();
string payFee = totalprice;
//客戶端ip地址
string clientIp = "客戶端ip地址";
//128個字以內的說明文字
string body = "訂單號:" + orderid.Remove(orderid.Length - 4);
//回撥地址
string callbackUrl = “回撥頁面url”;
string timeStamp = GetTimespanSince1970();
//微信統一訂單下單地址
string postUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
//構造統一訂單引數
Dictionary<string, string> parms = BuildParams(openId, orderNum, payFee, clientIp, body, callbackUrl);
//對統一訂單引數進行ascii排序
Dictionary<string, string> orderParms = OrderParams(parms);
//將排序後的訂單引數轉換成url引數形式
string urlParms = BuildUrlParams(orderParms);
//url地址後加上key
urlParms = urlParms + "&key=" + appKey;
//把url地址進行md5加密作為sign
var sign = Md5Encrypt(urlParms).ToUpper();
//在將簽名sign新增到提交引數中
orderParms.Add("sign", sign);
//////////////此時正式提交的引數構造完畢//////////////////
string xmlString = DictionaryToXML(orderParms);
//post提交資料到微信統一訂單下單API
resultXml = PostResponse(postUrl, xmlString);
//XML解析,並獲取prepay_id,
XmlDocument doc = new XmlDocument();
doc.LoadXml(resultXml);
string return_code = doc.GetElementsByTagName("return_code").Item(0).InnerText;
string result_code = doc.GetElementsByTagName("result_code").Item(0).InnerText;
string package = string.Empty;
if (return_code.Equals("SUCCESS") && result_code.Equals("SUCCESS"))
{
string prepay_id = doc.GetElementsByTagName("prepay_id").Item(0).InnerText;
package = "prepay_id=" + prepay_id;
}
OrderSuccCallbackData data = new OrderSuccCallbackData()
{
appId = appid,
nonceStr = orderParms["nonce_str"],
package = package,
//paySign = sign,
signType = "MD5",
timeStamp = timeStamp
};
data.paySign = GetJSApiSign(data.appId, data.nonceStr, data.package, data.timeStamp);
return data;
}
public string GetJSApiSign(string appId, string nonceStr, string package, string timeStamp)
{
Dictionary<string, string> parms = new Dictionary<string, string>();
parms.Add("appId", appId);
parms.Add("nonceStr", nonceStr);
parms.Add("package", package);
parms.Add("signType", "MD5");
parms.Add("timeStamp", timeStamp);
//排序引數
parms = parms.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
string urlParms = BuildUrlParams(parms);
//url地址後加上key
urlParms = urlParms + "&key=" + appKey;
//把url地址進行md5加密作為sign
var sign = Md5Encrypt(urlParms).ToUpper();
//在將簽名sign新增到提交引數中
parms.Add("sign", sign);
return sign;
}
private string PostResponse(string url, string param)
{
string pi_strParm = param;
ServicePointManager.Expect100Continue = false;//post提交資料時,客戶端會先詢問伺服器是否會處理資料,若不處理,則不提交。此設定為不詢問,直接提交資料。
Encoding t_Encoding = Encoding.UTF8;
Uri t_Uri = new Uri(url);
byte[] paramBytes = t_Encoding.GetBytes(pi_strParm);
WebRequest t_WebRequest = WebRequest.Create(t_Uri);
t_WebRequest.Timeout = 100000;
t_WebRequest.ContentType = "application/x-www-form-urlencoded";
t_WebRequest.Method = "POST";
using (Stream t_REStream = t_WebRequest.GetRequestStream())
{
t_REStream.Write(paramBytes, 0, paramBytes.Length);
}
WebResponse t_webResponse = t_WebRequest.GetResponse();
using (StreamReader t_StreamReader = new StreamReader(t_webResponse.GetResponseStream(), Encoding.UTF8))
{
string returnStr = t_StreamReader.ReadToEnd();
return returnStr;
}
}
private string GetTimespanSince1970()
{
double totalSecs = (DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds;
return Convert.ToInt32(totalSecs).ToString();
}
private string DictionaryToXML(Dictionary<string, string> parms)
{
StringBuilder sb = new StringBuilder();
sb.Append("<xml>");
foreach (KeyValuePair<string, string> item in parms)
{
string pre = "<" + item.Key + ">";
string end = "</" + item.Key + ">";
string line = pre + item.Value + end;
sb.Append(line);
}
sb.Append("</xml>");
return sb.ToString();
}
private Dictionary<string, string> BuildParams(
string openId,
string orderNum,
string payFee,
string clientIp,
string body,
string callbackUrl)
{
Dictionary<string, string> parms = new Dictionary<string, string>();
parms.Add("openid", openId);
parms.Add("appid", appid);
parms.Add("mch_id", mch_id);
parms.Add("nonce_str", Md5Encrypt(new Random().Next().ToString()));
parms.Add("body", body);
parms.Add("out_trade_no", orderNum);
parms.Add("total_fee", payFee);
parms.Add("spbill_create_ip", clientIp);
parms.Add("notify_url", callbackUrl);
parms.Add("trade_type", "JSAPI");
return parms;
}
private Dictionary<string, string> OrderParams(Dictionary<string, string> parms)
{
Dictionary<string, string> orderParams = parms.OrderBy(p => p.Key).ToDictionary(p => p.Key, q => q.Value);
return orderParams;
}
private string BuildUrlParams(Dictionary<string, string> parms)
{
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<string, string> item in parms)
{
sb.Append(item.Key + "=" + item.Value + "&");
}
string sbStr = sb.ToString();
return sbStr.TrimEnd('&');
}
private string Md5Encrypt(string sourceStr)
{
MD5 md5 = new MD5CryptoServiceProvider();
var data = Encoding.UTF8.GetBytes(sourceStr);
var encs = md5.ComputeHash(data);
return BitConverter.ToString(encs).Replace("-", "");
}
public class OrderSuccCallbackData
{
/// <summary>
/// appip
/// </summary>
public string appId { get; set; }
/// <summary>
/// 1970年時間戳
/// </summary>
public string timeStamp { get; set; }
/// <summary>
/// 隨機碼
/// </summary>
public string nonceStr { get; set; }
/// <summary>
/// 預付id prepay_id=123456789
/// </summary>
public string package { get; set; }
/// <summary>
/// 簽名型別,MD5
/// </summary>
public string signType { get; set; }
/// <summary>
/// 簽名
/// </summary>
public string paySign { get; set; }
}
5.在回撥頁面進行訂單處理。
希望對那個需要的你有所幫助。。