微信公众平台:https://mp.weixin.qq.com/
进入 微信支付 管理》开通支付功能。
微信支付|商户平台:
设置安全目录:https://pay.weixin.qq.com/index.php/extend/pay_setting,意思是只有该目录下的页面才能够发起支付请求。
注意保存对应的appid和Appsecret。
接下来是微信的授权js,Authorize.cshtml
<script type="text/javascript"> var code = GetQueryString("code"); var state = GetQueryString("state"); if (code == null || code == undefined || code == "") { //步骤1:第一次进入本页面,先获取微信的授权code,然后再跳转会本页面,这时候微信会自动加上code参数 var REDIRECT_URI = encodeURI("http://www.xxx.com/Home/Authorize"); var url2 = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=xxxxxx&redirect_uri=" + REDIRECT_URI + "&response_type=code&scope=snsapi_userinfo&state=" + state + "#wechat_redirect"; window.location.href = url2; } else { //步骤1会重新返回到本页面,并携带code参数,然后进入步骤2:服务器端获取openid $.ajax({ type: "GET", url: "/WX/GetToken", data: { code: code }, success: function (result) { var data = $.parseJSON(result); if (data.openid != null && data.openid != "" && data.openid != undefined) { if (data.IsFirst) { window.location.href = "/UInfo/UData?state=" + state; } else { if (state == 1) { window.location.href = "/BInfo/Index"; } else if (state == 2) { window.location.href = "/CInfo/Index"; } else { window.location.href = "/UInfo/Index"; } } } else { alert(data.errmsg); } } }); } </script>
服务器端代码:
/// <summary> /// 微信授权登录,获取微信用户基础数据、生成AccessToken、注册用户,WX/GetToken?code=xxx /// </summary> /// <param name="code"></param> /// <returns></returns> [HttpGet] public ContentResult GetToken(string code) { JavaScriptSerializer js = new JavaScriptSerializer(); try { //获取token WXAuthorizeModel authorizeModel = GetWXAuthorizeInfo(code); if (authorizeModel != null && authorizeModel.errcode == 0) { //记录token,获取数据库中已存在的该用户的 WX token Models.WXMPTokensInfo tokensInfo = WXMPTokensInfoBLL.GetDataByOpenId(authorizeModel.openid); if (tokensInfo == null) { tokensInfo = new Models.WXMPTokensInfo(); } tokensInfo.access_token = authorizeModel.access_token; tokensInfo.CreateDate = DateTime.Now; tokensInfo.EndDate = DateTime.Now.AddSeconds(authorizeModel.expires_in); tokensInfo.expires_in = authorizeModel.expires_in; tokensInfo.openid = authorizeModel.openid; tokensInfo.refresh_token = authorizeModel.refresh_token; tokensInfo.scope = authorizeModel.scope; int no = 0; if (tokensInfo.ID > 0) { no = WXMPTokensInfoBLL.Modify(tokensInfo); } else { no = WXMPTokensInfoBLL.Add(tokensInfo); } //获取微信用户个人资料 WXUserInfo wxuserInfo = GetWXUserInfo(authorizeModel.openid); Models.UserInfo userInfo = UserInfoBLL.GetEntityByOpenID(authorizeModel.openid); if (userInfo == null) { userInfo = new Models.UserInfo(); } userInfo.city = wxuserInfo.city; userInfo.country = wxuserInfo.country; userInfo.headimgurl = wxuserInfo.headimgurl; userInfo.nickname = wxuserInfo.nickname; userInfo.openid = wxuserInfo.openid; userInfo.privilege = "";//wxuserInfo.privilege; userInfo.province = wxuserInfo.province; userInfo.sex = wxuserInfo.sex; userInfo.unionid = wxuserInfo.unionid; //保存、更新微信用户资料 bool isFirst = true; int no2 = 0; if (userInfo.ID > 0) { isFirst = false; no2 = UserInfoBLL.ModifyEntity(userInfo); } else { no2 = UserInfoBLL.Append(userInfo); userInfo.ID = no2; } //设置session Session["UModel"] = userInfo; //设置cookie保存微信openid CookiesHelper.setCookie("openid", authorizeModel.openid, 7); //返回json数据给页面 var data = new { authorizeModel.openid, authorizeModel.errcode, authorizeModel.errmsg, IsFirst = isFirst }; return Content(js.Serialize(data)); } //token获取失败,返回-1 return Content(js.Serialize(new { openid = "", errcode = -1, authorizeModel.errmsg })); } catch (Exception ex) { Log.Error("GetWXToken", ex.Message); return Content(js.Serialize(new { openid = "", errcode = -1, ex.Message })); } }
获取微信token:
/// <summary> /// 获取微信授权信息(AccessToken) /// </summary> /// <param name="code"></param> /// <returns></returns> public WXAuthorizeModel GetWXAuthorizeInfo(string code) { string url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=xxxxxx&secret=xxxxxx&code=" + code + "&grant_type=authorization_code"; string result = Utils.ClientRequest(url, "", "GET");//这是一个发送Http请求的函数,博客园里很多,自己搜就好了,我以前的文章里也有。 JavaScriptSerializer js = new JavaScriptSerializer(); WXAuthorizeModel authorizeModel = js.Deserialize<WXAuthorizeModel>(result); return authorizeModel; } /// <summary> /// 获取微信用户数据 /// </summary> /// <param name="openid"></param> /// <returns></returns> public WXUserInfo GetWXUserInfo(string openid) { Models.WXMPTokensInfo tokensInfo = WXMPTokensInfoBLL.GetDataByOpenId(openid); if (tokensInfo != null && tokensInfo.EndDate > DateTime.Now)//如果Token的有效期已经过了,则要重新获取Token { string url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + tokensInfo.access_token + "&openid=" + openid + "&lang=zh_CN"; string result = Utils.ClientRequest(url, "", "GET"); JavaScriptSerializer js = new JavaScriptSerializer(); WXUserInfo wXUser = js.Deserialize<WXUserInfo>(result); return wXUser; } return null; } public class WXAuthorizeModel { 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 int errcode { get; set; } public string errmsg { get; set; } }
微信支付参数和通知:
/// <summary> /// 生成微信支付js参数 /// /WX/GeneralWXPayPara /// {"openid":"xxxx"} /// openid:微信用户openid; /// </summary> /// <param name="data"></param> /// <returns></returns> [AcceptVerbs("POST")] public ContentResult GeneralWXPayPara(WXPayModel data) { JavaScriptSerializer js = new JavaScriptSerializer(); try { string openid = data.openid;if (!string.IsNullOrEmpty(openid)) { Models.UserInfo userinfo = UserInfoBLL.GetEntityByOpenID(openid); if (userinfo != null) { int total_fee = 1;//单位:分 string body = "test"; string attach = "1";//这是用户自定义附加的字符串,在通知接口中会携带返回,很重要,可以传自己业务逻辑的标识。string tradeNo = WxPayApi.GenerateOutTradeNo();//下载的微信SDK中自带的函数 //若传递了相关参数,则调统一下单接口,获得后续相关接口的入口参数 JsApiPay jsApiPay = new JsApiPay(); jsApiPay.openid = openid; jsApiPay.total_fee = total_fee; //JSAPI支付预处理 WxPayData unifiedOrderResult = jsApiPay.GetUnifiedOrderResult(body, attach, tradeNo);//这个函数是我修改的,下载的微信SDK里一些参数他是写死的,我改成传参了。 string wxJsApiParam = jsApiPay.GetJsApiParameters();//获取H5调起JS API参数 return Content(js.Serialize(new { code = 1, msg = "操作成功", data = wxJsApiParam })); } else { return Content(js.Serialize(new { code = -2, msg = "用户不存在" }));//用户不存在 } } else { return Content(js.Serialize(new { code = -1, msg = "参数异常" }));//参数异常 } } catch (Exception ex) { Log.Error("WX/GeneralWXPayPara", ex.Message); return Content(js.Serialize(new { code = -3, msg = "系统异常:" + ex.Message }));//系统异常 } } /// <summary> /// 微信支付异步通知 /// http://www.xxx.com/WX/WXNotify /// </summary> /// <returns></returns> [AcceptVerbs("POST", "GET")] public ContentResult WXNotify() { try { WxPayData res = new WxPayData(); ResultNotify resultNotify = new ResultNotify(); string xmlStr = resultNotify.ProcessNotify();//获取通知结果 WxPayData notifyData = resultNotify.notifyData; //判断通知合法 if (resultNotify.Success) { string return_code = ""; //SUCCESS/FAIL,这个要进行判断的,因为微信可能会传null过来。 if (notifyData.GetValue("return_code") != null) { return_code = notifyData.GetValue("return_code").ToString(); } string return_msg = ""; if (notifyData.GetValue("return_msg") != null) { return_msg = notifyData.GetValue("return_msg").ToString(); } //判断是否通信成功 if (return_code == "SUCCESS") { string result_code = ""; if (notifyData.GetValue("result_code") != null) { result_code = notifyData.GetValue("result_code").ToString(); } string err_code_des = ""; if (notifyData.GetValue("err_code_des") != null) { err_code_des = notifyData.GetValue("err_code_des").ToString(); } //判断支付成功 if (result_code == "SUCCESS") { string openid = notifyData.GetValue("openid").ToString(); string out_trade_no = notifyData.GetValue("out_trade_no").ToString(); int total_fee = Convert.ToInt32(notifyData.GetValue("total_fee").ToString()); int attach = Convert.ToInt32(notifyData.GetValue("attach").ToString());//附加字符串(商品ID) Models.UserInfo userinfo = UserInfoBLL.GetEntityByOpenID(openid); int no1 = 0; //生成订单信息 Models.TradeInfo model = new Models.TradeInfo(); model.CreateDate = DateTime.Now; model.Description = ""; if (userinfo != null) { model.Description = "userid:" + userinfo.ID + ";openid:" + openid + ";NickName:" + userinfo.nickname + ";Mobile:" + userinfo.Mobile + ";"; } model.PayMethod = Convert.ToInt32(Common.EnumHelper.TradePayMethod.微信); model.TradeTypeID = 1; model.ProID = attach; model.Title = "购买商品"; model.TotalFee = Convert.ToDouble(total_fee) / 100;//把金额的单位 分 转化为 圆 model.TradeNo = out_trade_no; model.TradeStatus = "SUCCESS"; model.UserID = userinfo.ID; no1 = TradeInfoBLL.Append(model); Log.Error("WX/WXNotify", "添加订单"); if (no1 > 0) { res.SetValue("return_code", "SUCCESS"); res.SetValue("return_msg", "OK"); return Content(res.ToXml()); } } else { Log.Error("WX", "支付失败 : " + err_code_des); res.SetValue("return_code", "FAIL"); res.SetValue("return_msg", "支付失败:" + err_code_des); return Content(res.ToXml()); } } else { Log.Error("WX", "通信失败 : " + return_msg); res.SetValue("return_code", "FAIL"); res.SetValue("return_msg", "通信失败:" + return_msg); return Content(res.ToXml()); } } res.SetValue("return_code", "FAIL"); res.SetValue("return_msg", "逻辑处理异常"); return Content(res.ToXml()); } catch (Exception ex) { WxPayData res = new WxPayData(); res.SetValue("return_code", "FAIL"); res.SetValue("return_msg", "系统处理异常"); Log.Error("WX", "WXNotify Exception : " + ex.ToString()); return Content(res.ToXml()); } }
发起微信支付的js:
function BuyProduct(openid, proid) { callpay(openid, 2, proid); } function BuyVip(openid) { callpay(openid, 1, 0); } //调用微信JS api 支付 function jsApiCall(openid, TradeTypeID, ProID) { //生成支付参数 $.ajax({ type: "POST", dataType: "json", url: "/WX/GeneralWXPayPara", data: { openid: openid, TradeTypeID: TradeTypeID, ProID: ProID }, success: function (result) { if (result.code == 1) { //进入支付 var jd = $.parseJSON(result.data);//注意转化成json数据 WeixinJSBridge.invoke('getBrandWCPayRequest', jd, function (res) { //alert(JSON.stringify(res));//提示支付结果 if (res.err_msg == "get_brand_wcpay_request:ok") { alert("支付成功"); } else { alert("支付失败"); } }); } else { alert(result.msg); } } }); } function callpay(openid, TradeTypeID, ProID) { if (typeof WeixinJSBridge == "undefined") { if (document.addEventListener) { document.addEventListener('WeixinJSBridgeReady', jsApiCall, false); } else if (document.attachEvent) { document.attachEvent('WeixinJSBridgeReady', jsApiCall); document.attachEvent('onWeixinJSBridgeReady', jsApiCall); } } else { jsApiCall(openid, TradeTypeID, ProID); } }