1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > 微信公众号第三方平台开发PYTHON教程 PART 1

微信公众号第三方平台开发PYTHON教程 PART 1

时间:2018-08-09 22:22:15

相关推荐

微信公众号第三方平台开发PYTHON教程 PART 1

微信是一个时代的标志,虽然它现在不温不火,但我们大部分人离不开它。最近我帮朋友的公司接入了微信公众号第三方,使其成为第三方开发者。

网上公众号的开发教程,描述很多,但第三方的就几乎没有,可能是商业部分,大家都保密吧。我是无所谓,因为这东西不难,用心就可以搞定,我把它开源,放到github上。

github地址:cppfun@wechat-open-third-party-dev

第一部分我们先要介绍几个参数,我直接截图,然后进行说明:

https://open.

这里面的参数: # 登录授权的发起页域名:

# 授权事件接收URL: /auth

# 公众号消息与事件接收URL: /receive/$APPID$

这三个参数你需要在新建应用时就进行确认,但不用截图记下,提交后会有记录,实时可以查看修改。

接下来我们讲讲授权流程的技术实现。为了避免您的困惑,我准备采用小而精的方式,一步步来用代码实现。

在开始之前,我先说说微信第三方开发平台的思路。我们先回到公众号开发,公众号开发是利用公众号的api来控制粉丝即用户;

微信第三方开发平台是利用更高层的公众号api来控制各个授权的公众号(我个人觉得这种类比思维很重要,有了这种思维来开发微信第三方开发平台很简单)。

https://open.上面的文档说实话,很一般。

我们进入后端第一环节,接收腾讯微信服务器推送component_verify_ticket。这里和python公众号开发一样,我们将其保存到json文件里,其实到数据库里面也可以,但我觉得没必要,因为它是唯一的。

首先我们需要个回调验证类:

classWxOpenCallback:

def __init__ ( self ):

self. token = token

defcheck_signature ( self ,pams ):

if not self. token:

returnHttpResponse ( 'TOKEN is not defined!' )

msg_signature =pams. get ( 'msg_signature' , '' )

timestamp =pams. get ( 'timestamp' , '' )

nonce =pams. get ( 'nonce' , '' )

tmparr = [ self. token ,timestamp ,nonce ]

tmparr. sort ( )

string = ''. join (tmparr )

string =hashlib. sha1 ( string ). hexdigest ( )

# print signature

# print string

returnmsg_signature == string

这里面的token就是上面截图当中的token,其余的都是微信服务器post过来的参数。

接着我们获取component_verify_ticket,这里微信为了安全,传递过来的是加密的xml,我们需要解密,解密的python类微信已经提供给我们。我这里不再累述。

wxOpenCallBack =WxOpenCallback ( )

is_valid =wxOpenCallBack. check_signature (request. GET )

ifis_valid:

# get the url params

msg_signature =request. GET. get ( 'msg_signature' , '' )

timestamp =request. GET. get ( 'timestamp' , '' )

nonce =request. GET. get ( 'nonce' , '' )

# get the xml

encrypt_xml =smart_str (request. body )

decryp_xml =WxUtils. get_decrypt_xml (encrypt_xml =encrypt_xml ,

msg_signature =msg_signature ,

timestamp =timestamp ,

nonce =nonce )

if len (decryp_xml ) != 0:

ticket_xml =etree. fromstring (decryp_xml )

infoType =ticket_xml. find ( 'InfoType' ). text

ifinfoType == 'component_verify_ticket':

data = {'ComponentVerifyTicket': ticket_xml. find ( 'ComponentVerifyTicket' ). text }

json_file = open ( 'com_ticket.json' , 'w' )

json_file. write (json. dumps (data ) )

json_file. close ( )

这里我们将component_verify_ticket存储到com_ticket.json文件中。另外这里我封装了微信的加解密类,代码如下:

classWxUtils:

defget_encrypt_xml ( self ,reply_xml ,nonce ):

encrypt =WXBizMsgCrypt ( token ,encodingAESKey ,component_appid )

ret_encrypt ,encrypt_xml =encrypt. EncryptMsg (reply_xml ,nonce )

ifret_encrypt == 0:

returnencrypt_xml

else:

return ''

defget_decrypt_xml ( self ,encrypt_xml ,msg_signature ,timestamp ,nonce ):

decrypt =WXBizMsgCrypt ( token ,encodingAESKey ,component_appid )

ret_decrypt ,decrypt_xml =decrypt. DecryptMsg (encrypt_xml ,

msg_signature ,

timestamp ,

nonce )

ifret_decrypt == 0:

returndecrypt_xml

else:

return ''

填坑1:

你用以上代码来解密时,其实会出现一个问题,微信传递过来的xml文件中没有ToUserName字段,所以以上的解密方法会报错,我们看一下微信传递过来的xml:

<xml>

<AppId>something </AppId>

<CreateTime>1413192605 </CreateTime>

<InfoType>component_verify_ticket </InfoType>

<ComponentVerifyTicket>something </ComponentVerifyTicket>

</xml>

这时你怎么做? 我是直接判断xml中有没有ToUserName字段,如果没有,我就把AppId替换为ToUserName。我们可以顺便看下微信的解密方法中的其中一段代码:

defextract ( self ,xmltext ):

"""提取出xml数据包中的加密消息

@param xmltext: 待提取的xml字符串

@return: 提取出的加密消息字符串

"""

try:

xml_tree =ET. fromstring (xmltext )

encrypt =xml_tree. find ( "Encrypt" )

touser_name =xml_tree. find ( "ToUserName" )

returnierror. WXBizMsgCrypt_OK ,encrypt. text ,touser_name. text

except Exception ,e:

#print e

returnierror. WXBizMsgCrypt_ParseXml_Error , None , None

这是提取加密字符串的方法,没有ToUserName的xml会报错:

WXBizMsgCrypt_ParseXml_Error =- 40002

所以从这一点可以看出微信内部的开发人员水平我个人觉得也一般,至少没有考虑后来的扩展,它直接写死了。

还有一个办法就是在你的xml中提取出ComponentVerifyTicket字段,然后重新拼接个xml来解密,从思想的角度来讲,明显替换的方法效率高。

填坑2:

这个坑在后面会用到,就是当你接收的xml中有中文字符是时,我们需要在进行加解密前先进行utf8编码:

reply_xml =reply_xml. encode ( 'utf-8' )

这样在加解密的时候,就不会再报错。

好了,第一节就到这里,我们马上开始第二节。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。