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事件
”
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(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 parms = BuildParams(openId, orderNum, payFee, clientIp, body, callbackUrl);
//对统一订单参数进行ascii排序
Dictionary 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 parms = new Dictionary();
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 parms)
{
StringBuilder sb = new StringBuilder();
sb.Append("");
foreach (KeyValuePair item in parms)
{
string pre = "<" + item.Key + ">";
string end = "" + item.Key + ">";
string line = pre + item.Value + end;
sb.Append(line);
}
sb.Append(" ");
return sb.ToString();
}
private Dictionary BuildParams(
string openId,
string orderNum,
string payFee,
string clientIp,
string body,
string callbackUrl)
{
Dictionary parms = new Dictionary();
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 OrderParams(Dictionary parms)
{
Dictionary orderParams = parms.OrderBy(p => p.Key).ToDictionary(p => p.Key, q => q.Value);
return orderParams;
}
private string BuildUrlParams(Dictionary parms)
{
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair 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
{
///
/// appip
///
public string appId { get; set; }
///
/// 1970年时间戳
///
public string timeStamp { get; set; }
///
/// 随机码
///
public string nonceStr { get; set; }
///
/// 预付id prepay_id=123456789
///
public string package { get; set; }
///
/// 签名类型,MD5
///
public string signType { get; set; }
///
/// 签名
///
public string paySign { get; set; }
}
5.在回调页面进行订单处理。
希望对那个需要的你有所帮助。。