一、微信第三方登录
通过微信打开链接:http://www.hzm.com/Entry/Login
微信OAuth2.0授权登录目前支持authorization_code模式,适用于拥有server端的应用授权。该模式整体流程为:
  . 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数;   . 通过code参数加上AppID和AppSecret等,通过API换取access_token;   . 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。
.控制器中代码
public ActionResult Login()
{
//若已经登录,直接跳到首页
if (HttpContext.User.Identity.IsAuthenticated)
{
return RedirectToAction("Index", "Entry");
}
//微信登录
//1.获取code
if (string.IsNullOrEmpty(Request.QueryString["code"]))
{
//从定向到微信,微信再重定向到当前函数(进入第1步获取code)
return RedirectToWeixin();
}
//2.获取openID
//通过code获取openID
string openID = "";
try
{
openID = GetOpenID(Request.QueryString["code"]);
}
catch(Exception e)
{
Log.Debug("GetOpenID Exception", e.StackTrace);
return Redirect("/Entry/Login");
}
//3.查找或存储用户信息
User user = new User();
user = db.Users.SingleOrDefault(p => p.OpenID == openID);
if (user == null)
{
//添加用户
user = new User();
user.OpenID = openID;
db.Users.Add(user);
db.SaveChanges();
}
//登录成功
FormsAuthentication.SetAuthCookie(user.ID.ToString(), false);//记录登录凭证
return RedirectToAction("Index", "Entry");
}
1.1.获取code
private ActionResult RedirectToWeixin()
{
JsApiPay jsApiPay = new JsApiPay(this);
var redirect_url = jsApiPay.GetRedirectToWeixinUrlForCode();//将回调stata参数值设为awardUserID
return Redirect(redirect_url);//调回:/Entry/Login
}
1.2.通过code获取openID和access_token
private string GetOpenID(string code)
{
JsApiPay jsApiPay = new JsApiPay(this);
//如果code有值
if (!string.IsNullOrEmpty(code))
{
Log.Debug(" GetOpenID code", code);
//去获取OpenID
jsApiPay.GetOpenidAndAccessTokenFromCode(code);
}
Log.Debug("GetOpenidAndAccessTokenFromCode openid", jsApiPay.openid.ToString());
return jsApiPay.openid.ToString();
}
二、微信支付
2.1.生成业务订单和微信交易号Out_trade_no
public ActionResult CreateOrder(int entryID, PayMode payMode)
{
//一个报名只应对应一个订单
//判断订单是否已经存在,则直接进入详情页
if (db.Orders.Any(p => p.EntryID == entryID))
{
return Redirect("/Entry/Detail?out_trade_no=" + db.Orders.SingleOrDefault(p => p.EntryID == entryID).Out_trade_no);
}
Entry entry = db.Entrys.Include("Event").SingleOrDefault(p => p.ID == entryID);
Order order = new Order();
order.EntryID = entry.ID;
order.Amount = GetDiscount(entry.Event);
order.PayMode = payMode;
order.State = OrderSatet.Unpaid;
order.SubmitTime = DateTime.Now;
order.Body = entry.Event.Theme;
order.Out_trade_no = WxPayApi.GenerateOutTradeNo();
db.Orders.Add(order);
db.SaveChanges();
if (payMode == PayMode.Remittance)
{
return RedirectToAction("Detail", new { out_trade_no = order.Out_trade_no });
}
return RedirectToAction("Pay", new { orderID = order.ID });
}
2.2.微信支付
public ActionResult Pay(int orderID)
{
//获取订单
Order order = db.Orders.SingleOrDefault(p => p.ID == orderID); //修改支付方式
order.PayMode = PayMode.Weixin;
db.SaveChanges(); //微信openID
Entry entry = db.Entrys.Include("Event").SingleOrDefault(p => p.ID == order.EntryID);
User user = db.Users.SingleOrDefault(p => p.ID == entry.UserID);
Log.Debug("openID", user.OpenID);
Log.Debug("entry.UserID", entry.UserID.ToString());
Log.Debug("HttpContext.User.Identity.Name", HttpContext.User.Identity.Name);
//当前订单的商户系统的订单号
ViewData["out_trade_no"] = order.Out_trade_no;
//支付费用
decimal totalFee = GetDiscount(entry.Event);
Log.Debug("totalFee", "100.00");
JsApiPay jsApiPay = new JsApiPay(this);
try
{
//若传递了相关参数,则调统一下单接口,获得后续相关接口的入口参数
jsApiPay.openid = user.OpenID; jsApiPay.total_fee = Convert.ToInt32(totalFee * );//支持两位小数,如0.01
Log.Debug(this.GetType().ToString(), "参数赋值成功1");
//JSAPI支付预处理
Log.Debug(this.GetType().ToString(), "参数赋值成功2");
WxPayData unifiedOrderResult = jsApiPay.GetUnifiedOrderResult(entry.Name + "的" + entry.Event.Theme, "报名", order.Out_trade_no); Log.Debug(this.GetType().ToString(), "预支付订单生成成功");
//获取H5调起JS API参数
var wxJsApiParam = jsApiPay.GetJsApiParameters();
ViewData["wxJsApiParam"] = wxJsApiParam; Log.Debug(this.GetType().ToString(), "wxJsApiParam参数获取成功");
//预支付订单号
var prepay_id = jsApiPay.unifiedOrderResult.GetValue("prepay_id").ToString();
ViewData["prepay_id"] = prepay_id;
Log.Debug(this.GetType().ToString(), "prepay_id参数获取成功");
/*###################################*/
Log.Debug(this.GetType().ToString(), "wxJsApiParam : " + wxJsApiParam);
}
catch (Exception ex)
{
Response.Write("<span style='color:#FF0000;font-size:20px'>" + "下单失败,请返回重试" + "</span>");
Log.Debug("Award-ConfirmPayPage", ex.Message + ex.StackTrace);
Log.Debug("Award-ConfirmPayPage", "预支付订单生成或保存异常");
} return View(); }
2.3.页面中调起微信支付接口(Pay.html)
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>支付页面</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<script type="text/javascript">
var wxJsApiParam=@Html.Raw(ViewData["wxJsApiParam"].ToString());
//调用微信JS api 支付 function jsApiCall() {
WeixinJSBridge.invoke(
'getBrandWCPayRequest',
wxJsApiParam,
function (res)
{
WeixinJSBridge.log(res.err_msg); //alert(res.err_code + res.err_desc + res.err_msg); if(res.err_msg=="get_brand_wcpay_request:ok"){
location.href ="/Entry/Detail?out_trade_no=@ViewData["out_trade_no"]";
}else
{
location.href ="/Entry/Detail?out_trade_no=@ViewData["out_trade_no"]";
} //alert(res.err_msg);
}
);
} function callpay()
{
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();
}
}
callpay();
</script>
</head>
<body>
</body>
</html>
2.4.支付成功后微信发送支付成功异步通知(post方式,通知地址在Config.cs中配置的NOTIFY_URL,在这里添加订单处理业务逻辑)
public ActionResult Notify()
{
ResultNotify notify = new ResultNotify(this);
WxPayData data = notify.GetNotifyData();
Log.Debug("return_code", data.GetValue("return_code").ToString());
Log.Debug("return_msg", data.GetValue("return_code").ToString());
if (data.GetValue("return_code").ToString() == "SUCCESS")
{
Log.Debug("out_trade_no", data.GetValue("out_trade_no").ToString());
var out_trade_no = data.GetValue("out_trade_no").ToString(); Order order = db.Orders.SingleOrDefault(p => p.Out_trade_no == out_trade_no);
Log.Debug("orderID", order.ID.ToString()); order.State = OrderSatet.Paid;
var time_end = data.GetValue("time_end").ToString();
order.PayTime = DateTime.ParseExact(time_end, "yyyyMMddHHmmss", CultureInfo.CurrentCulture);
order.TransactionID = data.GetValue("transaction_id").ToString();
order.OpenID = data.GetValue("openid").ToString();
db.SaveChanges(); }
notify.ProcessNotify(); return View();
}
2.5.支付成功后跳转到(Pay.html页面设置的地址)
如: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

.net mvc 微信支付的更多相关文章

  1. 【原创分享·微信支付】C# MVC 微信支付教程系列之现金红包

            微信支付教程系列之现金红包           最近最弄这个微信支付的功能,然后扫码.公众号支付,这些都做了,闲着无聊,就看了看微信支付的其他功能,发现还有一个叫“现金红包”的玩意,想 ...

  2. 【原创分享·微信支付】 C# MVC 微信支付教程系列之扫码支付

    微信支付教程系列之扫码支付                  今天,我们来一起探讨一下这个微信扫码支付.何为扫码支付呢?这里面,扫的码就是二维码了,就是我们经常扫一扫的那种二维码图片,例如,我们自己添 ...

  3. 【原创分享·微信支付】 C# MVC 微信支付教程系列之公众号支付

    微信支付教程系列之公众号支付         今天,我们接着讲微信支付的系列教程,前面,我们讲了这个微信红包和扫码支付.现在,我们讲讲这个公众号支付.公众号支付的应用环境常见的用户通过公众号,然后再通 ...

  4. 【原创分享·微信支付】C# MVC 微信支付之微信模板消息推送

    微信支付之微信模板消息推送                    今天我要跟大家分享的是“模板消息”的推送,这玩意呢,你说用途嘛,那还是真真的牛逼呐.原因在哪?就是因为它是依赖微信生存的呀,所以他能不 ...

  5. C# MVC 微信支付教程系列之公众号支付

    微信支付教程系列之公众号支付           今天,我们接着讲微信支付的系列教程,前面,我们讲了这个微信红包和扫码支付.现在,我们讲讲这个公众号支付.公众号支付的应用环境常见的用户通过公众号,然后 ...

  6. 【分享·微信支付】 C# MVC 微信支付教程系列之公众号支付

    微信支付教程系列之公众号支付           今天,我们接着讲微信支付的系列教程,前面,我们讲了这个微信红包和扫码支付.现在,我们讲讲这个公众号支付.公众号支付的应用环境常见的用户通过公众号,然后 ...

  7. C# MVC 微信支付之微信模板消息推送

    微信支付之微信模板消息推送                    今天我要跟大家分享的是"模板消息"的推送,这玩意呢,你说用途嘛,那还是真真的牛逼呐.原因在哪?就是因为它是依赖微信 ...

  8. MVC 微信支付

    微信支付方式有好几种,俺研究了跟自己需要的两种,即:JS API网页支付和Native原生支付,这两个名词实在是有目的难懂.JS API网页支付:我的理解是在微信浏览器里面可以调用微信支付控件的支付方 ...

  9. asp.net mvc 微信支付代码分析(根据沐雪微信平台3.1商城业务来分析)

    开发微信应用,微信支付是永远要面对的.现在的微信支付相对以往已经很稳定,很少出现诡异情况.再加上无数人开发的经验分享,现在开发微信支付已经没什么难度了. 我这次主要是想基于沐雪微信平台的微商城业务来分 ...

随机推荐

  1. Tomcat长出现的内存溢出问题

    以下内容转载自博客:http://www.cnblogs.com/apaqi/archive/2012/07/09/2582480.html 在eclipse.ini配置文件中加上以下两行 -XX:P ...

  2. node_nibbler:自定义Base32/base64 encode/decode库

    https://github.com/mattrobenolt/node_nibbler 可以将本源码复制到自己需要的JS文件中,比如下面这个文件,一个基于BASE64加密请求参数的REST工具: [ ...

  3. 找出linux服务器IO占用高的程序

     一台服务器比较性能无外乎内存.cpu使用率.IO使用率,把这3样优化好了,你服务器的负载就要小很多,当然网络情况不在我的考虑范围,毕竟网络这个情况是很不稳定,就算你服务器上把网络优化得再好,idc不 ...

  4. JSON库之性能比较:JSON.simple VS GSON VS Jackson VS JSONP

    从http://www.open-open.com/lib/view/open1434377191317.html 转载 Java中哪个JSON库的解析速度是最快的? JSON已经成为当前服务器与WE ...

  5. 用Visual Studio 2015 编写 MASM 汇编程序(一)环境配置

    原文地址:http://kipirvine.com/asm/gettingStartedVS2015/index.htm#CreatingProject 下面内容根据上面文章翻译整理而来! 开发32位 ...

  6. JavaScript中Math--random()/floor()/round()/ceil()

    Math.random():返回0-1之间的任意数,不包括0和1: Math.floor(num):返回小于等于num的整数,相当于四舍五入的四舍,不五入:例子:Math.floor(1.0);Mat ...

  7. yield个人理解及简明示例

    1.写法有2种:yield return <expression>和yield breakyield用于在迭代中返回一个值,并将值带入下一次迭代中.yield break则意味着停止迭代. ...

  8. 【摘】使用tail、head命令过滤行

    tail  -n  10  test.log   查询日志尾部最后10行的日志; tail -n +10 test.log    查询10行之后的所有日志; head -n 10  test.log  ...

  9. JDBC事务处理

    关于事务: 1.一个事务中的多个操作应该公用一个connection,如果每一个操作都用不同的connection,事务将无法回滚. 2.具体步骤: 1).在事务开始前,应该取消事务的自动提交,即设置 ...

  10. 卡特兰数 (Catalan)

    卡特兰数:(是一个在计数问题中出现的数列) 一般项公式: 1.         或       2.   递归公式: 1.  或 2. 注:全部可推导. (性质:Cn为奇数时,必然出现在奇数项 2k- ...