作者归档:jucelin

开发企业微信专用小程序遇到的问题

企业微信移动客户端从2.5.8版本开始,有内置小程序基础库,开发者无需做适配,即可将微信小程序移植到企业微信上运行,同时开发者也可以针对企业微信提供的特殊接口开发出更适应于企业内部场景的小程序。需注意,目前企业微信只支持运行已在微信侧上架的小程序,暂不支持独立的企业微信小程序。

这段无责任复制自官方文档,这让开发者开心,因为无需修改即可直接套用再企业微信上。

但上面的引文的最后一句需要开发者特别注意,即不可以从零开始开发仅适配企业微信的小程序

问题点

下面就列举下我们从零开始开发一个只能在企业微信中使用的小程序所遇到的问题:

1. 一个小程序需要一个注册一个开发者帐号,一个身份证只能注册5个帐号,每个帐号独立独立认证

虽然现在可以通过已认证的公众号来快速认证,但这样的限制对于开发企业内部应用来说,限制太大了。

2. 小程序命名不可重名

我们的需求是仅可用于企业微信,不对外开放,那么按照一般的惯例,名称应该可以随便取。但实时上不可以。

3. 调用企业微信专属API需要先关联到企业微信

文章开头的引言的最后一句话也说了,只能关联已发布的小程序,可是目前我们的小程序还在开发阶段。我也到小程序社区发帖咨询,得到的回复是

因为企业微信也是支持wx.login的,先两边都处理成一致,发布关联成功再去调试企业微信的相关接口吧

换句话说就是,先适配微信端开发,完成了审核发布,再关联到企业微信中,然后二次开发适配企业微信端的。

4. 开发调试

我们想在开发时,在企业微信上联调,目前暂时无法实现。仅能通过“预览”-“二维码”的方式在企业微信中打开开发版。

5. 发布均需要审核

理论上,我们开发的仅可在企业微信中使用,完全可以开放审核,减少发布步骤。

6. 微信和企业微信的小程序支持库还是有点差距的

这个官方文档有介绍,另外某些组件在企业微信上的表现可能不是预期的。

7. 无法关闭微信的访问通道

因为无法关闭,我们开发时需要额外进行2步操作:

  1. 在小程序后台关闭可以被搜索;
  2. 在小程序中判断打开的环境,如果是微信,则做相应的提示,引导用户在企业微信侧打开。

结语

实际上,小程序对于企业微信来说还只是起步,企业微信也没有真正重视小程序的应用,导致目前开发上遇到很多阻碍。

企业微信小程序Access Token过期策略

官方文档中描述了过期策略,即expires_in标注的有效期。实际测试时和微信公众号的过期策略还是不一样的。

实际测试中,每次调用API,返回的都是相同的token,而且有效期都是7200s,那么你肯定有这样的疑问

Access Token到底什么时候到期?

在与企业微信客服咨询后,得到下图:

通过对比,我们得出下面的结论:

微信公众号 企业微信
唯一性 同时仅存1个有效token 同时可存在2个token
过期时间 最长7200s,如果提前请求token,原token立即过期 最长14400s,在token过期前请求,将自动延长7200s,但在7200s后请求,将产生新的token,同时这2个token均有效

上面的对比,是无法在官方文档中找到的。

我使用了中控7000s刷新token,已实现安全过渡。当然也可以设为3600s+的时间刷新。

HTML邮件设计注意点

由于查看邮件的客户端很多,如网页、outlook2003/2007/…、手机浏览器、第三方邮件APP。公司邮件主要涉及PC网页、outlook各个版本,因此考虑的更少。记录下遇到的问题:

  1. head中的style定义无效

    一般写网页,喜欢在head中定义css样式,可惜在此处失效。以网易邮箱PC网页版为例,网易邮箱会主动截取<body></body>之间的代码作为邮件内容,如果在head中定义样式,将不被加载;QQ邮箱PC网页版则会全部加载;outlook2003表现正常,但2007同样不会解析。

  2. 布局使用table

    DIV除了块级的表现正常,其他则出现了异常,如float/position/width/margin:0 auto 等等。所以先使用table作为最大的父级,需要居中,可以是设定align=”center”。

  3. 使用内联样式

    CSS中子级会继承父级的样式,但outlook中表现奇怪,因此保险起见,为最小的子级定义内联样式。如<td style=”color:red”>警告</td>。

  4. line-height无法实现垂直居中

    设计的过程中,我参考了京东商城发送的电子邮件,表头使用的height+line-height来实现垂直居中,但outlook7中表现为底部对齐,可能原因是outlook2007的解析原理不一致,我们可以使用padding来撑高。在文字段落中line-height仍然是正常的。

  5. 各版本解析方式不一致

    参考文章①和②已列出来,简单而言就是outlook2007使用的是word引擎(HTML e-mails are now displayed by a word engine),想区别的,2003版本则是使用的是浏览器引擎,2012为深究。其他的PC网页版则肯定使用的浏览器引擎,微信也是使用的浏览器解析引擎。

  6. outlook转发会丢失样式

    HTML邮件在outlook中表现正常,但转发时会调用word编辑器,则会破坏了原来的样式,最明显的表现就是会在每个table结束时加个换行。目前还没找到具体的解决办法,如果有网易邮箱的“原件转发”功能,是否能解决呢?
    mail-wiht-html

  7. 尽可能不要使用图片

    由于outlook的安全设置,默认都是不显示图片的。如果使用到了,需指定宽度和高度,避免图片不显示是预留位置撑破页面。

  8. 统计邮件到达及阅读情况

    阅后回复是个方案,更为简单的方法是使用图片。在邮件底部隐藏一个图片,图片地址则是包含统计参数的URL,如京东的:

    <table style=”display:none;” width=”1″ height=”1″><tr><td><img width=”1″ height=”1″ src=”http://csc.jd.com/log.ashx?type1=edm&amp;type2=stats1&amp;data=A_1770035069%7C%7C%7Cwebmaster@webmaster.com%7C%7C%7C1400010897587″></td></tr></table>

    当然上一条已经决定了该方法存在失效的可能。

  9. 将发件人加入通讯录

    由于邮件标题一样,如果大量发送邮件,经常会被列入垃圾邮件,避免这种情况,可以考虑动态生成标题,并要求收件人将发件人加入通讯录。这里不得不吐槽godaddy,正常通知邮件和广告邮件的发件箱相同,导致正常的通知邮件也被列入广告邮件中。

  10. 将附件中图片插入的邮件内容中

    请阅读参考文章③

其它待补充。

参考文章:

  1. Word 2007 HTML and CSS Rendering Capabilities in Outlook 2007
  2. Inxmail Guide HTML E-mails with Outlook 2007
  3. RFC 2111 – Content-ID and Message-ID Uniform Resource Locators (RFC2111)

Highcharts导出gb2312乱码问题

Highcharts是utf-8编码的,其本地的.net导出环境也是utf-8格式的,导致网页如果采用gb2312编码,显示正常,导出就乱码了。这种现象也同样经常出现在ajax的使用过程中。

ajax中一般的解决办法就是将中文等非英文的字符进行escape编码,再由后端模拟unescape解码,以避免编码的问题。跟着这个思路修改以解决Highcharts的导出乱码问题。同时为了配合后端简化,我使用了encodeURIComponent去编码。

由于需要在提交之前进行编码,那么我们需要修改Highcharts的导出文件的源码,你需要慎重考虑下。

1.前端

我们修改js/modules/exporting.src.js中的Highcharts.post方法:

	// add the data
	for (name in data) {
		createElement('input', {
			type: HIDDEN,
			name: name,
			value: encodeURIComponent(data[name])//here we add escape for all value
		}, null, form);
	}

修改上面的代码,在value的值前全部加上encodeURIComponent的编码方法。

2.后端

我们修改项目中的Exporter.cs,在class Exporter下增加下面的函数,并将接收的参数进行编码:

    /// <summary>
    /// Unescape for javascript escape. Return string;
    /// </summary>
    public static string UnEscape(string str)
    {
        return HttpUtility.UrlDecode(str);
    }

    //在Exporter中我们同样要修改如下
    //unescape all arguments
    string extension;
    fileName = UnEscape(fileName);
    this.ContentType = UnEscape(type).ToLower();
    this.Name = fileName;
    this.Svg = UnEscape(svg);

保存,生成,将生成的dll文件覆盖现在使用的,再次导出基本上可以解决乱码的问题。

其他说明

1.由于使用的是HttpUtility.UrlDecode()方法,如果你传递前没有encodeURIComponent,且编码就为utf-8,那么导出也是正常的;

2.没有经过大数据的测试,用于正式项目前建议您先测试下;

3.压缩包:http://pan.baidu.com/share/link?shareid=1309032918&uk=352812205

4.由于使用了编码,因此导出的文件名也是可以被指定为中文的;

5.导出文件的width必须被指定,否则导致导出出错,待修复。

压缩包中的版本已经修复的问题:

1.未选中项目导出时未被忽略,描述:http://www.cnblogs.com/youngerliu/p/3177252.html

2.网页为gb2312,导出时中文乱码问题。

highcharts的.net本地导出环境安装记录

由于项目中highcharts需要内网使用,需要本地搭建导出的环境。下面简述下步骤:

1.下载开源的.net导出文件:https://github.com/imclem/Highcharts-export-module-asp.net

2.新建虚拟站点,IIS下配置如图:(注意端口设定:80端口已经用了,就设定为8081;应用池的设定,仅支持framework3.5以上版本)

20130803162202

3.拷贝下载的压缩包中的Exporting_Demo_website文件夹下的文件到新站点的目录下。删除目录下的web.config文件,重命名web-dotNET4.0.config为web.config。(不需要Exporting_Demo_website这个文件夹,文件放在根目录下即可,否则后面的操作全部要加上这个路径)

4.打开站点http://localhost:8081/访问,内置一个Demo,选择导出,看是否正常。正常即完成。不正常就需要修正了。

访问Demo时出现500错误?

打开IIS管理器,选择“ISAPI和CGI限制”,里面找到我们上面设置的framework的版本,设定为允许。

关于未选中的数据线导出时依然显示的BUG

BUG描述及修复,请参见http://www.cnblogs.com/youngerliu/p/3177252.html

需要修改的地方是在Exporter.cs的CreateSvgDocument方法

private SvgDocument CreateSvgDocument()<br />    {<br />      SvgDocument svgDoc;<br /><br />      XmlDocument xml = new XmlDocument();<br />      xml.LoadXml(this.Svg);<br />      XmlNodeList nodeListAllg = xml.GetElementsByTagName("g");<br />      Dictionary&lt;int, XmlNode[,]&gt; dic = new Dictionary&lt;int, XmlNode[,]&gt;();<br />      int i = 0;<br />      foreach (XmlNode xNod in nodeListAllg)<br />      {<br />          i++;<br />          XmlNode xmlvisibility = xNod.Attributes.GetNamedItem("class");<br />          if (xmlvisibility != null &amp;&amp; xmlvisibility.Value == "highcharts-series-group")<br />          {<br />              foreach (XmlNode xNod2 in xNod.ChildNodes)<br />              {<br />                  i++;<br />                  XmlNode xmlvisibility1 = xNod2.Attributes.GetNamedItem("visibility");<br />                  if (xmlvisibility1 != null &amp;&amp; xmlvisibility1.Value == "hidden")<br />                  {<br />                      XmlNode[,] xmln = new XmlNode[1, 2];<br />                      xmln[0, 0] = xNod;<br />                      xmln[0, 1] = xNod2;<br />                      dic.Add(i, xmln);<br />                  }<br />              }<br />          }<br />          else if (xmlvisibility != null &amp;&amp; xmlvisibility.Value == "highcharts-tooltip")<br />          {<br />              XmlNode[,] xmln = new XmlNode[1, 2];<br />              xmln[0, 0] = xml.FirstChild;<br />              xmln[0, 1] = xNod;<br />              dic.Add(i, xmln);<br />          }<br />      }<br />      foreach (KeyValuePair&lt;int, XmlNode[,]&gt; a in dic)<br />      {<br />          a.Value[0, 0].RemoveChild(a.Value[0, 1]);<br />      }<br /><br />      this.Svg = xml.OuterXml;<br /><br />      // Create a MemoryStream from SVG string.<br />      using (MemoryStream streamSvg = new MemoryStream(<br />        Encoding.UTF8.GetBytes(this.Svg)))<br />      {<br />        // Create and return SvgDocument from stream.<br />        svgDoc = SvgDocument.Open(streamSvg);<br />      }<br /><br />      // Scale SVG document to requested width.<br />      svgDoc.Transforms = new SvgTransformCollection();<br />      float scalar = (float)this.Width / (float)svgDoc.Width;<br />      svgDoc.Transforms.Add(new SvgScale(scalar, scalar));<br />      svgDoc.Width = new SvgUnit(svgDoc.Width.Type, svgDoc.Width * scalar);<br />      svgDoc.Height = new SvgUnit(svgDoc.Height.Type, svgDoc.Height * scalar);<br /><br />      return svgDoc;<br />    }

注意:复制上面博客中的代码时,需要在项目中引入相关的文件,如图

20130803163428

这里我已经生成,没有环境的朋友可以直接到这里下载:http://pan.baidu.com/share/link?shareid=1300438122&uk=352812205(下载后直接把Bin目录下的4个文件覆盖掉项目Bin文件夹下的4个文件)

生成时出现“不是标准win32文件”

菜单栏—工具—导入与导出设置—重置所有设置—下一步。完成后重新生成,依然无效,只有重启电脑(我是重启电脑解决的)。

外部调用地址

在你的文档里面增加设定,width为必须项,否则报错

exporting: {<br />                url: 'http://localhost:8081/HighchartsExport.axd',<br />                filename: 'MyChartX',<br />                width: 1200//必选参数<br />            }

win2003 server配置时出现500错误

注意开启IIS的写权限,因为highcharts的导出代码可能较大,所以导出使用的是上传文件流的方式,具体可参考exporting.src.js源码。另外在正式服中配置时特别注意端口冲突及framework的版本问题(如果选择4.0以上版本,需要修改web.config,上面有提到),建议先找个win2003的测试服试试!

导出Pie图形时无数据的问题

此问题来自:http://www.cnblogs.com/wxmxiaoming/articles/3522468.htmljucelin没有验证,供参考。

080940233723150

解决方法:

从以下地址下载Svg.dll文件覆盖Bin目录下对应的文件即可(两个文件虽然版本一样,但是MD5值不一样);

http://svg.codeplex.com/

jquery触发两次onchange事件

因为项目中需要校验信息,又不想给服务器带来较大负荷,就使用onchange来实现校验。使用jquery绑定change事件,如下面的代码:


<script type="text/javascript">
        $(document).ready(function()
        {
            $('#test1').bind("change", function()
            {
                alert(this.value);
                this.value = this.value+"aa";
            });
        });

</script>
<input id="test1" type="text" />

演示地址:http://runjs.cn/detail/1r4wltof

测试环境

目前仅在IE8下发现此类问题,我仅测试了IE8/Chrome25/Firefox19

原因分析

google了下,有人将此问题归类为jqueryBUG,存在于1.4 – 1.6.4.版本,详见原帖内容
个人认为,在操作中js改变了input的内容,导致再次触发change事件。那么再次处罚了change事件后,内容也发生了改变,理论上应该进入死循环,但实际上只触发了2次。另外我也尝试了直接给input添加onchange属性来触发,开始时,也是触发了2次,但不知道改变了什么,后来仅触发了1次。

解决方法

我尝试了先解绑,再绑定的方法。注,#test1的方法是正确的,#test2的方法则是没实现的,作对比。setTimeout的方法来自这里.

$(document).ready(function(){
	$('#test1').bind("change", function(){
		var thatFun=arguments.callee;
		var that=this;

		$(this).unbind("change",thatFun);

		//you can do something here
		alert(this.value);
		this.value=this.value+"aa";

		//rebind again
		setTimeout(function(){$(that).bind("change",thatFun)},0);//why use setTimeout? sorry, I don't know...
	});

	//without setTimeout, it will not work. just like this.
	$('#test2').bind("change", function(){
		$(this).unbind("change",arguments.callee);
		alert(this.value);
		this.value=this.value+"aa";
		$(this).bind("change",arguments.callee);
	});
});

Typecho又拍云Upyun插件:UpyunUploader

插件作用如其名UpyunUploader。因为图片使用又拍云的外链比较方便,最主要的是网站在长城外,但图片在长城内,由此可大幅度的提高加载速度。

在最新稳定版0.9 (13.12.12)中测试通过,可正常使用。注意检查下插件配置是否正确。

如何安装

下载-上传-安装-配置。配置中几个项目都必须填写,如果信息填错了,那么上传肯定失败。目前仅测试了typecho的“最新版”0.8(10.8.15)-release。

下载地址:百度网盘 | 华为网盘

如何使用

配置完成后,当你上传附件时,插件会自动将上传的附件上传一遍到又拍云,如果上传成功,则会返回成功后的外链地址。再点击插入后,可以看到使用的就是外链地址了。

已知缺点

1.会直接在你的又拍云空间里面创建文件夹usr/uploads/…,以实现本地目录和又拍云空间里面的目录保持一致。

2.如果本次上传的文件没有插入到文章内容中去,那么下次打开后点击插入,则会使用本地的文件路径。解决办法可以直接将你的又拍云外链地址替换本地地址即可,原因由上面一条说明。

3.其他暂未知。

PS:吐槽下,TE新版开发太慢了…

Godaddy域名续费优惠码

刚续费了jucelin.com,找了半天优惠码,就【ZEN10】这个优惠幅度比较多大,最后续费价格是$7.67=RMB48.94,支付宝支付。下面是可能还能用的优惠码,自己掂量着试试吧。

续费.com域名仅需7.49美元优惠码:【ZEN10】

续费在Godaddy的.com域名仅7.49美元/年,支持支付宝。

续费.COM域名仅7.99美元优惠码:【bb5020d5】

续费在GoDaddy的.COM域名仅7.99美元/年,支持支付宝。

续费.COM域名仅8.49美元优惠码:【cjc795dom】【gdbbren8】

续费在GoDaddy的.COM域名仅8.49美元/年,支持支付宝。

续费.NET域名仅7.49美元优惠码:【emfb7】【cwm7】

续费在GoDaddy的.NET域名仅7.49美元/年。支持支付宝。

续费.NET域名仅7.50美元优惠码:【gdbbren8】【bb5020d5】

续费在GoDaddy的.NET域名仅7.50美元/年,支持支付宝。

续费.NET域名仅7.99美元优惠码:【scam14】

续费在GoDaddy的.NET域名仅7.99美元/年,支持支付宝。

续费.ORG域名仅7.49美元优惠码:【emfb7】【cwm7】

续费在GoDaddy的.ORG域名仅7.49美元/年,支持支付宝。

续费.ORG域名仅7.50美元优惠码:【gdbbren8】【gdbb776】

续费在GoDaddy的.ORG域名仅7.50美元/年,支持支付宝。

提示:复制的时候不要把方括号也复制了。

onpropertychange功能的兼容

IE的onpropertychange十分的好用,可惜的是只兼容IE,非IE就悲剧了。还好现在HTML5中的oninput已经兼容了这个功能。下面写了个测试页面,大家可以试试。

Demo:lab/onpropertychange/onpropertychange.html

看到这里,你需要知道onpropertychange的作用,还有onchange/onkeyup/onkeydown/onkeypress这几个属性的不同作用。

另外,前辈们已经写了个JS来完美支持这个特性,在Demo中也加入了进去,代码看下面


function immediately(){
	var element = document.getElementById("mytext");
	if("\v"=="v"){//判断IE
		element.onpropertychange = webChange;
	}else{//非IE
		element.addEventListener("input",webChange,false);
	}
	function webChange(){
		if(element.value){document.getElementById("test").innerHTML = element.value};
	}
}

使用建议

如果是只开发移动项目,只用oninput就OK了,如果是非移动项目,用onpropertychange+oninput基本就OK,我使用这2个方法测试了Chrome15、Opear12、IE6、IE7、IE8,均兼容,对于低版本的Chrome和Opear未测试。如果你的浏览器和我测试的不同,欢迎测试并反馈给我,万分感谢。

其他资源:

《js监听输入框值的即时变化》

《哥俩好:oninput & onpropertychange》

《A HTML5 Browser maze, oninput support》

升级在线挂QQ系统-QQ挂机宝

关于QQ挂机宝,可以移步这里看下:PHP模拟QQ登录,宣传版的:QQ挂机宝:免费在线挂QQ

因为TX方面将3g版QQ的安全机制进行了升级,从3g版登录后,如果IP地址改变,将要求再次输入验证码,否则无法正常登录,所以原先只需要本地获得的SID和QQ号即可登录的方式已经失效,而需要在挂QQ的服务器上成功登录获得的SID才可以无验证码方式登录。

说起来升级,其实也就在自动获取SID的地方增加了验证码的输入并提交,让QQ能成功的在服务器的IP地址上完成一次成功登录。

挂Q地址:QQ挂机宝(推荐非IE访问)

在原版本中,很多朋友都加我,并向我要源码。这里需要说明下:

1. 这个程序本身就是利用的TX漏洞或者说设计上的不足来写的,如果开源,后果你懂的,当然核心源代码其实已经公布了;

2. 我发布的QQ挂机宝是多用户版的,而如果想单个QQ挂机,可以直接参考PHP模拟QQ登录

3. 考虑到这次升级的内容,估计PHP模拟QQ登录中的方法仅支持本地了。

4. 程序中仅记录QQ号和SID,不存储QQ密码,个人人品保证,如果不信,那随便吧。

5. 程序依然有很多不足,只能说尽量去实现,欢迎提意见。

PS:好久没写日志了,懒了很多。发现现在和玩微博一样,基本上都是以看为主,所以如果没有及时回复留言,还请见谅。广告下,我的腾讯微博@jucelin,哈哈。

CSS制作小箭头

在西门大哥的博客中看到一篇文章:CSS实用小技巧,利用border属性实现一个标签做箭头,西门使用的是border,这里jucelin介绍另一种方法,用到的是一个特殊字符:◆。

演示DEMO

代码:请狂击DEMO,然后右键,查看源代码(写得应该还算规范)。

主要用途:制作tips等。

实现原理:方法很简单,特殊字符◆就已经有了箭头的效果,那么用2个◆,用相对或绝对定位将他们完全重合,如果想做成向上的箭头,则再将下一层的◆向上移动1px。设置下颜色:下一层的使用的是下面内容部分的边框色,而上一层的◆使用的是内容部分的背景色,这样就出现一个想要的样式。

兼容性:用的position定位,兼容性你懂的(DEMO中未测试,用于生产需自测)。

比较下

西门大哥的方法并不好实现border同一色的问题,当然如果使用上面的方法也是可以实现的。

最后说明

如果一个页面中用了很多tips箭头,我仍然建议使用图片,减少浏览器的渲染时间,当然似乎要很多很多,才能看出浏览器有卡的效果。

相关资源

另一种实现小箭头的方法:CSS实用小技巧,利用border属性实现一个标签做箭头

WP修改自带jquery加载方式

调用自带jquery方法

<?php wp_enqueue_script("jquery"); ?>

但要注意的是: wp_enqueue_script(“jquery”); 务必加在 wp_head(); 的前面。

同时,需要注意的是wordpress自带的jquery和官方的jquery是有区别的,自带的jquery则需要这样使用:

jQuery(document).ready(function($) {
// "$"符号在这里才能被识别
});

WP 的 jQuery 和原版唯一的不同, 就是在最后一行加了 jQuery.noConflict();这个noConflict() 就是为了与其它的library 兼容性, 如:Prototype, MooTools, 或 YUI。

调用其他jquery方式

1.最直接的:

<script type=”text/javascript” src=”<?php bloginfo(‘template_url’); ?>/js/jquery.js”></script>

2.调用谷歌 Google 的 API库:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
//最好再加上以下代码,一边在连接google的API库是失效时调用本地的jQuery文件:
<script>
!window.jQuery && document.write('<script src="jquery-1.6.1.min.js"><\/script>');
</script>

取消使用自带jquery

网上最多的方法是在/wp-includes/script-loader.php的119行,将

$scripts->add( 'jquery', '/wp-includes/js/jquery/jquery.js', false, '1.7.1' );

//修改为

if(is_admin()){
 $scripts->add( 'jquery', '/wp-includes/js/jquery/jquery.js', false, '1.7.1' );
}

这个方法不支持wp升级,因为升级后会将这个文件修改回来。另外jucelin想到的最简单的方法就是,将官方的jquery替换自带的jquery文件(这个方法会导致后台无法使用自带jQuery!)当然这也应该不支持wp的升级,升级后会被新的jquery覆盖掉。

参考来源:

1.在WordPress调用jQuery的方法及注意事项

2.去掉wordpress自带的jquery 及 附属信息