微信开发小结——积累与沉淀

前言

微信开发是个人、企业或组织在拥有超大用户群体的微信应用上,利用微信公众平台,开发类似插件或服务的轻应用。微信公众平台分为三种:订阅号:主要面向媒体和个人,旨在为用户提供信息资讯,每天能够群发1条消息,通过微信认证,可获得菜单、获得用户信息等接口权限;服务号:主要面向企业、政府和组织,旨在为用户提供服务,每月能够群发4条消息,通过微信认证,可获得高级接口权限;企业号:主要面向企业,旨在为企业用户提供移动端办公,只有企业通讯录中的用户才能关注使用,可以自由推送消息,不受限制,保密消息,防转发。期间我负责开发了基于服务号的微信投票和基于企业号的微信ERP,以下我主要从开发的角度介绍期间遇到的问题和心得体会。

前提准备

1、微信公众号申请,并通过微信认证。

2、准备一个二级以上域名,域名必须要备案。

3、对于需要自定义开发,需要提供可以部署程序的公网服务器。

对于2、3点,可以由开发公司提供,只需提供客户方一个管理后台地址和管理员账号密码,由客户方管理人员进行维护。

开发者认证获取票据

无论何种公众平台,开发者第一步工作是,获取AccessToken票据,因为绝大部分调用接口时都需携带AccessToken票据。AccessToken需要用申请的公众平台提供的CorpID和Secret(服务号则用AppID和Secret)来换取,不同的Secret会返回不同的AccessToken,换取的过程就是一次接口的调用。每次获取的AccessToken有效期是2个小时,失效后需要重新换取,我利用缓存处理把每次获取的AccessToken保存起来,设置7100秒,防止临界值的情况,并把它设置成静态属性,封装获取过程。在每次调用微信接口时,直接校验是否失效。

static string AccessToken { get { return qyUtils.GetTenket(); } }
        /// <summary>
        /// 应用toket获取
        /// </summary>
        /// <returns></returns>
        public static string GetTenket()
        {
            try
            {
                var cache = new mCache("token", "qyAccessToken");
                if (cache.ValidCache()) return cache.GetCache().ToString();
                string url = string.Format("{0}/cgi-bin/gettoken", Globals.QY_HTTP);
                StringBuilder param = new StringBuilder();
                param.Append("corpid=");
                param.Append(Globals.CORP_ID);
                param.Append("&corpsecret=");
                param.Append(Globals.CORP_SECRET);
                string strValue = Utils.GetData(url, param.ToString());
                ACCESS_TOKEN ac_token = JsonConvert.DeserializeObject<ACCESS_TOKEN>(strValue);
                if (ac_token.errcode == ReturnCode.请求成功)
                {
                    cache.ExpireTime = 7100;
                    cache.SetCache(ac_token.access_token);
                    return ac_token.access_token;
                }
                else
                {
                    HttpContext.Current.Response.Write("<script>$.alert('" + ac_token.errmsg + "');</script>");
                    return null;
                }
            }
            catch { }
            return null;
        }

接口封装

工欲善其事必先利其器!微信提供的API接口都是HTTP的POST请求和Get请求,我们可以封装成工具类,方面后期的使用。对于Get请求,我把URL变量作为参数传入发送HttpWebRequest请求,获取HttpWebResponse响应,反序列化结果判断请求是否成功,对于Post请求也差不多,只是多加一个传入数据的参数变量。

public static string PostData(string url, string data)
        {
            data = Regex.Unescape(data);
            string json = HttpPost(url, data);
            try
            {
                var item = JsonConvert.DeserializeObject<WxJsonResult>(json);
                if (item.errcode != 0)
                {
                    if (item.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效 || item.errcode == ReturnCode.oauth_code超时)
                    {
                        ClearTenket();
                    }
                    item.errmsg = item.errcode.ToString();
                    json = JsonConvert.SerializeObject(item);
                }
            }
            catch { }
            return json;
        }

公众号经常有需要用到一些临时性的多媒体素材的场景,是通过media_id来进行的,而对于上传文件的POST请求,我直接使用的.NET语言自带的WebClient进行处理,先将文件上传到自己服务器端,使用相对路径获取服务器上的文件资源,调用微信公众号API,上传文件,返回媒体文件唯一标识。

public static QyUploadTemp WeChatUpload(string url, string type)
        {
            try
            {
                if (!string.IsNullOrEmpty(qyUtils.GetTenket()))
                {
                    string posturl = string.Format("{0}/cgi-bin/media/upload?access_token={1}&type={2}", Globals.QY_HTTP, AccessToken, type);
                    System.Net.WebClient webclient = new System.Net.WebClient();
                    string media = HttpContext.Current.Server.MapPath(url);
                    byte[] be = webclient.UploadFile(new Uri(String.Format(posturl, AccessToken, type)), media);
                    string content = Encoding.Default.GetString(be);
                    var result = JsonConvert.DeserializeObject<QyUploadTemp>(content);
                    if (result.errcode == ReturnCode_QY.请求成功)
                    {
                        return result;
                    }
                }
            }
            catch { }
            return null;
        }

身份验证

微信应用经常需要获取用户身份信息,这就需要通过OAuth2.0验证接口。利用.NET应用的FormsAuthentication机制,判断请求是否已经过身份验证,否则跳转统一的授权认证处理/OAuth/QyLogOn调用OAuth验证接口获取code,这里需要指定成功获取code之后,根据code获取成员信息,并记录用户信息,身份验证处理。将需获取用户身份信息的方法继承基类QyBaseController,就可以在每次获取用户身份前,先OAuth验证,如果已经过身份验证,则无需重复身份验证。

1、未通过身份验证处理
		public ActionResult QyLogOn(string returnUrl)
        {
            if (!String.IsNullOrEmpty(returnUrl))
            {
                Session["WX_returnUrl"] = returnUrl;
            }
            string action = "OAuth/QyLogOnOAuth";
            return Redirect(Utils.GetAuthorizeUrl(Globals.CORP_ID, action, "", OAuthScope.snsapi_base));
        }
2、调用OAuth验证接口获取code,这里主要特别注意的是redirectUrl必须保证和浏览器中的地址一致
		public static string GetAuthorizeUrl(string appId, string action, string state, OAuthScope scope, string responseType = "code")
        {
            string redirectUrl = HttpUtility.UrlEncode(string.Format("{0}/{1}", Globals.DOMAIN_URL, action));
            string url =
            string.Format("https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type={2}&scope={3}&state={4}#wechat_redirect",
                            appId, redirectUrl, responseType, scope, state);
            return url;
        }
3、根据code获取成员信息,并记录用户信息,身份验证处理
		public ActionResult QyLogOnOAuth(string code, string state)
        {
            if (string.IsNullOrEmpty(code)) return Content("您拒绝了授权!");
            try
            {
                //通过,用code获取成员信息
                OAuthUserInfoResult result = qyUtils.GetUserInfobyCode(code);
                if (string.IsNullOrEmpty(result.UserId))
                    return Content("<div><span class='fa fa-error'>您不是企业用户,请通知管理员添加!</span></div>");
                var user = qyUtils.GetUserInfobyUserId(result.UserId);
                qyWxUser.LogOn(user);
                if (Session["WX_returnUrl"] != null) { return Redirect(Session["WX_returnUrl"].ToString()); }
            }
            catch (Exception ex)
            {
                return Content(ex.Message);
            }
            return RedirectToAction("ErrorTip", "Account");
        }

微信端UI框架

由于之前缺乏移动端开发经验,对于前端框架都不熟悉,只能网上了解一些开源的UI框架,又因为自己毕竟不是专业的前端开发工程师,最佳的选择是自带功能丰富组件的开源UI库。经过筛选,最先尝试的是由微信官方的推的weui,发现只有一些简单的组件,对于js请求处理响应都得自己写,便放弃了。后来了解到由阿里巴巴基于Framework7开发的SUI库,轻量、精美,实现了下拉刷新、日历、省市区选择器等功能非常强大的组件。这种资源对于一个只是刚刚入门的前端开发来说,无疑是最好的。但却忽略了很重要的一点,对于这种开源项目来说,团队的的持续维护更新,是至关重要的。随着使用频率增加,以及业务要求的复杂,SUI框架中隐藏的问题渐渐暴露出来:路由跳转页面和路由返回上一个页面存在问题,下拉滚动加载数据不能与上拉刷新并存,Android
端微信显示效果比IOS端微信差,日历组件初次打开不会聚焦输入框里的时间;这套UI库是引用Zepto.js,再引用Jquery库,会出现冲突以致组件失效、不稳定,而且SUI的主力开发人员已离开阿里巴巴,没有人继续负责维护这个项目了。后来了解到SUI框架的作者另外开了一个新的项目Light7,相当于SUI的升级版,修复了很多bug,还扩展了一些新的功能,而且会长期维护更新,于是又切换新的UI库。

这次前端UI框架的选择,给我最大的体会是项目风险管理,在开发过程中引入新技术,不可避免地要遇到各种风险。对于新技术开发,在项目开发早期,就应该建立系统的架构,解决关键技术难题、开发的基础构件,对所需要应用的技术做深度探索。越是技术复杂度高的项目,就越应该早地处理技术难题。新技术开发是探索性很强的工作,潜在着许多失败的风险,在可行性分析阶段,要广泛搜集相关信息,设计多种可行方案,进行充分论证。如果针对新技术,没有经验可借鉴,探索过程中要充分利用互联网资源,学习同行经验,往往事半功倍。

用户体验

微信端开发类似一个App软件应用,页面数据渲染速度对用户体验是至关重要的,微信端数据加载采用的是Juicer模板渲染的方式,高效、轻量的前端 (Javascript) 模板引擎,当用户进行滚动加载或者下拉刷新时,体验很流畅。对于ASP.NET MVC程序,需要解决一个符号的冲突,把@符号换成&,然后把后端处理得到的数据封装成指定的JSON格式,绑定模板即可。模板的定义(注:这里的"{&"符号使用必须修改juicer.js中的"{@"):

<script type="text/template" id="morder_li_head">
    {&if head != null }
    <div class="list-group">
        <ul class="list-block list-container media-list" >
            <li class="list-group-title" >${head.ItemClassName}</li>
        </ul>
    </div>
    {&/if}
</script>
封装JS调用,以参数的形式指定渲染的模板ID和数据,统一处理渲染数据的判断过程,降低代码冗余:
initTpl = function (e, t, n) {
	n || (n = !1),
	"feed_list" != e || t.showDing || 0 == t.showDing || (t.showDing = !0);
	var i = $("#" + e).html(),
	a = juicer(i),
	o = a.render(t);
	console.log(t);
	return t.page && !n && t.total > t.page * t.count && null != t.data && t.data.length > 0 && !n && (o += loadMoreHtml),
	o
}
调用方法就是:
list = JSON.parse(e);
$("#popup-info").find("#inventoryview").html(initTpl("morder_li_head ",  list));

管理后台

当申请微信公众号,都会有一个相应的微信管理登陆后台,但是,对于微信端很多自定义功能,需要管理后台进行统一的管理,比如:微信投票项目的发起,参与公司的审核,投票数据统计,ERP用户与微信账号的对应关系,ERP菜单权限分配。数据处理采用的优秀的开源项目jQuery MiniUI,丰富的UI控件、高度的稳定性、强大的扩展能力和平滑的版本升级能力。

集成的功能:系统管理里添加了登陆用户角色和权限管理,指定不同用户类型不同的功能,最高管理员权限用户可以管理多个微信公众号(这一点仍在开发中...),只需开放企业管理员账户给相应客户即可。管理后台添加了日志管理功能,做到错误记录,方便管理员跟踪。对于微信ERP主要是企业号应用管理,微信端ERP菜单管理,微信用户添加、修改和关联ERP用户,分配ERP菜单权限,以及指定微信用户发送文本、图文、图片、文件、视频、语音消息。

注:后续我还会针对应用的技术进行拆分讲解记录,主要是给自己做一个积累,也供大家学习参考,少走弯路。

时间: 2024-10-09 18:17:51

微信开发小结——积累与沉淀的相关文章

使用Html5+C#+微信 开发移动端游戏详细教程 :(一)序(关于作者创业失败的感想)

说起梦想,我清楚的记得2012年7月初毕业,拿到毕业证书的那天果断买好了次日南下去深圳的绿皮火车票,500多块,26个小时车程.第二天就拖上行李到了深圳. 一开始的想法仅仅是过去想见见世面,学习点新技术,不过对于刚毕业的人来说机会并不多,何况我还是大专文凭,整日游荡在人才市场和出租房之间, 不过好在工作还是找到了,但工资只有2000多,基本吃饭加房租就没了,技术上也没什么长进,深圳的消费和房价让人望尘莫及.半年不到之后,卷铺盖走人. 回到老家后,应他人邀请到常州发展,在一个旅游公司做网站,修电脑

CSDN专家精选,微信开发学习路线大有看头!

1999年成立至今,CSDN积累了丰富的IT专业技术内容.现在,我们邀请了数百位各领域专家,深入挖掘CSDN站内优质资源,按照从基础到高阶的学习路径,逐步打造覆盖热门技术领域的学习路线,并结合CSDN产品家族(视频学院.技术问答.交流社区等),为广大开发者和IT从业人员提供最为便捷与专业的在线学习平台. CSDN推出的开发技术精品资源合集,按照技术领域,分为不同的学习路线.内容涵盖入门.进阶.实战三个阶段,以帮助开发者系统学习掌握专项技术,快速提升开发水平. 截止目前,已经上线了Rust开发技术

微信开发系列教程:(1)订阅号和服务号深入分析

微信开发系列教程,将以一个实际的微信平台项目为案例,深入浅出的讲解微信开发.应用各环节的实现方案和技术细节. 原创内容,欢迎转载,转载请注明出处. 首先在第1章节中,我们先理清什么是订阅号,什么又是服务号,以及两者的关键性区别. 订阅号和服务号统称为微信公众号. 订阅号强调媒体资讯属性,为会员提供信息订阅,适用于新闻传媒类企业.订阅号从某种意义上来讲,是拿来做内容的,如果你没有原创作品,对用户没有任何意义. 服务号强调服务和应用属性,旨在为会员提供服务并与之互动.支持所有微信高级接口,几乎所有的

微信开发】【Asp.net MVC】-- 微信分享功能

[微信开发][Asp.net MVC]-- 微信分享功能 2017-01-15 09:09 by stoneniqiu, 12886 阅读, 15 评论, 收藏, 编辑 内嵌在微信中的网页,右上角都会有一个默认的分享功能.如下图所示,第一个为自定义的效果,第二个为默认的效果.实现了自定义的分享链接是不是更让人有点击的欲望?下面讲解下开发的过程. 一.准备,设置js接口安全域名 这需要使用微信的jssdk,先需要在微信公众号后台进行设置:公众号设置-->功能设置-->JS接口安全域名.打开这个页

基于SpringBoot的开源微信开发平台,Jeewx-Boot 1.0 版本发布

项目介绍 JeewxBoot 是一款基于SpringBoot的免费微信开发平台.支持微信公众号.小程序官网.微信抽奖活动. Jeewx-Boot实现了微信公众号管理.小程序CMS.微信抽奖活动等基础功能,便于二次开发,可以快速搭建微信应用!Jeewx-Boot独创插件开发机制,实现了每一抽奖活动(砸金蛋.刮刮乐.砍价等).官网.商城都是一个独立的插件,对JAVA来讲就是一个JAR包,可以很方便的做插拔,最终打造像discuzz.微擎一样的插件生态圈.. Jeewx-Boot诞生的目的 Jeewx

【微信开发】网页授权多域名解决方案

在做微信开发的时候,会遇到这样的场景:一个公众号,会有多个业务:官网.论坛.商城等等 网页授权是只能一个域名,那么问题来了?这怎么搞? 答案就是: 做一个中转服务! 域名1: www.test.com 域名2: bbs.test.com 这时候,再解析一个二级域名:code.test.com 作为中转授权域名 并在微信公众平台后台网页授权域名地方填写这个 中转域名 www.test.com   授权代码改为: header("location:http://code.test.com/code.

Java企业微信开发_09_身份验证之移动端网页授权(有完整项目源码)

注: 源码已上传github: https://github.com/shirayner/WeiXin_QiYe_Demo 一.本节要点 1.1 授权回调域(可信域名) 在开始使用网页授权之前,需要先设置一下授权回调域.这里瞬间想到之前做JSSDK的时候,也设置过一个域名.二者本质上都是设置可信域名. 当用户授权完毕之后,请求将重定向到此域名(或者子域名)下的执行者(jsp页面或者servlet等).如何设置授权回调域,请见第二节. 1.2 获取Code https://open.weixin.

夺命雷公狗---微信开发23----客服消息接口基础和推送文本

我们这边课程里面一共用到了三个文件,分别是WeChat.class.php和common.php以及index.php 我们在写这个功能之前也要学会查手册,手册我们可以在微信开发这里找到,如下所示: 点击进去后我们将会看到客服接口,我们可以点击下进去看看里面有什么动动 这里有一个发送文本消息的,我们点击进去看下 这里很明显就看到文本消息是通过一个json数据来进行实现的,废话不多说,开工 这里我们先来写一个WeChat.php的文件,这里作用主要适用于封装一个CURL上传类的,代码如下所示: <

微信开发学习总结(一)—微信开发环境搭建

目前移动App开发领域主要分为以下几种类型: 一.微信开发环境搭建 1.要有一个用来测试的公众号. 2.用来调式代码的开发环境 1.1.注册测试公众号 微信公众号分为服务号.订阅号.企业号,订阅号可以个人申请,服务号和企业号要有企业资质才可以. 我们所说的微信公众号开发指的是订阅号和服务号. 关于订阅号和服务号的区别,官方是这样解释的 服务号:主要偏向于服务交互(功能类似12315,114,银行,提供绑定信息,服务交互),每月可群发4条消息:服务号适用人群:媒体.企业.政府或其他组织. 订阅号: