def update_page(self, page_id, title, description, icon_url, page_url, comment=None): """ 编辑页面信息 详情请参考 http://mp.weixin.qq.com/wiki/5/6626199ea8757c752046d8e46cf13251.html :param page_id: 摇周边页面唯一ID :param title: 在摇一摇页面展示的主标题,不超过6个字 :param description: 在摇一摇页面展示的副标题,不超过7个字 :param icon_url: 在摇一摇页面展示的图片。图片需先上传至微信侧服务器, 用“素材管理-上传图片素材”接口上传图片,返回的图片URL再配置在此处 :param page_url: 跳转链接 :param comment: 可选,页面的备注信息,不超过15个字 :return: 页面信息 """ data = optionaldict() data['page_id'] = page_id data['title'] = title data['description'] = description data['icon_url'] = icon_url data['page_url'] = page_url data['comment'] = comment res = self._post('shakearound/page/update', data=data, result_processor=lambda x: x['data']) return res
def create(self, user_id, name, department=None, position=None, mobile=None, gender=0, tel=None, email=None, weixin_id=None, extattr=None): """ 创建成员 详情请参考 http://qydev.weixin.qq.com/wiki/index.php?title=管理成员 """ user_data = optionaldict() user_data['userid'] = user_id user_data['name'] = name user_data['gender'] = gender user_data['department'] = department user_data['position'] = position user_data['mobile'] = mobile user_data['tel'] = tel user_data['email'] = email user_data['weixinid'] = weixin_id user_data['extattr'] = extattr return self._post('client/create', data=user_data)
def search_device(self, identifiers=None, apply_id=None, begin=0, count=10): """ 查询设备列表 详情请参考 http://mp.weixin.qq.com/wiki/15/b9e012f917e3484b7ed02771156411f3.html :param identifiers: 设备 ID 信息列表 :param apply_id: 批次ID,申请设备ID超出500个时所返回批次ID :param begin: 设备列表的起始索引值 :param count: 待查询的设备个数 :return: 设备列表 """ data = optionaldict() data['begin'] = begin data['count'] = count data['apply_id'] = apply_id if identifiers: data['device_identifiers'] = identifiers res = self._post('shakearound/device/search', data=data, result_processor=lambda x: x['data']) return res
def set(self, agent_id, name=None, description=None, redirect_domain=None, logo_media_id=None, report_location_flag=0, is_report_user=True, is_report_enter=True): """ 设置企业号应用 详情请参考 http://qydev.weixin.qq.com/wiki/index.php?title=设置企业号应用 :param agent_id: 企业应用的 id :param name: 企业应用名称 :param description: 企业应用详情 :param redirect_domain: 企业应用可信域名 :param logo_media_id: 企业应用头像的mediaid,通过多媒体接口上传图片获得mediaid :param report_location_flag: 企业应用是否打开地理位置上报 0:不上报;1:进入会话上报;2:持续上报 :param is_report_user: 是否接收用户变更通知 :param is_report_enter: 是否上报用户进入应用事件 :return: 返回的 JSON 数据包 """ agent_data = optionaldict() agent_data['agentid'] = agent_id agent_data['name'] = name agent_data['description'] = description agent_data['redirect_domain'] = redirect_domain agent_data['logo_mediaid'] = logo_media_id agent_data['report_location_flag'] = report_location_flag agent_data['isreportuser'] = 1 if is_report_user else 0 agent_data['isreportenter'] = 1 if is_report_enter else 0 return self._post('agent/set', data=agent_data)
def bind_device_location(self, poi_id, device_id=None, uuid=None, major=None, minor=None): """ 配置设备与门店的关联关系 详情请参考 http://mp.weixin.qq.com/wiki/15/b9e012f917e3484b7ed02771156411f3.html :param poi_id: 待关联的门店ID :param device_id: 设备编号,若填了UUID、major、minor,则可不填设备编号,若二者都填,则以设备编号为优先 :param uuid: UUID :param major: major :param minor: minor :return: 返回的 JSON 数据包 """ data = optionaldict() data['poi_id'] = poi_id data['device_identifier'] = { 'device_id': device_id, 'uuid': uuid, 'major': major, 'minor': minor } return self._post('shakearound/device/bindlocation', data=data)
def _request(self, method, url_or_endpoint, **kwargs): if not url_or_endpoint.startswith(('http://', 'https://')): api_base_url = kwargs.pop('api_base_url', self.API_BASE_URL) url = '{base}{endpoint}'.format(base=api_base_url, endpoint=url_or_endpoint) else: url = url_or_endpoint if isinstance(kwargs.get('data', ''), dict): data = optionaldict(kwargs['data']) if 'mchid' not in data: # F**k Tencent data.setdefault('mch_id', self.mch_id) data.setdefault('sub_mch_id', self.sub_mch_id) data.setdefault('nonce_str', random_string(32)) sign = calculate_signature(data, self.api_key) body = dict_to_xml(data, sign) body = body.encode('utf-8') kwargs['data'] = body # 商户证书 if self.mch_cert and self.mch_key: kwargs['cert'] = (self.mch_cert, self.mch_key) res = requests.request(method=method, url=url, **kwargs) try: res.raise_for_status() except requests.RequestException as reqe: raise WeChatPayException(return_code=None, client=self, request=reqe.request, response=reqe.response) return self._handle_result(res)
def update(self, chat_id, op_user, name=None, owner=None, add_user_list=None, del_user_list=None): """ 修改会话 详情请参考 http://qydev.weixin.qq.com/wiki/index.php?title=企业会话接口说明 :param chat_id: 会话 ID :param op_user: 操作人 userid :param name: 会话标题 :param owner: 管理员userid,必须是该会话userlist的成员之一 :param add_user_list: 会话新增成员列表,成员用userid来标识 :param del_user_list: 会话退出成员列表,成员用userid来标识 :return: 返回的 JSON 数据包 """ data = optionaldict( chatid=chat_id, op_user=op_user, name=name, owner=owner, add_user_list=add_user_list, del_user_list=del_user_list, ) return self._post('chat/update', data=data)
def update_device(self, device_id=None, uuid=None, major=None, minor=None, comment=None): """ 更新设备信息 详情请参考 http://mp.weixin.qq.com/wiki/15/b9e012f917e3484b7ed02771156411f3.html :param device_id: 设备编号,若填了UUID、major、minor,则可不填设备编号,若二者都填,则以设备编号为优先 :param uuid: UUID :param major: major :param minor: minor :param comment: 设备的备注信息,不超过15个汉字或30个英文字母。 :return: 返回的 JSON 数据包 """ data = optionaldict() data['comment'] = comment data['device_identifier'] = { 'device_id': device_id, 'uuid': uuid, 'major': major, 'minor': minor } return self._post('shakearound/device/update', data=data)
def get_by_filter(self, status=None, begin_time=None, end_time=None): filter_dict = optionaldict(status=status, begintime=begin_time, endtime=end_time) res = self._post('merchant/order/getbyfilter', data=dict(filter_dict), result_processor=lambda x: x['order_list']) return res
def search(self, query, category, uid=None, latitude=None, longitude=None, city=None, region=None): """ 发送语义理解请求 详情请参考 http://mp.weixin.qq.com/wiki/0/0ce78b3c9524811fee34aba3e33f3448.html :param query: 输入文本串 :param category: 需要使用的服务类型,多个可传入列表 :param uid: 可选,用户唯一id(非开发者id),用户区分公众号下的不同用户(建议填入用户openid) :param latitude: 可选,纬度坐标,与经度同时传入;与城市二选一传入 :param longitude: 可选,经度坐标,与纬度同时传入;与城市二选一传入 :param city: 可选,城市名称,与经纬度二选一传入 :param region: 可选,区域名称,在城市存在的情况下可省;与经纬度二选一传入 :return: 返回的 JSON 数据包 使用示例:: from wechatpy import WeChatClient client = WeChatClient('appid', 'secret') res = client.semantic.search( '查一下明天从北京到上海的南航机票', 'flight,hotel', city='北京' ) """ if isinstance(category, (tuple, list)): category = ','.join(category) data = optionaldict() data['query'] = query data['category'] = category data['uid'] = uid data['latitude'] = latitude data['longitude'] = longitude data['city'] = city data['region'] = region data['appid'] = self._client.appid return self._post( url='https://api.weixin.qq.com/semantic/semproxy/search', data=data)
def create(self, name, parent_id=1, order=None, id=None): """ 创建部门 详情请参考 http://qydev.weixin.qq.com/wiki/index.php?title=管理部门 :param name: 部门名称,长度限制为 1~64 个字符 :param parent_id: 父亲部门 id ,根部门 id 为 1 :return: 返回的 JSON 数据包 """ department_data = optionaldict() department_data['name'] = name department_data['parentid'] = parent_id department_data['order'] = order department_data['id'] = id return self._post('department/create', data=dict(department_data))
def convert_to_openid(self, user_id, agent_id=None): """ user_id 转成 openid 详情请参考 http://qydev.weixin.qq.com/wiki/index.php?title=Userid%E4%B8%8Eopenid%E4%BA%92%E6%8D%A2%E6%8E%A5%E5%8F%A3 :param user_id: 企业号内的成员 ID :param agent_id: 可选,需要发送红包的应用ID,若只是使用微信支付和企业转账,则无需该参数 :return: 返回的 JSON 数据包 """ data = optionaldict() data['userid'] = user_id data['agentid'] = agent_id return self._post('client/convert_to_openid', data=data)
def update(self, id, name=None, parent_id=None, order=None): """ 更新部门 详情请参考 http://qydev.weixin.qq.com/wiki/index.php?title=管理部门 :param id: 部门 id :param name: 部门名称 :param parent_id: 父亲部门 id :param order: 在父部门中的次序,从 1 开始,数字越大排序越靠后 :return: 返回的 JSON 数据包 """ department_data = optionaldict() department_data['id'] = id department_data['name'] = name department_data['parentid'] = parent_id department_data['order'] = order return self._post('department/update', data=dict(department_data))
def set_test_whitelist(self, userids=None, usernames=None): """ 设置测试人员白名单 注意:每次设置均被视为一次重置,而非增量设置。openid、微信号合计最多设置10个。 详情请参考 http://mp.weixin.qq.com/wiki/15/1007691d0f1c10a0588c6517f12ed70f.html :param userids: 可选,测试人员的 openid 列表 :param usernames: 可选,测试人员的微信号列表 :return: 返回的 JSON 数据包 """ data = optionaldict( openid=userids, username=usernames ) return self._post('testwhitelist/set', data=data)
def send_video(self, agent_id, user_ids, media_id, title=None, description=None, party_ids='', tag_ids='', safe=0): video_data = optionaldict() video_data['media_id'] = media_id video_data['title'] = title video_data['description'] = description return self._send_message( agent_id, user_ids, party_ids, tag_ids, msg={ 'msgtype': 'video', 'video': dict(video_data), 'safe': safe } )
def _request(self, method, url_or_endpoint, **kwargs): http_client = AsyncHTTPClient() if not url_or_endpoint.startswith(('http://', 'https://')): api_base_url = kwargs.pop('api_base_url', self.API_BASE_URL) url = '{base}{endpoint}'.format(base=api_base_url, endpoint=url_or_endpoint) else: url = url_or_endpoint headers = {} params = kwargs.pop('params', {}) params = urlencode(dict((k, to_binary(v)) for k, v in params.items())) url = '{0}?{1}'.format(url, params) data = kwargs.get('data') if isinstance(data, dict): data = optionaldict(data) if 'mchid' not in data: # F**k Tencent data.setdefault('mch_id', self.mch_id) data.setdefault('sub_mch_id', self.sub_mch_id) data.setdefault('nonce_str', random_string(32)) sign = calculate_signature(data, self.api_key) body = dict_to_xml(data, sign) body = body.encode('utf-8') else: body = data req = HTTPRequest(url=url, method=method.upper(), headers=headers, body=body) res = yield http_client.fetch(req) if res.error is not None: raise WeChatClientException(errcode=None, errmsg=None, client=self, request=req, response=res) result = self._handle_result(res) raise Return(result)
def list_devices(self, shop_id=None, page_index=1, page_size=20): """ 查询设备 详情请参考 http://mp.weixin.qq.com/wiki/10/6232005bdc497f7cf8e19d4e843c70d2.html :param shop_id: 可选,门店 ID :param page_index: 可选,分页下标,默认从1开始 :param page_size: 可选,每页的个数,默认20个,最大20个 :return: 返回的 JSON 数据包 """ data = optionaldict(shop_id=shop_id, pageindex=page_index, pagesize=page_size) res = self._post('device/list', data=data, result_processor=lambda x: x['data']) return res
def close_session(self, openid, account, text=None): """ 多客服关闭会话 详情请参考 http://mp.weixin.qq.com/wiki/2/6c20f3e323bdf5986cfcb33cbd3b829a.html :param openid: 客户 openid :param account: 完整客服账号 :param text: 附加信息,可选 :return: 返回的 JSON 数据包 """ data = optionaldict( openid=openid, kf_account=account, text=text ) return self._post( 'https://api.weixin.qq.com/customservice/kfsession/close', data=data )
def list_product(self, offset=0, limit=10, status=None, key=None): """ 批量查询商品信息 详情请参考 http://mp.weixin.qq.com/wiki/15/7fa787701295b884410b5163e13313af.html :param offset: 可选,批量查询的起始位置,从 0 开始,包含该起始位置 :param limit: 可选,批量查询的数量,默认为 10 :param status: 可选,支持按状态拉取。on为发布状态,off为未发布状态, check为审核中状态,reject为审核未通过状态,all为所有状态 :param key: 支持按部分编码内容拉取。填写该参数后,可将编码内容中包含所传参数的商品信息拉出 :return: 返回的 JSON 数据包 """ data = optionaldict( offset=offset, limit=limit, status=status, keystr=key, ) return self._post('product/getlist', data=data)
def apply_device_id(self, quantity, reason, poi_id=None, comment=None): """ 申请设备ID 详情请参考 http://mp.weixin.qq.com/wiki/15/b9e012f917e3484b7ed02771156411f3.html :param quantity: 申请的设备ID的数量,单次新增设备超过500个,需走人工审核流程 :param reason: 申请理由,不超过100个字 :param poi_id: 可选,设备关联的门店ID :param comment: 可选,备注,不超过15个汉字或30个英文字母 :return: 申请的设备信息 """ data = optionaldict() data['quantity'] = quantity data['apply_reason'] = reason data['poi_id'] = poi_id data['comment'] = comment res = self._post('shakearound/device/applyid', data=data, result_processor=lambda x: x['data']) return res
def invite_user(self, url, token, encoding_aes_key, user_ids=None, party_ids=None, tag_ids=None, invite_tips=None): """ 邀请成员关注 详情请参考 http://qydev.weixin.qq.com/wiki/index.php?title=异步任务接口 :param url: 企业应用接收企业号推送请求的访问协议和地址,支持http或https协议 :param token: 用于生成签名 :param encoding_aes_key: 用于消息体的加密,是AES密钥的Base64编码 :param user_ids: 可选,成员ID列表,多个接收者用‘|’分隔,最多支持1000个。 :param party_ids: 可选,部门ID列表,多个接收者用‘|’分隔,最多支持100个。 :param tag_ids: 可选,标签ID列表,多个接收者用‘|’分隔。 :param invite_tips: 可选,推送到微信上的提示语 :return: 返回的 JSON 数据包 """ data = optionaldict() data['callback'] = { 'url': url, 'token': token, 'encodingaeskey': encoding_aes_key } if isinstance(user_ids, (tuple, list)): user_ids = '|'.join(map(to_text, user_ids)) if isinstance(party_ids, (tuple, list)): party_ids = '|'.join(map(to_text, party_ids)) if isinstance(tag_ids, (tuple, list)): tag_ids = '|'.join(map(to_text, tag_ids)) data['touser'] = user_ids data['toparty'] = party_ids data['totag'] = tag_ids data['invite_tips'] = invite_tips return self._post('batch/inviteuser', data=data)