def test_string_field_to_xml(self): from wechatpy.fields import StringField name = "Content" value = "test" expected = "<{name}><![CDATA[{value}]]></{name}>".format(name=name, value=value) field = StringField(name) self.assertEqual(expected, field.to_xml(value))
class BaseMessage(metaclass=MessageMetaClass): """Base class for all messages and events""" type = "unknown" id = IntegerField("MsgId", 0) source = StringField("FromUserName") target = StringField("ToUserName") create_time = DateTimeField("CreateTime") time = IntegerField("CreateTime") def __init__(self, message): self._data = message def __repr__(self): return f"{self.__class__.__name__}({repr(self._data)})"
class UserScanProductEvent(BaseEvent): """ 打开商品主页事件 详情请参考 http://mp.weixin.qq.com/wiki/15/f4109a5e44b4bfbc7eb1337eb739f3e3.html """ event = 'user_scan_product' standard = StringField('KeyStandard') key = StringField('KeyStr') country = StringField('Country') province = StringField('Province') city = StringField('City') sex = IntegerField('Sex') scene = IntegerField('Scene')
class LocationMessage(BaseMessage): """ 地理位置消息 详情请参阅 http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html """ type = 'location' location_x = StringField('Location_X') location_y = StringField('Location_Y') scale = StringField('Scale') label = StringField('Label') @property def location(self): return self.location_x, self.location_y
class UserPayFromPayCell(BaseEvent): """ 卡券买单事件推送 详情请参阅 https://developers.weixin.qq.com/doc/offiaccount/Cards_and_Offer/Coupons_Vouchers_and_Cards_Event_Push_Messages.html#6 """ event = "user_pay_from_pay_cell" card_id = StringField("CardId") code = StringField("UserCardCode") trans_id = StringField("TransId") location_id = IntegerField("LocationId") fee = IntegerField("Fee") original_fee = IntegerField("OriginalFee")
class UserScanProductEvent(BaseEvent): """ 打开商品主页事件 详情请参考 https://mp.weixin.qq.com/wiki?id=mp1455872179 """ event = 'user_scan_product' standard = StringField('KeyStandard') key = StringField('KeyStr') country = StringField('Country') province = StringField('Province') city = StringField('City') sex = IntegerField('Sex') scene = IntegerField('Scene')
class LocationSelectEvent(BaseEvent): """ 弹出地理位置选择器的事件 详情请参阅 https://mp.weixin.qq.com/wiki?id=mp1421141016 """ event = 'location_select' key = StringField('EventKey') location_info = BaseField('SendLocationInfo', {}) @property def location_x(self): return self.location_info['Location_X'] @property def location_y(self): return self.location_info['Location_Y'] @property def location(self): return self.location_x, self.location_y @property def scale(self): return self.location_info['Scale'] @property def label(self): return self.location_info['Label'] @property def poiname(self): return self.location_info['Poiname']
class BaseMessage(metaclass=MessageMetaClass): """Base class for all messages and events""" type = 'unknown' id = IntegerField('MsgId', 0) source = StringField('FromUserName') target = StringField('ToUserName') create_time = DateTimeField('CreateTime') time = IntegerField('CreateTime') def __init__(self, message): self._data = message def __repr__(self): _repr = "{klass}({msg})".format(klass=self.__class__.__name__, msg=repr(self._data)) return _repr
class BaseComponentMessage(six.with_metaclass(MessageMetaClass)): """Base class for all component messages and events""" type = 'unknown' appid = StringField('AppId') time = IntegerField('CreateTime', 0) def __init__(self, message): self._data = message def __repr__(self): _repr = "{klass}({msg})".format(klass=self.__class__.__name__, msg=repr(self._data)) if six.PY2: return to_binary(_repr) else: return to_text(_repr) @property def create_time(self): """ 消息创建时间 ``datetime.datetime`` 类型 """ tz = timezone('Asia/Shanghai') created = datetime.fromtimestamp(self.time, tz) return created
class ComponentUnauthorizedMessage(BaseComponentMessage): """ 取消授权通知 """ type = "unauthorized" authorizer_appid = StringField("AuthorizerAppid")
class LocationMessage(BaseMessage): """ 地理位置消息 详情请参阅 https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html """ type = "location" location_x = StringField("Location_X") location_y = StringField("Location_Y") scale = StringField("Scale") label = StringField("Label") @property def location(self): return self.location_x, self.location_y
class WxaMediaCheckEvent(BaseEvent): """ 异步检测结果通知事件 详情请参考 https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/sec-check/security.mediaCheckAsync.html """ event = "wxa_media_check" is_risky = IntegerField("isrisky") # 检测结果,0:暂未检测到风险,1:风险 extra_info_json = StringField("extra_info_json") # 附加信息,默认为空 trace_id = StringField("trace_id") # 任务 id status_code = IntegerField("status_code") # 默认为:0,4294966288(-1008)为链接无法下载 @property def is_valid(self): return self.is_risky == 0 and self.status_code == 0
class LocationSelectEvent(BaseEvent): """ 弹出地理位置选择器的事件 详情请参阅 http://mp.weixin.qq.com/wiki/9/981d772286d10d153a3dc4286c1ee5b5.html """ event = 'location_select' key = StringField('EventKey') location_info = BaseField('SendLocationInfo', {}) @property def location_x(self): return self.location_info['Location_X'] @property def location_y(self): return self.location_info['Location_Y'] @property def location(self): return self.location_x, self.location_y @property def scale(self): return self.location_info['Scale'] @property def label(self): return self.location_info['Label'] @property def poiname(self): return self.location_info['Poiname']
class LocationSelectEvent(BaseEvent): """ 弹出地理位置选择器的事件 详情请参阅 https://developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Custom_Menu_Push_Events.html """ event = "location_select" key = StringField("EventKey") location_info = BaseField("SendLocationInfo", {}) @property def location_x(self): return self.location_info["Location_X"] @property def location_y(self): return self.location_info["Location_Y"] @property def location(self): return self.location_x, self.location_y @property def scale(self): return self.location_info["Scale"] @property def label(self): return self.location_info["Label"] @property def poiname(self): return self.location_info["Poiname"]
class ComponentVerifyTicketMessage(BaseComponentMessage): """ component_verify_ticket协议 """ type = "component_verify_ticket" verify_ticket = StringField("ComponentVerifyTicket")
class UserScanProductEvent(BaseEvent): """ 打开商品主页事件 详情请参考 https://mp.weixin.qq.com/wiki?id=mp1455872179 """ event = "user_scan_product" standard = StringField("KeyStandard") key = StringField("KeyStr") country = StringField("Country") province = StringField("Province") city = StringField("City") sex = IntegerField("Sex") scene = IntegerField("Scene")
class TextReply(BaseReply): """ 文本回复 详情请参阅 http://mp.weixin.qq.com/wiki/9/2c15b20a16019ae613d413e30cac8ea1.html """ type = 'text' content = StringField('Content')
class ClickEvent(BaseEvent): """ 点击菜单拉取消息事件 详情请参阅 http://mp.weixin.qq.com/wiki/2/5baf56ce4947d35003b86a9805634b1e.html """ event = 'click' key = StringField('EventKey')
class ViewEvent(BaseEvent): """ 点击菜单跳转链接事件 详情请参阅 http://mp.weixin.qq.com/wiki/2/5baf56ce4947d35003b86a9805634b1e.html """ event = 'view' url = StringField('EventKey')
class BaseReply(six.with_metaclass(MessageMetaClass)): """Base class for all replies""" source = StringField('FromUserName') target = StringField('ToUserName') time = IntegerField('CreateTime', time.time()) type = 'unknown' def __init__(self, **kwargs): self._data = {} message = kwargs.pop('message', None) if message and isinstance(message, BaseMessage): if 'source' not in kwargs: kwargs['source'] = message.target if 'target' not in kwargs: kwargs['target'] = message.source if hasattr(message, 'agent') and 'agent' not in kwargs: kwargs['agent'] = message.agent if 'time' not in kwargs: kwargs['time'] = time.time() for name, value in kwargs.items(): field = self._fields.get(name) if field: self._data[field.name] = value else: setattr(self, name, value) def render(self): """Render reply from Python object to XML string""" tpl = '<xml>\n{data}\n</xml>' nodes = [] msg_type = '<MsgType><![CDATA[{msg_type}]]></MsgType>'.format( msg_type=self.type ) nodes.append(msg_type) for name, field in self._fields.items(): value = getattr(self, name, field.default) node_xml = field.to_xml(value) nodes.append(node_xml) data = '\n'.join(nodes) return tpl.format(data=data) def __str__(self): if six.PY2: return to_binary(self.render()) else: return to_text(self.render())
class TextMessage(BaseMessage): """ 文本消息 详情请参阅 http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html """ type = 'text' content = StringField('Content')
class CardPassCheckEvent(BaseEvent): """ 卡券审核事件推送 https://developers.weixin.qq.com/doc/offiaccount/Cards_and_Offer/Coupons_Vouchers_and_Cards_Event_Push_Messages.html#1 """ event = 'card_pass_check' card_id = StringField('CardId')
class UserInfoModifiedEvent(BaseEvent): """ 授权用户资料变更 详情请参考 公众号:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/authorization_change.html 移动应用:https://developers.weixin.qq.com/doc/oplatform/Mobile_App/WeChat_Login/authorization_change.html 网页应用:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/authorization_change.html 小程序:https://developers.weixin.qq.com/miniprogram/dev/framework/security.html#授权用户资料变更 """ event = 'user_info_modified' open_id = StringField('OpenID') # 撤回或变更资料的用户 OpenID app_id = StringField('AppID') # 应用的 AppID revoke_info = StringField('RevokeInfo') # 用户撤回的授权信息 plugin_id = StringField('PluginID') # 插件场景用户撤回,插件的 AppID open_pid = StringField('OpenPID') # 插件场景用户撤回,撤回用户的 OpenPID
class UserEnterTempSessionEvent(BaseEvent): """ 小程序用户进入客服消息 详情请参阅 https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/customer-message/receive.html """ event = 'user_enter_tempsession' session_from = StringField('SessionFrom')
class TemplateSendJobFinishEvent(BaseEvent): """ 模板消息任务完成事件 详情请参阅 http://mp.weixin.qq.com/wiki/17/304c1885ea66dbedf7dc170d84999a9d.html """ event = 'templatesendjobfinish' status = StringField('Status')
class SubscribeEvent(BaseEvent): """ 用户关注事件 详情请参阅 https://mp.weixin.qq.com/wiki?id=mp1421140454 """ event = 'subscribe' key = StringField('EventKey', '')
class TextReply(BaseReply): """ 文本回复 详情请参阅 https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Passive_user_reply_message.html """ type = "text" content = StringField("Content")
class ViewEvent(BaseEvent): """ 点击菜单跳转链接事件 详情请参阅 https://mp.weixin.qq.com/wiki?id=mp1421140454 """ event = 'view' url = StringField('EventKey')
class ClickEvent(BaseEvent): """ 点击菜单拉取消息事件 详情请参阅 https://mp.weixin.qq.com/wiki?id=mp1421140454 """ event = 'click' key = StringField('EventKey')
class SubscribeEvent(BaseEvent): """ 用户关注事件 详情请参阅 http://mp.weixin.qq.com/wiki/2/5baf56ce4947d35003b86a9805634b1e.html """ event = 'subscribe' key = StringField('EventKey', '')
class TextMessage(BaseMessage): """ 文本消息 详情请参阅 https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html """ type = "text" content = StringField("Content")