1、首先到官網下載微信API。
2、解壓后將cert、lib兩個文件夾復制到項目更目錄下。
3、微信公眾號支付
控制器代碼
1 /// <summary> 2 /// 生成訂單及JSAPI提交參數 3 /// </summary> 4 /// <param name="tmpModel"></param> 5 /// <returns></returns> 6 public ActionResult GenerateOrder(string orderno) 7 { 8 //string wxEditAddrParam; 9 10 JsApiPay jsapipay = new JsApiPay(); 11 try 12 { 13 GetOpenidAndAccessToken(); 14 jsapipay.openid = Session["openid"].ToString(); 15 jsapipay.access_token = Session["access_token"].ToString(); 16 Log.Info(this.GetType().ToString(),"openid:"+jsapipay.openid+",access_token:"+jsapipay.access_token); 17 //wxEditAddrParam = GetEditAddressParameters(); 18 //ViewBag.wxEditAddrParam = wxEditAddrParam; 19 ViewBag.openid = jsapipay.openid; 20 } 21 catch (Exception) 22 { 23 throw; 24 } 25 return View(); 26 } 27 28 /** 29 * 30 * 網頁授權獲取用戶基本信息的全部過程 31 * 詳情請參看網頁授權獲取用戶基本信息:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html 32 * 第一步:利用url跳轉獲取code 33 * 第二步:利用code去獲取openid和access_token 34 * 35 */ 36 private void GetOpenidAndAccessToken() 37 { 38 if (!string.IsNullOrEmpty(Request.QueryString["code"])) 39 { 40 string code = Request.QueryString["code"]; 41 GetOpenidAndAccessTokenFromCode(code); 42 } 43 else 44 { 45 string host = Request.Url.Host; 46 string path = Request.Url.PathAndQuery; 47 string redirect_uri = HttpUtility.UrlEncode("http://" + host + path); 48 //string redirect_uri = HttpUtility.UrlEncode("http://gzh.lmx.ren"); 49 WxPayData data = new WxPayData(); 50 data.SetValue("appid", PublicConst.Wx_appid); 51 data.SetValue("redirect_uri", redirect_uri); 52 data.SetValue("response_type", "code"); 53 data.SetValue("scope", "snsapi_base"); 54 data.SetValue("state", "STATE" + "#wechat_redirect"); 55 string url = "https://open.weixin.qq.com/connect/oauth2/authorize?" + data.ToUrl(); 56 Response.Redirect(url); 57 } 58 } 59 60 public void GetOpenidAndAccessTokenFromCode(string code) 61 { 62 try 63 { 64 WxPayData data = new WxPayData(); 65 data.SetValue("appid", WxPayConfig.APPID); 66 data.SetValue("secret", WxPayConfig.APPSECRET); 67 data.SetValue("code", code); 68 data.SetValue("grant_type", "authorization_code"); 69 string url = "https://api.weixin.qq.com/sns/oauth2/access_token?" + data.ToUrl(); 70 71 //請求url以獲取數據 72 string result = HttpService.Get(url); 73 74 //Log.Debug(this.GetType().ToString(), "GetOpenidAndAccessTokenFromCode response : " + result); 75 76 //保存access_token,用於收貨地址獲取 77 JsonData jd = JsonMapper.ToObject(result); 78 79 Session["access_token"] = (string)jd["access_token"]; 80 Session["openid"] = (string)jd["openid"]; 81 } 82 catch (Exception ex) 83 { 84 throw new WxPayException(ex.ToString()); 85 } 86 } 87 88 public string GetEditAddressParameters() 89 { 90 string parameter = ""; 91 try 92 { 93 string host = Request.Url.Host; 94 string path = Request.Path; 95 string queryString = Request.Url.Query; 96 //這個地方要注意,參與簽名的是網頁授權獲取用戶信息時微信后台回傳的完整url 97 string url = "http://" + host + path + queryString; 98 99 //構造需要用SHA1算法加密的數據 100 WxPayData signData = new WxPayData(); 101 signData.SetValue("appid", WxPayConfig.APPID); 102 signData.SetValue("url", url); 103 signData.SetValue("timestamp", WxPayApi.GenerateTimeStamp()); 104 signData.SetValue("noncestr", WxPayApi.GenerateNonceStr()); 105 signData.SetValue("accesstoken", Session["access_token"]); 106 string param = signData.ToUrl(); 107 108 Log.Debug(this.GetType().ToString(), "SHA1 encrypt param : " + param); 109 //SHA1加密 110 string addrSign = FormsAuthentication.HashPasswordForStoringInConfigFile(param, "SHA1"); 111 Log.Debug(this.GetType().ToString(), "SHA1 encrypt result : " + addrSign); 112 113 //獲取收貨地址js函數入口參數 114 WxPayData afterData = new WxPayData(); 115 afterData.SetValue("appId", WxPayConfig.APPID); 116 afterData.SetValue("scope", "jsapi_address"); 117 afterData.SetValue("signType", "sha1"); 118 afterData.SetValue("addrSign", addrSign); 119 afterData.SetValue("timeStamp", signData.GetValue("timestamp")); 120 afterData.SetValue("nonceStr", signData.GetValue("noncestr")); 121 122 //轉為json格式 123 parameter = afterData.ToJson(); 124 Log.Debug(this.GetType().ToString(), "Get EditAddressParam : " + parameter); 125 } 126 catch (Exception ex) 127 { 128 Log.Error(this.GetType().ToString(), ex.ToString()); 129 throw new WxPayException(ex.ToString()); 130 } 131 132 return parameter; 133 } 134 135 [HttpPost] 136 public JsonResult CreateWxPayOrder(string openid,string orderno) 137 { 138 Log.Info(this.GetType().ToString(), "生成訂單 : openid:" + openid + ",orderno=" + orderno); 139 ResponseDto<string> ret = new ResponseDto<string>(); 140 ret.IsSuccess = false; 141 var order = _order.QueryFirstOrDefault(c => c.OrderNo == orderno); //訂單信息 142 var orderDetail = _orderDetail.QueryFirstOrDefault(c => c.OrderNo == orderno); //訂單明細 143 JsApiPay jsApiPay = new JsApiPay(); 144 jsApiPay.openid = openid; 145 jsApiPay.total_fee = Convert.ToInt32(order.OrderAmount * 100); //付款金額 146 try 147 { 148 WxPayData unifiedOrderResult = GetUnifiedOrderResult(order,orderDetail,ref jsApiPay); 149 //ViewBag.wxJsApiParam = jsApiPay.GetJsApiParameters(); 150 ret.Data = jsApiPay.GetJsApiParameters(); 151 ret.IsSuccess = true; 152 } 153 catch (Exception ex) 154 { 155 Log.Info(this.GetType().ToString(), ex.StackTrace); 156 ret.ErrMessage = ex.Message; 157 } 158 return Json(ret); 159 } 160 161 public WxPayData GetUnifiedOrderResult(MXOrdersDto order,MXOrderDetailsDto detail,ref JsApiPay api) 162 { 163 WxPayData data = new WxPayData(); 164 data.SetValue("body", detail.ProductName); 165 data.SetValue("attach", "XX網訂單"); 166 data.SetValue("out_trade_no", order.OrderNo); 167 data.SetValue("total_fee", Convert.ToInt32(order.OrderAmount * 100)); 168 data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss")); 169 data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss")); 170 data.SetValue("goods_tag", detail.ProductName); 171 data.SetValue("trade_type", "JSAPI"); 172 data.SetValue("openid", api.openid); 173 data.SetValue("appid", PublicConst.Wx_appid);//公眾賬號ID 174 data.SetValue("mch_id", PublicConst.Wx_wchid);//商戶號 175 176 Log.Error(this.GetType().ToString(), Newtonsoft.Json.JsonConvert.SerializeObject(data)); 177 WxPayData result = WxPayApi.UnifiedOrder(data); 178 if (!result.IsSet("appid") || !result.IsSet("prepay_id") || result.GetValue("prepay_id").ToString() == "") 179 { 180 Log.Error(this.GetType().ToString(), "UnifiedOrder response error!"); 181 throw new WxPayException("UnifiedOrder response error!"); 182 } 183 api.unifiedOrderResult = result; 184 return result; 185 } 186 187 /// <summary> 188 /// 獲取code 189 /// </summary> 190 /// <returns></returns> 191 [HttpPost] 192 public ActionResult getCode() 193 { 194 object objResult = ""; 195 if (Session["url"] != null) 196 { 197 objResult = Session["url"].ToString(); 198 } 199 else 200 { 201 objResult = "url為空。"; 202 } 203 return Json(objResult); 204 } 205 206 [HttpPost] 207 public JsonResult WxUpdateOrder(string orderno) 208 { 209 var order = _order.QueryFirstOrDefault(c => c.OrderNo == orderno); 210 if (order != null) 211 { 223 //這里寫入自己的訂單處理邏輯; 224 return Json(true); 225 } 226 return Json(false); 227 } 228 229 /// <summary> 230 /// 接收從微信支付后台發送過來的數據並驗證簽名 231 /// </summary> 232 /// <returns>微信支付后台返回的數據</returns> 233 private WxPayData GetNotifyData() 234 { 235 //接收從微信后台POST過來的數據 236 System.IO.Stream s = Request.InputStream; 237 int count = 0; 238 byte[] buffer = new byte[1024]; 239 StringBuilder builder = new StringBuilder(); 240 while ((count = s.Read(buffer, 0, 1024)) > 0) 241 { 242 builder.Append(Encoding.UTF8.GetString(buffer, 0, count)); 243 } 244 s.Flush(); 245 s.Close(); 246 s.Dispose(); 247 248 Log.Info(this.GetType().ToString(), "Receive data from WeChat : " + builder.ToString()); 249 250 //轉換數據格式並驗證簽名 251 WxPayData data = new WxPayData(); 252 try 253 { 254 data.FromXml(builder.ToString()); 255 } 256 catch (WxPayException ex) 257 { 258 //若簽名錯誤,則立即返回結果給微信支付后台 259 WxPayData res = new WxPayData(); 260 res.SetValue("return_code", "FAIL"); 261 res.SetValue("return_msg", ex.Message); 262 Log.Error(this.GetType().ToString(), "Sign check error : " + res.ToXml()); 263 Response.Write(res.ToXml()); 264 Response.End(); 265 } 266 267 Log.Info(this.GetType().ToString(), "Check sign success"); 268 return data; 269 }
GenerateOrder.cshtml 頁面代碼:(需要url傳入訂單號)
1 <!DOCTYPE html> 2 3 <html> 4 <head> 5 <meta name="viewport" content="width=device-width" /> 6 <title>生成微信訂單並支付</title> 7 <script src="~/Scripts/jquery-1.10.2.min.js" type="text/javascript"></script> 9 </head> 10 <body> 11 <p id="pmsg">生成訂單中,請稍候。。。</p> 12 <input id="txtOrderNo" type="hidden" value="@Request.QueryString["orderno"]" /> 13 <input type="hidden" value="@Request.QueryString["code"]" /> 14 <input id="txtOpenID" type="hidden" value="@ViewBag.openid" /> 15 <script type="text/javascript"> 16 $(function () { 17 //if (typeof WeixinJSBridge == "undefined") { 18 // if (document.addEventListener) { 19 // document.addEventListener('WeixinJSBridgeReady', editAddress, false); 20 // } 21 // else if (document.attachEvent) { 22 // document.attachEvent('WeixinJSBridgeReady', editAddress); 23 // document.attachEvent('onWeixinJSBridgeReady', editAddress); 24 // } 25 // //jsApiCall(); 26 //} 27 //else { 28 // editAddress(); 29 //} 60 callpay(); 61 }) 62 //獲取url的參數 63 function getQueryString(name) { 64 var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); 65 var r = window.location.search.substr(1).match(reg); 66 if (r != null) return unescape(r[2]); return null; 67 } 68 function editAddress() { 69 WeixinJSBridge.invoke( 70 'editAddress', 71 '', 72 function (res) { 73 var addr1 = res.provinceFirstStageName; 74 var addr2 = res.addressCitySecondStageName; 75 var addr3 = res.addressCountiesThirdStageName; 76 var addr4 = res.addressDetailInfo; 77 var tel = res.telNumber; 78 var addr = addr1 + addr2 + addr3 + addr4; 79 alert(addr + ":" + tel); 80 alert(res.err_code + res.err_desc + res.err_msg); 91 } 92 ); 93 } 94 function onBridgeReady(json) { 95 WeixinJSBridge.invoke( 96 'getBrandWCPayRequest', { 97 "appId": json.appId, //公眾號名稱,由商戶傳入 98 "timeStamp": json.timeStamp, //時間戳,自1970年以來的秒數 99 "nonceStr": json.nonceStr, //隨機串 100 "package": json.packageValue, 101 "signType": "MD5", //微信簽名方式: 102 "paySign": json.paySign //微信簽名 103 }, 104 function (res) { 105 //alert(res.err_code + res.err_desc + res.err_msg); 106 if (res.err_msg == "get_brand_wcpay_request:ok") { 107 //alert("支付成功,請稍后查詢余額,如有疑問,請聯系管理員."); 108 //fAlreadyPay();
<!--這里寫入回傳的處理邏輯--> 109 $.post("/WxUpdateOrder/?orderno="+$("#txtOrderNo").val(),function(data){ 110 111 }); 112 } // 使用以上方式判斷前端返回,微信團隊鄭重提示:res.err_msg將在用戶支付成功后返回 ok,但並不保證它絕對可靠。 113 } 114 ); 115 } 116 //調用微信JS api 支付 117 function jsApiCall() { 118 $.ajax({ 119 type: "post", 120 url: "/CreateWxPayOrder/?openid=" + $("#txtOpenID").val() + "&orderno=" + $("#txtOrderNo").val(), 121 async: false, 122 success: function (data) { 123 var json = $.parseJSON(data.Data); 124 $("#pmsg").text("訂單生成成功,轉到支付界面中。。。"); 125 //var json = eval("(" + msg + ")");//轉換后的JSON對象 126 WeixinJSBridge.invoke( 127 'getBrandWCPayRequest', { 128 "appId": json.appId, //公眾號名稱,由商戶傳入 129 "timeStamp": json.timeStamp, //時間戳,自1970年以來的秒數 130 "nonceStr": json.nonceStr, //隨機串 131 "package": json.package, 132 "signType": "MD5", //微信簽名方式: 133 "paySign": json.paySign //微信簽名 134 }, 135 function (res) { 136 //alert(res.err_code + res.err_desc + res.err_msg); 137 if (res.err_msg == "get_brand_wcpay_request:ok") { 138 //alert("支付成功,請稍后查詢余額,如有疑問,請聯系管理員."); 139 //fAlreadyPay(); 140 $.post("/WxUpdateOrder/?orderno=" + $("#txtOrderNo").val(), function (data) { 141 $("#pmsg").text("支付完成"); 143 }); 144 } // 使用以上方式判斷前端返回,微信團隊鄭重提示:res.err_msg將在用戶支付成功后返回 ok,但並不保證它絕對可靠。 145 } 146 ); 147 }, 148 error: function (XMLHttpRequest, textStatus, errorThrown) { 149 alert(XMLHttpRequest.status); 150 alert(XMLHttpRequest.readyState); 151 alert(textStatus); 152 } 153 }) 169 } 170 171 function callpay() { 172 if (typeof WeixinJSBridge == "undefined") { 173 if (document.addEventListener) { 174 document.addEventListener('WeixinJSBridgeReady', jsApiCall, false); 175 } 176 else if (document.attachEvent) { 177 document.attachEvent('WeixinJSBridgeReady', jsApiCall); 178 document.attachEvent('onWeixinJSBridgeReady', jsApiCall); 179 } 180 //jsApiCall(); 181 } 182 else { 183 jsApiCall(); 184 } 185 } 186 187 </script> 188 </body> 189 </html>