ASP.NET MVC 微信公众号支付

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>

 

posted @ 2018-05-17 16:48  追逐者——Eagle  阅读(1888)  评论(0编辑  收藏  举报