wechatpy.client   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 137
Duplicated Lines 0 %

Test Coverage

Coverage 65.15%

Importance

Changes 0
Metric Value
eloc 85
dl 0
loc 137
rs 10
c 0
b 0
f 0
ccs 43
cts 66
cp 0.6515
wmc 14

8 Methods

Rating   Name   Duplication   Size   Complexity  
A WeChatComponentClient.fetch_access_token() 0 23 2
A WeChatClient.fetch_access_token() 0 13 1
A WeChatComponentClient.access_token_key() 0 3 1
A WeChatComponentClient.__init__() 0 17 5
A WeChatComponentClient.refresh_token_key() 0 3 1
A WeChatComponentClient.access_token() 0 7 2
A WeChatComponentClient.refresh_token() 0 3 1
A WeChatClient.__init__() 0 7 1
1
# -*- coding: utf-8 -*-
2 10
from __future__ import absolute_import, unicode_literals
3
4 10
import time
5
6 10
from wechatpy.client.base import BaseWeChatClient
7 10
from wechatpy.client import api
8
9
10 10
class WeChatClient(BaseWeChatClient):
11
12
    """
13
    微信 API 操作类
14
    通过这个类可以操作微信 API,发送主动消息、群发消息和创建自定义菜单等。
15
    """
16
17 10
    API_BASE_URL = 'https://api.weixin.qq.com/cgi-bin/'
18
19 10
    card = api.WeChatCard()
20 10
    customservice = api.WeChatCustomService()
21 10
    datacube = api.WeChatDataCube()
22 10
    device = api.WeChatDevice()
23 10
    group = api.WeChatGroup()
24 10
    invoice = api.WeChatInvoice()
25 10
    jsapi = api.WeChatJSAPI()
26 10
    material = api.WeChatMaterial()
27 10
    media = api.WeChatMedia()
28 10
    menu = api.WeChatMenu()
29 10
    merchant = api.WeChatMerchant()
30 10
    message = api.WeChatMessage()
31 10
    misc = api.WeChatMisc()
32 10
    poi = api.WeChatPoi()
33 10
    qrcode = api.WeChatQRCode()
34 10
    scan = api.WeChatScan()
35 10
    semantic = api.WeChatSemantic()
36 10
    shakearound = api.WeChatShakeAround()
37 10
    tag = api.WeChatTag()
38 10
    template = api.WeChatTemplate()
39 10
    user = api.WeChatUser()
40 10
    wifi = api.WeChatWiFi()
41 10
    wxa = api.WeChatWxa()
42 10
    marketing = api.WeChatMarketing()
43
    cloud = api.WeChatCloud()
44 10
45
    def __init__(self, appid, secret, access_token=None,
46 10
                 session=None, timeout=None, auto_retry=True):
47
        super(WeChatClient, self).__init__(
48
            appid, access_token, session, timeout, auto_retry
49 10
        )
50 10
        self.appid = appid
51
        self.secret = secret
52 10
53
    def fetch_access_token(self):
54
        """
55
        获取 access token
56
        详情请参考 http://mp.weixin.qq.com/wiki/index.php?title=通用接口文档
57
58
        :return: 返回的 JSON 数据包
59 10
        """
60
        return self._fetch_access_token(
61
            url='https://api.weixin.qq.com/cgi-bin/token',
62
            params={
63
                'grant_type': 'client_credential',
64
                'appid': self.appid,
65
                'secret': self.secret
66
            }
67
        )
68
69 10
70
class WeChatComponentClient(WeChatClient):
71
72
    """
73
    开放平台代公众号调用客户端
74
    """
75 10
76
    def __init__(self, appid, component, access_token=None,
77
                 refresh_token=None, session=None, timeout=None):
78
        # 未用到secret,所以这里没有
79
        super(WeChatComponentClient, self).__init__(
80
            appid, '', '', session, timeout
81
        )
82
        self.appid = appid
83
        self.component = component
84
        # 如果公众号是刚授权,外部还没有缓存access_token和refresh_token
85
        # 可以传入这两个值,session 会缓存起来。
86
        # 如果外部已经缓存,这里只需要传入 appid,component和session即可
87
        cache_access_token = self.session.get(self.access_token_key)
88
89
        if access_token and (not cache_access_token or cache_access_token != access_token):
90
            self.session.set(self.access_token_key, access_token, 7200)
91
        if refresh_token:
92
            self.session.set(self.refresh_token_key, refresh_token)
93 10
94
    @property
95
    def access_token_key(self):
96
        return '{0}_access_token'.format(self.appid)
97 10
98
    @property
99
    def refresh_token_key(self):
100
        return '{0}_refresh_token'.format(self.appid)
101 10
102
    @property
103
    def access_token(self):
104
        access_token = self.session.get(self.access_token_key)
105
        if not access_token:
106
            self.fetch_access_token()
107
            access_token = self.session.get(self.access_token_key)
108
        return access_token
109 10
110
    @property
111
    def refresh_token(self):
112
        return self.session.get(self.refresh_token_key)
113 10
114
    def fetch_access_token(self):
115
        """
116
        获取 access token
117
        详情请参考 https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list\
118
        &t=resource/res_list&verify=1&id=open1419318587&token=&lang=zh_CN
119
120
        这是内部刷新机制。请不要完全依赖!
121
        因为有可能在缓存期间没有对此公众号的操作,造成refresh_token失效。
122
123
        :return: 返回的 JSON 数据包
124
        """
125
        expires_in = 7200
126
        result = self.component.refresh_authorizer_token(
127
            self.appid, self.refresh_token)
128
        if 'expires_in' in result:
129
            expires_in = result['expires_in']
130
        self.session.set(
131
            self.access_token_key,
132
            result['authorizer_access_token'],
133
            expires_in
134
        )
135
        self.expires_at = int(time.time()) + expires_in
136
        return result
137