/** 轉載請保留本人博客園的原地址以及版權聲明,請勿惡意修改
* 作者:楊浩瑞 QQ:1420213383
* 演示系統地址:【后台】http://xiaoshuo.qqsiot.cn/manager 【前台】http://y6.qqsiot.cn
* 管理員賬號:admin 渠道商賬號:channel 代理商賬號:agent 演示密碼:1413051356 **/
一、微信小說分銷系統是什么?
微信小說分銷系統是一種合法變現系統,通過購買小說,添加到系統中,然后尋找一些需要粉絲變現的公眾號管理者來做自己的渠道商,然后讀者閱讀小說,充值的錢80%-90%直接給渠道商。平台收取10%-20%,當然,比例自己可以設置。
二、為什么要多網頁授權登錄
對於微信小說分銷系統來說,必然會出現多個公眾號的情況,其實就是多個渠道商,每個渠道商都擁有一個公眾號,為了更好的隔離渠道商,設計每個渠道商分配一個專屬子域名,比如y{0}.qqsiot.cn。
為了更好的用戶體驗,需要實現自動登錄和識別用戶的功能,這樣讀者打開網站的時候不需要輸入賬號和密碼之類的信息來驗證信息,除了自動登錄,還可以方便后期付款的時候可以調起微信支付。
三、多公眾號設計方案
既然考慮到用戶體驗,不想讓驗證賬號密碼,減少繁瑣的步驟,那么直接使用微信的無感授權登錄方式,snsapi_base方式可以在用戶沒有關注公眾號的時候獲取到該用戶的openid,並且不需要談起授權頁面,對於用戶來說,整個過程是無感的,但是不好的地方在於,此方法無法獲取到用戶的詳細信息,比如昵稱、性別、年齡等(不方便后期分析網站的用戶喜好和分布)。還有一種方式:snsapi_userinfo,此方式如果是從公眾號內部進入的話是沒有授權彈窗的,但是如果用戶沒有關注公眾號,此時會彈出是否授權的頁面,如果用戶拒絕授權,那勢必會造成一些不好的后果。
雖然snsapi_base方式無法獲取到用戶詳細信息,但是可以考慮使用其他的辦法解決,兩個地方可以處理:
1、當用戶閱讀到一定章節的時候,提示關注公眾號,關注成功后,微信會向我們的服務器推送一條關注消息,此時通過微信的獲取用戶消息接口去獲取該用戶的信息
收到的關注推送如下:
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[FromUser]]></FromUserName> <CreateTime>123456789</CreateTime> <MsgType><![CDATA[event]]></MsgType> <Event><![CDATA[subscribe]]></Event> </xml>
2、每次閱讀時需要判斷是否關注,若用戶未關注,則提示關注,若已關注,並且數據庫中記錄是未關注,那么更新一下用戶的詳細信息
上邊兩個地方都提到了獲取用戶詳細信息的接口,接口地址為:https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
可以獲取到如下信息:
{ "subscribe": 1, "openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M", "nickname": "Band", "sex": 1, "language": "zh_CN", "city": "廣州", "province": "廣東", "country": "中國", "headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4 eMsv84eavHiaiceqxibJxCfHe/0", "subscribe_time": 1382694957, "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL" "remark": "", "groupid": 0, "tagid_list":[128,2] }
有點跑題了,言歸正傳.
四、后台配置基本的公眾號信息
每個渠道商可以后台設置自己的公眾號的微信號、AppId、AppSecret,然后再微信公眾號后台配置授權域名等信息,如下圖:

微信后台需要配置的信息如下圖:

五、源碼分析
這些配置好之后,在數據庫中保存這些信息,當用戶打開網站的時候,拿出這些信息去授權。
var isWechat = Request.UserAgent.Contains("MicroMessenger"); if (isWechat) { int wid = Common.GetHomeWid(); string url = Request.Url.Scheme + "://" + Request.Url.Host; //傳遞參數,獲取用戶信息后,可跳轉到自己定義的頁面,想怎么處理就怎么處理 reurl = reurl ?? url; string appId; //只要打開這個付款頁面,就開始付款,不需要判斷什么了 Uri reurlObj = new Uri(reurl); if (reurlObj.LocalPath.ToLower().StartsWith("/payment/pay")) { appId = WxManFactory.AppId; } else { var account = _accountBll.Get(wid); if (account == null) { return RedirectToAction("Subscribe"); } appId = account.WechatPublicAppId; } reurl = Server.UrlEncode(reurl); var wxreurl = Server.UrlEncode(url + "/User/WechatLogin?reurl=" + reurl); //CommonBll.WriteLogFile("Login->" + wxreurl); //彈出授權頁面(如在不彈出授權頁面基礎下未獲得openid,彈出授權頁面,提示用戶授權) if (!string.IsNullOrWhiteSpace(auth) && auth == "1") { return Redirect("https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appId + "&redirect_uri=" + wxreurl + "&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect"); } //不彈出授權頁面 return Redirect("https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appId + "&redirect_uri=" + wxreurl + "&response_type=code&scope=snsapi_base&state=1#wechat_redirect"); } return RedirectToAction("Subscribe");
不要一味地去授權,先判斷一下是不是在微信瀏覽器打開的,如果是的話才會去授權,如果不是的話,跳轉到關注頁面,此頁面也是自己寫的,上邊有公眾號的二維碼,方便用戶使用手機微信掃描關注。
如果是微信端,那么先獲取渠道商的AppId,並且記錄授權后需要跳轉的地址,甚至是獲取code和openid后再次跳轉的地址。
if (!string.IsNullOrWhiteSpace(code)) { string url = Request.Url.Scheme + "://" + Request.Url.Host; reurl = reurl ?? url; Uri reurlObj = new Uri(reurl); //只要打開這個付款頁面,就開始付款,不需要判斷什么了 if (reurlObj.LocalPath.ToLower().StartsWith("/payment/pay")) { var model1 = WxManFactory.Get_token(code); if (model1 == null || string.IsNullOrWhiteSpace(model1.openid)) { return RedirectToAction("PayConfigError"); } Session["openid"] = model1.openid; return Redirect(reurl); } int wid = Common.GetHomeWid(); NameValueCollection collection = HttpUtility.ParseQueryString(reurlObj.Query); var wexinTool = new WeixinNormalTool(wid); OAuthToken model = wexinTool.Get_token(code); //獲取token //只做基本授權即可 UserBll userBll = new UserBll(); var user = userBll.GetByOpenId(model.openid); if (user == null) { //說明沒注冊 UserReferralBll urBll = new UserReferralBll(); ConfigBll configBll = new ConfigBll(); //其他平台ID var otherPlatform = collection.Get("other_id"); user = new User { Openid = model.openid, CoinNum = configBll.GetFirstLoginCoin(), Sex = 0,//1男2女0未知 BelongToChanneltId = wid, BelongToAgentId = wid, OtherPlatform = otherPlatform??"" }; //推廣鏈接ID var referralId = collection.Get("referralId"); var ur = urBll.Get(referralId); int agentId; var uid = collection.Get("uid"); if (ur != null) { //record belong to user.BelongToAgentId = ur.AgentId; user.BecauseReferralId = int.Parse(referralId); } else if (int.TryParse(uid, out agentId)) { //不是第一種推廣鏈接的時候,判斷是否是第二種 var account = _accountBll.Get(agentId); if (account.CreateBy == wid)//只有這個代理的id確實屬於該渠道的時候,才會加到該渠道 { user.BelongToAgentId = agentId; } } //為用戶注冊賬號 userBll.Add(user); } Session["openid"] = model.openid; //跳轉到自己的頁面,想怎么處理就怎么處理 return Redirect(reurl); } return RedirectToAction("Subscribe");
此時授權成功,並且如果用戶沒有注冊會自動注冊,如果已經注冊了,則直接打開剛才被攔截的頁面,另外代碼里邊還寫了支付頁面的攔截,以此實現支付獨立的功能。


后台手機查看,完美匹配

