Tag Archives: 微信公号

Hello World 微信开发

通过iBeacon接入微信摇一摇

什么是iBeacon?维基百科的定义是这样的:

一套iBeacon的部署由一个或多个在一定范围内发射传输他们唯一的识别码iBeacon信标设备组成。接收设备上的软件可以查找iBeacon并实现多种功能,比如通知用户,接收设备也可以通过链接iBeacons从iBeacon的通用属性配置服务来恢复价值。iBeacons不推送通知给接收设备(除了他们自己的ID),然而,手机软件可以使用从iBeacons接收到的信号来自己推送通知

不用太关注这个定义,微信摇一摇.周边功能,虽然使用到iBeacon,但其实只用到了它的“信标”功能,具体过程是这样的:

  1.  iBeacon基站通过不断地通过蓝牙广播自己的存在(实际有间隔,100~5000+ms)
  2. 用户手机打开微信摇一摇界面时,如果此时蓝牙是打开的,摇一摇就会就会在“人、歌曲、tv”之外多出一个“周边”,并且默认是“周边”
  3. 用户这时摇手机,就会出现第一步 iBeacon基站相关的信息

那么, 这个 iBeacon设备的信息如果设置哪?

  1. 首先,需要有一个开通支付功能的微信服务号
  2. 微信公号后台“新功能插件”里,选择“摇一摇周边”,申请
  3. 登录摇一摇后台(zb.weixin.qq.com),“设备管理”,新建设备,申请新设备的UUID/Major/Minor
  4. 将上述参数设置到你的iBeacon设备设备内

关于iBeacon基站,摇一摇后台就很多的推荐,另外,你也可以在淘宝购买,甚至可以自己购买蓝牙模块,通过简单配置,将其变成蓝牙基站

下面的这个链接,讲述了通过树莓派将HM-10蓝牙模块配置成iBeacon基站的方法,操作简单,亲测可用

http://www.xuebuyuan.com/2015895.html

 

 

Hello World 微信开发

玩转微信公号开发(九)——获取用户信息

这里的“用户信息”,指的是昵称、头像等信息,具体的:

1
2
3
4
5
6
7
8
9
10
11
12
{
    "subscribe": 1, 
    "openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M", 
    "nickname": "Band", 
    "sex": 1, 
    "language": "zh_CN", 
    "city": "广州", 
    "province": "广东", 
    "country": "中国", 
    "headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0", 
   "subscribe_time": 1382694957
}

具体的接口是:
https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

这里的ACCESS_TOKEN获取方法可以参考本系列之前的文章

如果用户没关注,subscribe字段为0,没有nickname、headimgurl等字段,只有用户关注你的公众号,才能拿到上面的全部信息

你可以用这个接口取得用户基本信息,也可以那它判断当前用户是否关注你的公众号

早期的时候,微信对用户基本信息控制的比较严格,只有用户授权过才能拿到这些信息,而且,再次拿信息的话,还要重新授权

偶然才看到微信的文档有了升级,用户信息接口换成了这个新的:/user/info,免去了惹人厌的授权过程。这点小小的开放,让很多基于微信的活动方案成为可能【赞一个】

————–
转载请注明出处:http://www.jiangkl.com/2014/04/weixin_user_info

Hello World

玩转微信公号开发(八)——消息的排重与回复

随着微信公号系统的逐步完善,原来的许多机制都得到了升级、增强,这可以让我们公众号的表现更稳定,但有时,也会给我们带来一下麻烦,比如下面这段微信文档新增的内容

————————————————
微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次,如果在调试中,发现用户无法收到响应的消息,可以检查是否消息处理超时。

关于重试的消息排重,有msgid的消息推荐使用msgid排重。事件类型消息推荐使用FromUserName + CreateTime 排重。

假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。 这种情况下,可以使用客服消息接口进行异步回复。
————————————————

首先,如果后端没有复杂的逻辑,5秒足够了,但是如果不能保证5秒内回复消息,就只能调客服消息接口了,可惜客服接口属于高级接口,订阅号是没有的(坑爹啊!),并且,即使是订阅号,客服消息的限制也挺多

另外,所谓的“断掉连接,重新发起请求”并不靠谱,我自己扫码或者点按钮后就经常会收到重复消息,也就是说,第一个请求还没结束,的二个请求可能就来了。。。

综合这两点,我们其实可以搭建一种这样的回复方式:

一个消息来了以后,首先根据微信文档里提到的排重方式,比如使用fromusername/msgid/event/count/createtime做md5,作为key,来标示这个消息,在这个请求内,处理相关的业务逻辑,但处理结果不在这个消息内回复,而是放到类似redis的缓存内

再有消息来时,由于同一个消息重复发送,key也是相同的,首先检查redis有没有该消息key的回复内容存在,如果有,直接回复,如果没有,再走上面的逻辑

这样子,不但可以排重,还可以为自己的业务逻辑多争取些处理时间

 

————

转载请注明出处:http://www.jiangkl.com/2014/03/重复消息/ ‎

 

Hello World 微信开发

玩转微信公号开发(七)——账号体系与oauth登录

默认情况下,如之前“接收消息”里所说,一个用户和微信公号发生交互是,开发者拿到的是用户的openId,每一个用户,对应每一个公号,都有唯一的一个openId,当用户使用微信内置webview访问我们的页面是,开发者可以调用oauth2.0协议,302到自定的url,获取访问者的openId

1
2
3
4
5
$redirect = 'http://xxxx.xxx.com/xxx';
$url = 'http://open.weixin.qq.com/connect/oauth2/authorize?appid=your-appid&redirect_uri='
   .$redirect.'&response_type=code&scope=snsapi_base&state=ubox#wechat_redirect';
$this->redirect($url);
exit;

其中,scope=snsapi_base是要获取的权限类型,snsapi_base获取的只是openId,snsapi_userinfo可以用户获取用的较详细的昵称、头像等内容,但是是需要用户授权
上面的$redirect,就是登陆后需要跳转回来的开发者服务器的地址,这个登录操作是自动的,不需要用户做操作
跳回以后,url后附加一个code参数,通过这个code,再调微信的对应接口,即可获得openId,或者userinfo

1
2
3
4
5
6
$url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=your-appid&secret=your-appSecret&code='.
	$_GET['code'].'&grant_type=authorization_code';
$json = Http::httpsGet($url);
$wxInfo = json_decode($json, true);
$openId = $wxInfo['openid'];
//.....你的其他操作

取得json的接口如下:

1
2
3
4
5
6
7
{
  "access_token":"xxxxxxxxxxxxxxxxxxxxxxxx",
  "expires_in":7200,
  "refresh_token":"xxxxxxxxxxxxxxxxxxxxxxxx",
  "openid":"ogaN_jp4sLWa4ZXGu5L39SSKcXU8",
  "scope":"snsapi_base,"
}

如你所见,openid就在里面了,进一步的,有了access_token,scope值如果是snsapi_userinfo,那么你还可以调“/sns/userinfo”接口取用户昵称等信息
expires_in是token超时时间,refresh_token可以用来刷新access_token

————
转载请注明出处: http://www.jiangkl.com/2014/02/weixin_oauth_userinfo/

Hello World 微信开发

玩转微信公号开发(六)——设置菜单

这里要讲的是,在开发模式下,如何自定义菜单

因为可能有中文乱码的问题,所以这里直接拼json串,然后调接口,post就ok了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public function weixin_custom_menu(){
	$token 		= WXUtil::getAccessToken();
	$url 			= "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$token;
	$msg 		= '{"button":['
		//单菜单
		.'{"type":"click","name":"现在购买","key":"BTN_1"},'
		.'{"type":"click","name":"优惠活动","key":"BTN_2"},'
		.'{"name":"帮助",//多级菜单
			"sub_button":[
					{"type":"view","name":"下载","url":"http://xx.com/download.html"},
					{"type":"view","name":"使用教程","url":"http://xx.com/howbuy.html"},  
					{"type":"view","name":"关于我们","url":"http://xx.com/about.html"}
				]
			}
		]}';
	echo $msg;
	$r 		= Http::httpsPost($url, $msg);
	print_r($r);//打印结果,返回error为0的话,即为设置成功
	exit;
}

参数说明

  • type,按钮的类型
    1. click,按钮,点击后,发送给开发者网关一个事件
      view,链接,打开一个webview页面,页面地址为url字段指定
  • name,按钮的显示名称
  • key,事件标示,对应本系列第二篇里提到的EventKey字段
  • url

菜单设置后,通常需要退出公众号再进一次才能生效,如果还不行,只能取消关注、再关注一次

————
转载请注明住处:http://www.jiangkl.com/2014/01/weixin_custom_menu

Hello World 微信开发

玩转微信公号开发(五)——发送主动消息

解决了access_token的问题,让我们来看看怎么主动给用户发消息

主动消息有两类,客服消息和模板消息,微信对滥发消息很敏感,所以对这两个功能限制很多,并且,这两个功能也都术语高级接口

客服消息

顾名思义,客服消息是给客服用的,具体限制是:用户给公众号发送过消息后(发送消息、菜单点击、支付成功、用户维权、扫描带参数二维码、订阅),48小时内,开发者可以调用客服消息接口,给该用户发送消息,消息的类型可以是文本、图片、语音、视频、音乐、图文,数据的格式是json~~注意,除了前面讲到的同步回复消息疑问,以后和微信的交互的数据格式都是json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
	//$data可以是字符串,也可能是数组,随具体的$type而改变
	public function sendCustom($openId, $data, $type = 'text'){
		$msg 		= array(
			'touser'		=> $openId,
		);
		switch($type){
			case 'text':
				$msg['msgtype'] = 'text';
				$msg['text'] 	= array('content' => urlencode($data));
				break;
			case 'image':
				$msg['msgtype'] = 'image';
				$msg['image'] 	= array('media_id' => $data);
				break;
			case 'voice':
				$msg['msgtype'] = 'voice';
				$msg['voice'] 	= array('media_id' => $data);
				break;
			case 'video':
				$msg['msgtype'] = 'video';
				$msg['video'] 	= $data;
				break;
			case 'music':
				$msg['msgtype'] = 'music';
				$msg['music'] 	= $data; 
				break;
			case 'news':
				$msg['msgtype'] = 'news';
				foreach($data as $k => $v){
					if(isset($v['title'])) $v['title'] = urlencode($v['title']);
					if(isset($v['description'])) $v['description'] = urlencode($v['description']);
					$data[$k] 	= $v;
				}
				$msg['news'] 	= array('articles' => $data);
				break;
		}
		$url 		= 'https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token='.self::getAccessToken();
		$postData 	= urldecode(json_encode($msg));
		$r 		= Http::httpsPost($url, $postData, true, false);
		return $r;
	}

getAccessToken,是在取access_token
httpsPost和上次说的httpsGet类似,只多了下面的两行,$input即为post的内容:

1
2
	curl_setopt($ch, CURLOPT_POST, true);
	curl_setopt($ch, CURLOPT_POSTFIELDS, $input);

模板消息

模板消息,没有上面客服消息的限制,但是必须在微信提供的模板框架内拼出消息,如果用户想使用自己的模板,需要特别申请~~基本上很难
首先,从微信公号后台挑选可用的模板,拿到templateId,然后拼装下面结构的post参数:

1
2
3
4
5
6
7
8
$postData = array(
	"touser"	=> $openId,//接受者
	"template_id"	=> $templateId,
	//data为模板内的实际内容,字段项目视具体模板而定
	"data"		=> array("NAME"=>"里斯之泪", "PRICE"=>"¥10000.00"),
	"url"		=> "http://xxxx.xxx.com/xxxx",
	"topcolor"	=> "#333",//顶栏颜色
);

然后整理数据、调用接口就ok了

1
2
$postData 	= json_encode($postData);
$r 		= Http::httpsPost($url, $postData);

————
转载请注明出处: http://www.jiangkl.com/2014/01/custom-send_template/

Hello World 微信开发

玩转微信公号开发(四)——获取access_token与上传多媒体文件

access_token

access_token是开发者访问其他微信接口的凭证,一个微信公众号,在同一时刻,只能有一个access_token,有效时间两小时

具体的获取方法如下

1
2
3
4
5
  $url   = "https://api.weixin.qq.com/cgi-bin/token?"
      ."grant_type=client_credential&appid=".$appId."&secret=".$appSecret;
  $r     = Http::httpsGet($url);
  $r     = json_decode($r, true);
  $token = isset($r['access_token']) ? urldecode($r['access_token']) : false;

其中,httpsGet:

1
2
3
4
5
6
7
8
9
10
11
12
  function httpsGet($url){
    $ch = curl_init(); 
    $header[] = "Content-type: text/plain";
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    $response = curl_exec($ch);
    curl_close($ch);
    $result = trim(urldecode($response));
    return $result;
  }

鉴于access_token的“广泛应用”和诸多限制,我们的做法是为它做了一个redis缓存,每小时刷新一次,所有用到access_token项目都从这个缓存里取

上传多媒体文件

~~其实,俺们的项目里,还没用到过这个功能,但既然做教程,就尽量做的完整些,下面内容只是微信官方文档的整理摘录

上传地址:http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE

type: image/voice/video/thumb(缩略图)

POST字段名:media

(看这格式,还是写个html页面比较合适)

限制:
图片(image): 128K,支持JPG格式
语音(voice):256K,播放长度不超过60s,支持AMR\MP3格式
视频(video):1MB,支持MP4格式
缩略图(thumb):64KB,支持JPG格式

下载多媒体文件

http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID

~~没啥可说的,一目了然

————
转载请注明出处:http://www.jiangkl.com/2014/01/access-token_media/

Hello World 微信开发

玩转微信公号开发(三)——消息的回复

这里说的消息回复,是指对用户发给公众号消息的同步回复,用户给公众号发了消息,开发者可以不回复,或者给该用户回复一条~~只一条

回复消息的格式如下:

1
2
3
4
5
6
7
  <xml>
    <ToUserName><![CDATA[orrnVjsadf-FbumIsdafZiBUFTw]]></ToUserName>
    <FromUserName><![CDATA[gh_fsadf942sdf9]]></FromUserName>
    <CreateTime>1390889296</CreateTime>
    <MsgType><![CDATA[text]]></MsgType>
    <Content><![CDATA[你好]]></Content>
  </xml>

虽然消息里第一项就是ToUserName,但是~~这里只能回复给当前发送消息的用户,写别的用户是无效的

    MsgType包括下面几个类型:

  • text,文本
  • image,图片
  • voice,语音
  • video,视频
  • music,音乐
  • news,图文

文本

即开篇的那个例子,Content是文本内容~~~告诉大家一个官方文档没有的小秘密:使用a标签,可以给消息添加链接

图片

1
2
3
4
5
6
7
8
9
  <xml>
    <ToUserName><![CDATA[orrnVjsadf-FbumIsdafZiBUFTw]]></ToUserName>
    <FromUserName><![CDATA[gh_fsadf942sdf9]]></FromUserName>
    <CreateTime>1390889296</CreateTime>
    <MsgType><![CDATA[image]]></MsgType>
   <Image>
     <MediaId><![CDATA[media_id]]></MediaId>
   </Image>
  </xml>

图片,以及下面的视频、音频里的media_id,首先要通过微信的上传多媒体文件接口获得,详细的情况,以后会讲到

语音

1
2
3
4
5
6
7
8
9
  <xml>
    <ToUserName><![CDATA[orrnVjsadf-FbumIsdafZiBUFTw]]></ToUserName>
    <FromUserName><![CDATA[gh_fsadf942sdf9]]></FromUserName>
    <CreateTime>1390889296</CreateTime>
    <MsgType><![CDATA[voice]]></MsgType>
    <Voice>
      <MediaId><![CDATA[media_id]]></MediaId>
    </Voice>
  </xml>

~没啥可说的,和图片类似

视频

1
2
3
4
5
6
7
8
9
10
11
  <xml>
    <ToUserName><![CDATA[orrnVjsadf-FbumIsdafZiBUFTw]]></ToUserName>
    <FromUserName><![CDATA[gh_fsadf942sdf9]]></FromUserName>
    <CreateTime>1390889296</CreateTime>
    <MsgType><![CDATA[video]]></MsgType>
    <Video>
      <MediaId><![CDATA[media_id]]></MediaId>
      <Title><![CDATA[视频标题]]></Title>
      <Description><![CDATA[视频介绍]]></Description>
    </Video> 
  </xml>

音乐

1
2
3
4
5
6
7
8
9
10
11
12
13
  <xml>
    <ToUserName><![CDATA[orrnVjsadf-FbumIsdafZiBUFTw]]></ToUserName>
    <FromUserName><![CDATA[gh_fsadf942sdf9]]></FromUserName>
    <CreateTime>1390889296</CreateTime>
    <MsgType><![CDATA[video]]></MsgType>
    <Music>
      <Title><![CDATA[音乐标题]]></Title>
      <Description><![CDATA[音乐介绍]]></Description>
      <MusicUrl><![CDATA[音乐链接]]></MusicUrl>
      <HQMusicUrl><![CDATA[WIFI环境优先使用的高质量音乐链接]]></HQMusicUrl>
      <ThumbMediaId><![CDATA[media_id~缩略图的媒体id]]></ThumbMediaId>
    </Music> 
  </xml>

图文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<xml>
  <ToUserName><![CDATA[orrnVjsadf-FbumIsdafZiBUFTw]]></ToUserName>
  <FromUserName><![CDATA[gh_fsadf942sdf9]]></FromUserName>
  <CreateTime>1390889296</CreateTime>
  <MsgType><![CDATA[news]]></MsgType>
  <ArticleCount>5</ArticleCount>
  <Articles>
    <item>
      <Title><![CDATA[标题1]]></Title>
      <PicUrl><![CDATA[http://y1.ifengimg.com/2014/01/28/14023732.jpg]]></PicUrl>
      <Url><![CDATA[http://xxxx.xxx.com/index]]></Url>
    </item>
    <item>
      <Title><![CDATA[标题2]]></Title>
      <PicUrl><![CDATA[http://xxxx.xxx.com/xxx.png]]></PicUrl>
      <Url><![CDATA[http://xxxx.xxx.com/index]]></Url>
    </item>
    ......  
  </Articles>
</xml>

ArticleCount,是item子项的数量

图文的第一条,会以大图显示,推荐尺寸720*400,不同的尺寸在不同的手机上显示效果差别很大,可能左右也可能上下被遮住

除第一条外,其他的图文里的图,都只显示小icon,所以我们用的时候,统一用了一个向右的箭头

最后,来说一个不常用,但对于新手很重要的东西:网关的验证消息怎么回复

太简单了~~直接输出get参数里的echostr

————
转载请注明出处:http://www.jiangkl.com/2014/01/weixin_msg_2/

Hello World 微信开发

玩转微信公号开发(二)——消息的接受

当用户在公号内微信推给开发者服务器的是这样一个xml

1
2
3
4
5
6
7
8
  <xml>
    <ToUserName><![CDATA[gh_fsadfe942b39]]></ToUserName>
    <FromUserName><![CDATA[orrnsdfsdfLom-FsssD1wZiBUFTw]]></FromUserName>
    <CreateTime>1390809909</CreateTime>
    <MsgType><![CDATA[event]]></MsgType>
    <Event><![CDATA[subscribe]]></Event>
    <EventKey><![CDATA[]]></EventKey>
  </xml>

或者这样:

1
2
3
4
5
6
7
8
  <xml>
    <ToUserName><![CDATA[gh_fsadfe942b39]]></ToUserName>
    <FromUserName><![CDATA[orrnsdfsdfLom-FsssD1wZiBUFTw]]></FromUserName>
    <CreateTime>1390810725</CreateTime>
    <MsgType><![CDATA[text]]></MsgType>
    <Content><![CDATA[你好]]></Content>
    <MsgId>5973123479001063148</MsgId>
  </xml>

    最基本的是如下四个字段:

  • ToUserName,是公号的标示
  • FromUserName,是用户的openId,如果要针对特定用户做什么事,这个字段会很有用
  • MsgType,消息类型,比如event、text、location、image等
  • CreateTime

    除了两个UserName和MsgType,每一种MsgType,xml还会包含如下字段:

  • event
    1. Event,具体的事件类型
      EventKey,事件的具体信息
  • text
    1. Content,用户给公号发送的信息内容
      MsgId
  • location
    1. Location_X,纬度
      Location_Y,精度
      Scale,地图缩放
      Label,地点名称
      MsgId
  • image
    1. PicUrl,图片内容
      MsgId
      MediaId,媒体id,貌似可以拿这个图片再做别的用途
  • link,网页
    1. Title,标题
      Description,部分内容
      Url,页面弟子
      MsgId
    另外还有语音、视频等类型,以后用到的时候再补充~~

    常用的事件类型包括如下几个(MsgType为event时)

  • subscribe,新用户关注,当然,也可能是再次关注
  • unsubscribe,取消关注
  • validate_url,微信后台测试开发者网关,只在设置网管是才会有
  • CLICK,菜单点击

好的,今天就到这儿。。。

什么,你问怎么得到消息?

微信通过post将xml给开发者服务器,php里,通过$GLOBALS[“HTTP_RAW_POST_DATA”]接收~~~xml怎么解析?我是用的simplexml_load_string,不太好用,应该还有更好用的xml解析工具

转载请注明出处:http://www.jiangkl.com/2014/01/weixin_msg/
Hello World 微信开发

玩转微信公号开发(一)——使用“开发模式”

近半年都在做基于微信公众号的开发,节前几天工作不忙,把相关的(可以公开的)经验写到blog里给大家分享,也算自己的一个小总结

先来理清关于微信公号的几个概念:

订阅号与服务号:

订阅号是相对比较好申请,但是权限较低的公众号

服务号由订阅号升级得到,貌似现在要花钱才能升级~~

订阅号相对服务号的唯一的优势是:每天可以群发一条信息,而服务号每个月才能群发一条

服务号可以享有更多的高级接口权限,比如客服消息、定位、支付等

编辑模式与开发模式:

两种模式下,均可以在微信后台对用户做消息的回复、群发,管理粉丝群。他们的不同,主要在自动回复的能力上

编辑模式下,可以在微信后台设置各种自动回复,可以根据关键字设置回复~~但仅此而已,再复杂的回复模式(目前)就做不到了

开发模式下,可以将用户的消息转到公号后台所设置的服务器,然后有服务器根据各种消息类型和业务逻辑,以及具体的用户,来做出回复

编辑模式和开发模式,只能选一个

开发者的服务器配置:

包括一个服务器网关的url地址,和一个token

网关,即你的服务器地址,用来接受用户发给你公众号的各种消息;你要回复给用户的消息,即为这个请求的响应

token,一个用作标示的字符串,让服务器可以判断哪一个公众号的消息

转载请注明出处:http://www.jiangkl.com/2014/01/weixin_dev/

—————–over,今天先到这里,下次继续