kk Blog —— 通用基础


date [-d @int|str] [+%s|"+%F %T"]
netstat -ltunp
sar -n DEV 1

微信公众号获取OpenId(未授权)(需要关注公众号)

https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html

https://blog.csdn.net/HanKin_/article/details/79010789

openId是微信对于用户的唯一辨识,只要有用户关注你的公众号,微信会通过公众号和用户微信号通过一种算法生成一种唯一标识码

1.在公众号后台设置回调的域名(大多情况下是你的项目)

开发-接口权限-网页账号-用户授权获取用户基础信息中修改

2.在页面上访问下面的网址

1
https://open.weixin.qq.com/connect/oauth2/authorize?appid=*******&redirect_uri=你回调的地址&response_type=code&scope=snsapi_base&state=1#wechat_redirect

上面的会返回到你回调的地址?code=xxxxxxxxx

也就是说它会返回到你回调的地址并且带上code参数,一般情况下,回调的地址设置为后端的action即可,然后就可以获取到code了,当你获取到code,已经成功了一大半。

3.然后在后端访问下面的网址

1
https://api.weixin.qq.com/sns/oauth2/access_token?appid=***&secret=***&code=***&grant_type=authorization_code

code的参数用刚刚返回的code值。

4.上面网页将会返回json,其中openId就在其中。

至此,openId就获取到了,但是要注意:此处只获取到了openId,也就是不需要用户授权的,要获取用户其它的信息请参考接口文档。还有就是每次获取openId请重新获取code,code值不要重复使用,防止出错。

在微信页面上我是把获取到的openId保存在cookie中的,这样就可以防止openId的重复获取,我只在用户第一次进入或者cookie中的openId失效的时候进行再次获取的。


code

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
<?php
class Wxmsg extends CI_Controller {
	function __construct()
	{
		parent::__construct();
		$this->load->model('Follow_model');
		$this->load->helper('url');
		$this->load->helper('xml');
	}

	function index($check = 1)
	{
		$echostr = $this->input->get('echostr');
		if (!empty($echostr)) {
			echo $echostr;
			return;
		}

		$token = "hello";

		# step 1: get args
		$slug = array('signature', 'timestamp', 'nonce', 'openid');
		foreach ($slug as $key) {
			$args[$key] = $this->input->get($key);
			if ($check && empty($args[$key]))
				die($key.' 不能为空');
		}

		# step 2: signature check
		$lists = array($args['timestamp'], $args['nonce'], $token);
		sort($lists, SORT_STRING);
		$hashcode = sha1(implode('', $lists));
		if ($check && $hashcode != $args['signature'])
			die('signature 校验错误');

		# step 3: webdata decode
		$webdata = $this->input->raw_input_stream;
		$xml = simplexml_load_string($webdata);
		foreach ($xml->children() as $child) {
			$arr[$child->getName()] = trim((string)$child);
		}

		if (empty($arr['FromUserName']) || empty($arr['ToUserName']))
			die('FromUserName、ToUserName 不能为空');

		if (empty($arr['MsgType']))
			die('MsgType 不能为空');

		if ($arr['MsgType'] == 'text') {
			if (empty($arr['CreateTime']) || empty($arr['Content']) || empty($arr['MsgId']))
				die('CreateTime、Content、MsgId 不能为空');

			# step 4.1 text msg
			$Content = self::msg_text($arr);

		} elseif ($arr['MsgType'] == 'event') {
			if (empty($arr['Event']))
				die('Event 不能为空');

			# step 4.2 event msg
			$Content = self::msg_event($arr);

		} else {
			die('不处理事件:'.$arr['MsgType']);
		}

		self::reply_msg($arr, $Content);
	}

	function reply_msg($arr, $Content)
	{
		$FromUserName = $arr['FromUserName'];
		$ToUserName = $arr['ToUserName'];
		$CreateTime = time();
		$reply =
<<<XML
	<xml>
		<ToUserName><![CDATA[$FromUserName]]></ToUserName>
		<FromUserName><![CDATA[$ToUserName]]></FromUserName>
		<CreateTime>$CreateTime</CreateTime>
		<MsgType><![CDATA[text]]></MsgType>
		<Content><![CDATA[$Content]]></Content>
	</xml>
XML;
		$reply_xml = new SimpleXMLElement($reply);
		echo $reply_xml->asXML();
	}

	function msg_text($arr)
	{
		$FromUserName = $arr['FromUserName'];
		$key = $arr['Content'];

		$Content = '萌萌嗒';
		return $Content;
	}

	function msg_event($arr)
	{
		$event = $arr['Event'];
		if ($event == 'subscribe') {
			$this->Follow_model->change($arr['FromUserName'], $arr['ToUserName'], 1);
			return "功能添加中\n敬请等待\n";
			#return '输入姓名或电话查询单号,输入单号查询物流信息';
		} elseif ($event == 'unsubscribe') {
			$this->Follow_model->change($arr['FromUserName'], $arr['ToUserName'], 0);
		}
		return '';
	}

	function test()
	{
		$openid = $this->input->ip_address();

		$openid = $this->input->cookie("openid");
		if (empty($openid)) {
			$appid = appId;
			$redirect_uri = "http://".HOST.ROOT."/wxmsg/openid";
			$URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=$appid&redirect_uri=$redirect_uri&response_type=code&scope=snsapi_base&state=1#wechat_redirect";
			redirect($URL);
		}

		echo "test";
	}

	function openid()
	{
		$code = $this->input->get('code');
		if (empty($code)) {
			die('无法获取code');
		}
		//echo $code;
		#$fp = fopen('/tmp/a.txt', 'w');
		#fwrite($fp, $code);

		$appid = appId;
		$secret = appSecret;
		$URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=$appid&secret=$secret&code=$code&grant_type=authorization_code";

		$furl = fopen($URL, 'r') or exit('Open url faild!');
		$res = fgets($furl);
		fclose($furl);

		$res = json_decode($res, True);

//        var_dump($res);
//        echo $res['openid'];

		if (empty($res['openid'])) {
			die('无法获取openid');
		}
		$this->input->set_cookie('openid', $res['openid'], 86400 * 7);

		$URL = ROOT."/wxmsg/test";
		redirect($URL);
	}
}

微信公众平台获取网页授权(测试号)

https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html

https://blog.csdn.net/luopotaotao/article/details/50611317

1.登陆微信公众号后台,左下角找到

2.进入之后,会看到测试号的一些基本信息,用你的微信号扫描二维码关注测试号

3.网页账号权限处,右侧点击修改,此处填入你的网页域名

确认之后,后台配置就完成了,此时,再按照微信开发者文档中所写的流程便可正确获得授权,跳转到你的网页了.

后台获取到code,向微信服务器交换到openId,可以将该openId放到当前request的session中,此时用户在你开发的页面上的操作,都可以用session中的openId来确定用户了

微信公众号自定义菜单

https://developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Creating_Custom-Defined_Menu.html

basic.py

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
# -*- coding: utf-8 -*-
# filename: basic.py
import urllib
import time
import json
class Basic:
	def __init__(self):
		self.__accessToken = ''
		self.__leftTime = 0
	def __real_get_access_token(self):
		appId = ""    # TODO
		appSecret = ""    # TODO
		postUrl = ("https://api.weixin.qq.com/cgi-bin/token?grant_type="
			   "client_credential&appid=%s&secret=%s" % (appId, appSecret))
		urlResp = urllib.urlopen(postUrl)
		urlResp = json.loads(urlResp.read())
		self.__accessToken = urlResp['access_token']
		self.__leftTime = urlResp['expires_in']
	def get_access_token(self):
		if self.__leftTime < 10:
			self.__real_get_access_token()
		return self.__accessToken
	def run(self):
		while(True):
			if self.__leftTime > 10:
				time.sleep(2)
				self.__leftTime -= 2
			else:
				self.__real_get_access_token()

menu.py

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# -*- coding: utf-8 -*-
# filename: menu.py
import urllib
from basic import Basic

class Menu(object):
	def __init__(self):
		pass
	def create(self, postData, accessToken):
		postUrl = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=%s" % accessToken
		if isinstance(postData, unicode):
			postData = postData.encode('utf-8')
		urlResp = urllib.urlopen(url=postUrl, data=postData)
		print urlResp.read()

	def query(self, accessToken):
		postUrl = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=%s" % accessToken
		urlResp = urllib.urlopen(url=postUrl)
		print urlResp.read()

	def delete(self, accessToken):
		postUrl = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=%s" % accessToken
		urlResp = urllib.urlopen(url=postUrl)
		print urlResp.read()

	#获取自定义菜单配置接口
	def get_current_selfmenu_info(self, accessToken):
		postUrl = "https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=%s" % accessToken
		urlResp = urllib.urlopen(url=postUrl)
		print urlResp.read()

if __name__ == '__main__':
	myMenu = Menu()
	appid = ""    # TODO
	uri = ""  # TODO exp: http://www.abcxyz.xyz/ci/wx/openid
	postJson = """
	{
		"button":
		[
			{
		"type": "view",
		"name": "openid",
		"url": "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_base&state=1#wechat_redirect"
			},
			{
				"type": "view",
				"name": "测试",
				"url": "http://www.abcxyzkk.xyz/rs/wxmsg/test"
			}
		  ]
	}
	""" % (appid, uri)
	accessToken = Basic().get_access_token()
	#myMenu.delete(accessToken)
	myMenu.create(postJson, accessToken)