1 一、微信第三方登录
2 通过微信打开链接:http://www.hzm.com/Entry/Login
3 微信OAuth2.0授权登录目前支持authorization_code模式,适用于拥有server端的应用授权。该模式整体流程为:
4 1. 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数;
5
6 2. 通过code参数加上AppID和AppSecret等,通过API换取access_token;
7
8 3. 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。
9 1.控制器中代码
10 public ActionResult Login()
11 {
12 //若已经登录,直接跳到首页
13 if (HttpContext.User.Identity.IsAuthenticated)
14 {
15 return RedirectToAction("Index", "Entry");
16 }
17 //微信登录
18 //1.获取code
19 if (string.IsNullOrEmpty(Request.QueryString["code"]))
20 {
21 //从定向到微信,微信再重定向到当前函数(进入第1步获取code)
22 return RedirectToWeixin();
23 }
24 //2.获取openID
25 //通过code获取openID
26 string openID = "";
27 try
28 {
29 openID = GetOpenID(Request.QueryString["code"]);
30 }
31 catch(Exception e)
32 {
33 Log.Debug("GetOpenID Exception", e.StackTrace);
34 return Redirect("/Entry/Login");
35 }
36 //3.查找或存储用户信息
37 User user = new User();
38 user = db.Users.SingleOrDefault(p => p.OpenID == openID);
39 if (user == null)
40 {
41 //添加用户
42 user = new User();
43 user.OpenID = openID;
44 db.Users.Add(user);
45 db.SaveChanges();
46 }
47 //登录成功
48 FormsAuthentication.SetAuthCookie(user.ID.ToString(), false);//记录登录凭证
49 return RedirectToAction("Index", "Entry");
50 }
51 1.1.获取code
52 private ActionResult RedirectToWeixin()
53 {
54 JsApiPay jsApiPay = new JsApiPay(this);
55 var redirect_url = jsApiPay.GetRedirectToWeixinUrlForCode();//将回调stata参数值设为awardUserID
56 return Redirect(redirect_url);//调回:/Entry/Login
57 }
58 1.2.通过code获取openID和access_token
59 private string GetOpenID(string code)
60 {
61 JsApiPay jsApiPay = new JsApiPay(this);
62 //如果code有值
63 if (!string.IsNullOrEmpty(code))
64 {
65 Log.Debug(" GetOpenID code", code);
66 //去获取OpenID
67 jsApiPay.GetOpenidAndAccessTokenFromCode(code);
68 }
69 Log.Debug("GetOpenidAndAccessTokenFromCode openid", jsApiPay.openid.ToString());
70 return jsApiPay.openid.ToString();
71 }
72 二、微信支付
73 2.1.生成业务订单和微信交易号Out_trade_no
74 public ActionResult CreateOrder(int entryID, PayMode payMode)
75 {
76 //一个报名只应对应一个订单
77 //判断订单是否已经存在,则直接进入详情页
78 if (db.Orders.Any(p => p.EntryID == entryID))
79 {
80 return Redirect("/Entry/Detail?out_trade_no=" + db.Orders.SingleOrDefault(p => p.EntryID == entryID).Out_trade_no);
81 }
82 Entry entry = db.Entrys.Include("Event").SingleOrDefault(p => p.ID == entryID);
83 Order order = new Order();
84 order.EntryID = entry.ID;
85 order.Amount = GetDiscount(entry.Event);
86 order.PayMode = payMode;
87 order.State = OrderSatet.Unpaid;
88 order.SubmitTime = DateTime.Now;
89 order.Body = entry.Event.Theme;
90 order.Out_trade_no = WxPayApi.GenerateOutTradeNo();
91 db.Orders.Add(order);
92 db.SaveChanges();
93 if (payMode == PayMode.Remittance)
94 {
95 return RedirectToAction("Detail", new { out_trade_no = order.Out_trade_no });
96 }
97 return RedirectToAction("Pay", new { orderID = order.ID });
98 }
99 2.2.微信支付
100 public ActionResult Pay(int orderID)
101 {
102 //获取订单
103 Order order = db.Orders.SingleOrDefault(p => p.ID == orderID);
104
105 //修改支付方式
106 order.PayMode = PayMode.Weixin;
107 db.SaveChanges();
108
109 //微信openID
110 Entry entry = db.Entrys.Include("Event").SingleOrDefault(p => p.ID == order.EntryID);
111 User user = db.Users.SingleOrDefault(p => p.ID == entry.UserID);
112 Log.Debug("openID", user.OpenID);
113 Log.Debug("entry.UserID", entry.UserID.ToString());
114 Log.Debug("HttpContext.User.Identity.Name", HttpContext.User.Identity.Name);
115 //当前订单的商户系统的订单号
116 ViewData["out_trade_no"] = order.Out_trade_no;
117 //支付费用
118 decimal totalFee = GetDiscount(entry.Event);
119 Log.Debug("totalFee", "100.00");
120 JsApiPay jsApiPay = new JsApiPay(this);
121 try
122 {
123 //若传递了相关参数,则调统一下单接口,获得后续相关接口的入口参数
124 jsApiPay.openid = user.OpenID;
125
126 jsApiPay.total_fee = Convert.ToInt32(totalFee * 100);//支持两位小数,如0.01
127 Log.Debug(this.GetType().ToString(), "参数赋值成功1");
128 //JSAPI支付预处理
129 Log.Debug(this.GetType().ToString(), "参数赋值成功2");
130 WxPayData unifiedOrderResult = jsApiPay.GetUnifiedOrderResult(entry.Name + "的" + entry.Event.Theme, "报名", order.Out_trade_no);
131
132 Log.Debug(this.GetType().ToString(), "预支付订单生成成功");
133 //获取H5调起JS API参数
134 var wxJsApiParam = jsApiPay.GetJsApiParameters();
135 ViewData["wxJsApiParam"] = wxJsApiParam;
136
137 Log.Debug(this.GetType().ToString(), "wxJsApiParam参数获取成功");
138 //预支付订单号
139 var prepay_id = jsApiPay.unifiedOrderResult.GetValue("prepay_id").ToString();
140 ViewData["prepay_id"] = prepay_id;
141 Log.Debug(this.GetType().ToString(), "prepay_id参数获取成功");
142 /*###################################*/
143 Log.Debug(this.GetType().ToString(), "wxJsApiParam : " + wxJsApiParam);
144 }
145 catch (Exception ex)
146 {
147 Response.Write("<span style='color:#FF0000;font-size:20px'>" + "下单失败,请返回重试" + "</span>");
148 Log.Debug("Award-ConfirmPayPage", ex.Message + ex.StackTrace);
149 Log.Debug("Award-ConfirmPayPage", "预支付订单生成或保存异常");
150 }
151
152 return View();
153
154 }
155 2.3.页面中调起微信支付接口(Pay.html)
156 @{
157 Layout = null;
158 }
159 <!DOCTYPE html>
160 <html>
161 <head>
162 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
163 <title>支付页面</title>
164 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
165 <script type="text/javascript">
166 var wxJsApiParam=@Html.Raw(ViewData["wxJsApiParam"].ToString());
167 //调用微信JS api 支付
168
169 function jsApiCall() {
170 WeixinJSBridge.invoke(
171 'getBrandWCPayRequest',
172 wxJsApiParam,
173 function (res)
174 {
175 WeixinJSBridge.log(res.err_msg);
176
177 //alert(res.err_code + res.err_desc + res.err_msg);
178
179 if(res.err_msg=="get_brand_wcpay_request:ok"){
180 location.href ="/Entry/Detail?out_trade_no=@ViewData["out_trade_no"]";
181 }else
182 {
183 location.href ="/Entry/Detail?out_trade_no=@ViewData["out_trade_no"]";
184 }
185
186 //alert(res.err_msg);
187 }
188 );
189 }
190
191 function callpay()
192 {
193 if (typeof WeixinJSBridge == "undefined")
194 {
195 if (document.addEventListener)
196 {
197 document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
198 }
199 else if (document.attachEvent)
200 {
201 document.attachEvent('WeixinJSBridgeReady', jsApiCall);
202 document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
203 }
204 }
205 else
206 {
207 jsApiCall();
208 }
209 }
210 callpay();
211 </script>
212 </head>
213 <body>
214 </body>
215 </html>
216 2.4.支付成功后微信发送支付成功异步通知(post方式,通知地址在Config.cs中配置的NOTIFY_URL,在这里添加订单处理业务逻辑)
217 public ActionResult Notify()
218 {
219 ResultNotify notify = new ResultNotify(this);
220 WxPayData data = notify.GetNotifyData();
221 Log.Debug("return_code", data.GetValue("return_code").ToString());
222 Log.Debug("return_msg", data.GetValue("return_code").ToString());
223 if (data.GetValue("return_code").ToString() == "SUCCESS")
224 {
225 Log.Debug("out_trade_no", data.GetValue("out_trade_no").ToString());
226 var out_trade_no = data.GetValue("out_trade_no").ToString();
227
228 Order order = db.Orders.SingleOrDefault(p => p.Out_trade_no == out_trade_no);
229 Log.Debug("orderID", order.ID.ToString());
230
231 order.State = OrderSatet.Paid;
232 var time_end = data.GetValue("time_end").ToString();
233 order.PayTime = DateTime.ParseExact(time_end, "yyyyMMddHHmmss", CultureInfo.CurrentCulture);
234 order.TransactionID = data.GetValue("transaction_id").ToString();
235 order.OpenID = data.GetValue("openid").ToString();
236 db.SaveChanges();
237
238 }
239 notify.ProcessNotify();
240
241 return View();
242 }
243 2.5.支付成功后跳转到(Pay.html页面设置的地址)
244 如:location.href ="/Entry/Detail?out_trade_no=@ViewData["out_trade_no"]";
微信支付官方文档地址:
1.App微信支付:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_3