When browsing message push , Stuck for a long time in the template card section ; It mainly involves url Callback work for , Not very familiar with . The website links - Template card
Official special instructions :
Special instructions
- have only Button interactive 、 Voting choice 、 Multiple choice And filled in action_menu Text notification type of field 、 Graphic display cards can be updated by callback or through the interface .
- Cards that support callback and update can enable users to click to trigger interactive events , The callback interface set by the developer is required to handle callback events , Callback protocol visible document Template card event push , Be careful Applications that do not have a callback interface configured cannot send cards that support callback .
- After the developer's service receives the callback event , The corresponding data needs to be returned according to the protocol to update the card , See the document for the corresponding protocol Update template card message .
- After this interface sends a card message that supports callback update , The returned parameters will be accompanied by response_code, You can use response_code Call the update template card message interface ,response_code 24 Within hours , And the interface can only be called once .
At present, the second item is solved , Configure the callback interface to support sending template cards
The website links - Callback service
The message can be customized through the callback service , Such as identifying keywords , Get the status of messages dynamically .
Before using code development , First, you need to configure the callback interface service in the corresponding application , Definition URL, Token, EncodingAESKey.
there URL This is the callback address accessed later
step :
First, download the third-party encryption library Encryption library link ; Choose the right language to github Download
To configure django project , Define callback interface :http://ip:port/jyg/vertifyinfo, When the enterprise administrator saves the callback configuration information , Enterprise wechat will send a verification message to the filled in URL, That is, in a given url Add later timestamp, nonce, echostr, msg_signature Used to verify
def versityInfo(request):
sToken = "xxx"
sEncodingAESKey = "xxx" # Just configured , Written here , The configuration information can be extracted separately
sCorpID = "xxx" # corpID
if request.method == 'GET': # GEt To verify the
wxcpt=WXBizMsgCrypt(sToken,sEncodingAESKey,sCorpID)
# Extract the parameters in the request
sVerifyMsgSig = request.GET.get("msg_signature")
sVerifyTimeStamp=request.GET.get("timestamp")
sVerifyNonce=request.GET.get("nonce")
sVerifyEchoStr=request.GET.get("echostr")
# Call a third-party library to verify
ret,sEchoStr=wxcpt.VerifyURL(sVerifyMsgSig, sVerifyTimeStamp,sVerifyNonce,sVerifyEchoStr)
if(ret!=0):
print("ERR: VerifyURL ret: " + str(ret))
sys.exit(1)
# Return the message after verification and decryption
return HttpResponse(sEchoStr)
for example VerifyURL For the third party Library , There are three methods in total , You can browse the official website for details .
Code completion can be tested using interface testing tools : The website links - Interface testing tool
Then click Save to complete the configuration .
Request mode :GET(HTTPS)
Request address :https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_follow_user_list?access_token=ACCESS_TOKEN
Request parameters :
{
"touser" : "JiuXiaTian",
"msgtype" : "template_card",
"agentid" : 1000033,
"template_card" : {
"card_type" : "text_notice",
"source" : {
"desc": " Enterprise WeChat ",
"desc_color": 1
},
"action_menu": {
"desc": " Auxiliary interactive text description of the card ",
"action_list": [
{
"text": " Accept push ", "key": "A"},
{
"text": " No more push ", "key": "B"}
]
},
"task_id": "task_id",
"main_title" : {
"title" : " Welcome to enterprise wechat ",
"desc" : " Your friend is inviting you to join enterprise wechat "
},
"quote_area": {
"type": 1,
"url": "https://work.weixin.qq.com",
"title": " Reference style of enterprise wechat ",
"quote_text": " Enterprise wechat is very useful "
},
"emphasis_content": {
"title": "100",
"desc": " Core Data "
},
"sub_title_text" : " Downloading enterprise wechat can also grab red envelopes !",
"horizontal_content_list" : [
{
"keyname": " The invitee ",
"value": " Zhang San "
},
{
"type": 1,
"keyname": " Enterprise wechat official website ",
"value": " Click on the access ",
"url": "https://work.weixin.qq.com"
}
],
"card_action": {
"type": 1,
"url": "https://work.weixin.qq.com"
}
},
"enable_id_trans": 0,
"enable_duplicate_check": 0,
"duplicate_check_interval": 1800
}
Running results :
In the enterprise wechat, you can customize the callback message according to the sent message , The renderings are as follows :
The callback interface for passively receiving messages POST Method , The official website call interface is as follows :
Request mode :POST
Request address :http://api.3dept.com/?msg_signature=ASDFQWEXZCVAQFASDFASDFSS×tamp=13500001234&nonce=123412323
Request body : When the user submits a message , Will be encapsulated in the request body as a ${xml} Formatted data
have access to if request.method Route distribution in the way of , But observe the parameters :GET Include in validation sVerifyEchoStr, and POST Request body data when stored in , You can also judge from this point , Such as :
# Common parameters
sVerifyMsgSig = request.GET.get("msg_signature")
sVerifyTimeStamp = request.GET.get("timestamp")
sVerifyNonce = request.GET.get("nonce")
sVerifyEchoStr = request.GET.get("echostr")
if sVerifyEchoStr:
pass
else: # receive messages
pass
preparation , Define a custom message body , To process information decryption , Encryption and other situations :
# Custom message processing
class MessageHandler:
def __init__(self, baseData):
self.wxcpt = baseData['wxcpt']
self.sVerifyMsgSig = baseData['sVerifyMsgSig']
self.sVerifyTimeStamp = baseData['sVerifyTimeStamp']
self.sVerifyNonce = baseData['sVerifyNonce']
# Processing initialization parameters in request
# Data initialization
sToken = URLRobackSetting['sToken']
sEncodingAESKey = URLRobackSetting['sEncodingAESKey']
sCorpID = URLRobackSetting['sCorpID']
wxcpt = WXBizMsgCrypt(sToken, sEncodingAESKey, sCorpID)
# Common parameters
sVerifyMsgSig = request.GET.get("msg_signature")
sVerifyTimeStamp = request.GET.get("timestamp")
sVerifyNonce = request.GET.get("nonce")
sVerifyEchoStr = request.GET.get("echostr")
baseData = {
"wxcpt": wxcpt,
"sVerifyMsgSig": sVerifyMsgSig,
"sVerifyTimeStamp": sVerifyTimeStamp,
"sVerifyNonce": sVerifyNonce
}
# Custom message processing class
messageHandler = MessageHandler(baseData)
Receive a message , Parse to plaintext , Call the official decryption function :DecryptMsg
def receiveInfo(self, sReqData):
"""" receive messages """
try:
# Decrypt
sReqMsgSig = self.sVerifyMsgSig
sReqTimeStamp = self.sVerifyTimeStamp
sReqNonce = self.sVerifyNonce
# Decryption function
ret, sMsg = self.wxcpt.DecryptMsg(
sReqData, sReqMsgSig, sReqTimeStamp, sReqNonce)
print("=>", ret, sMsg)
# here sMsg In plain text
return ret, sMsg
except Exception as e:
raise e
Parsing the contents of plaintext , Then customize the message :
def responseInfo(self, sEncryptMsg):
result = xmltodict.parse(sEncryptMsg)
xml = result["xml"]
# Parsing content
content = xml['Content']
fromUserName = xml['FromUserName']
# Custom message
if content == "test":
message = "this is success test"
else:
message = "please check document"
return self.customMessage(fromUserName, message)
xmltodict: modular , Is used to xml Convert to python Dictionary in
Customized messages are encrypted according to the official data , Call function :EncryptMsg
def customMessage(self, user, content):
try:
response_data = "<xml><ToUserName><![CDATA[" + user + \
"]]></ToUserName><FromUserName><![CDATA[corid]]></FromUserName><CreateTime>1476422779</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[" + content + "]]></Content></xml>"
# response_data = unicode(response_data).encode('utf8') # python2 Handle
print("data=>", response_data)
ret, sEncryptMsg = self.wxcpt.EncryptMsg(
response_data, self.sVerifyNonce, self.sVerifyTimeStamp)
if(ret != 0):
raise Exception
# Return the encrypted reply message
final_data = {
"code": 200,
"sEncryptMsg": sEncryptMsg
}
return HttpResponse(json.dumps(final_data))
except Exception:
raise Exception
@csrf_exempt
def versityInfo(request):
sToken = URLRobackSetting['sToken']
sEncodingAESKey = URLRobackSetting['sEncodingAESKey']
sCorpID = URLRobackSetting['sCorpID']
try:
wxcpt = WXBizMsgCrypt(sToken, sEncodingAESKey, sCorpID)
# Common parameters
sVerifyMsgSig = request.GET.get("msg_signature")
sVerifyTimeStamp = request.GET.get("timestamp")
sVerifyNonce = request.GET.get("nonce")
sVerifyEchoStr = request.GET.get("echostr")
baseData = {
"wxcpt": wxcpt,
"sVerifyMsgSig": sVerifyMsgSig,
"sVerifyTimeStamp": sVerifyTimeStamp,
"sVerifyNonce": sVerifyNonce
}
# Custom message processing class
messageHandler = MessageHandler(baseData)
if sVerifyEchoStr:
print("=>", sVerifyMsgSig, sVerifyTimeStamp, sVerifyEchoStr)
ret, sEchoStr = wxcpt.VerifyURL(
sVerifyMsgSig, sVerifyTimeStamp, sVerifyNonce, sVerifyEchoStr)
if(ret != 0):
print("ERR: VerifyURL ret: " + str(ret))
final_data = {
"code": 400,
"sEncryptMsg": " Verification failed "
}
return HttpResponse(json.dumps(final_data))
return HttpResponse(sEchoStr)
else: # receive messages
# Extract parameters
# unicode(string).encode("utf-8")
sReqData = request.body
sReqMsgSig = sVerifyMsgSig
sReqTimeStamp = sVerifyTimeStamp
sReqNonce = sVerifyNonce
print("=>", sReqData, type(sReqMsgSig), sReqTimeStamp, sReqNonce)
# receive data
ret, sEncryptMsg = messageHandler.receiveInfo(sReqData)
if(ret != 0):
print("ERR: EncryptMsg ret: ", str(ret))
final_data = {
"code": 400,
"sEncryptMsg": " Parameter error "
}
return HttpResponse(json.dumps(final_data))
# Parsing plaintext data , And then send a message
return messageHandler.responseInfo(sEncryptMsg)
except Exception as e:
print("system error:", e)
final_data = {
"code": 10056,
"sEncryptMsg": " The system is currently under repair ..."
}
response = HttpResponse(json.dumps(final_data))
return response
# Custom message body
class MessageHandler:
def __init__(self, baseData):
self.wxcpt = baseData['wxcpt']
self.sVerifyMsgSig = baseData['sVerifyMsgSig']
self.sVerifyTimeStamp = baseData['sVerifyTimeStamp']
self.sVerifyNonce = baseData['sVerifyNonce']
def receiveInfo(self, sReqData):
"""" receive messages """
try:
# Decrypt
sReqMsgSig = self.sVerifyMsgSig
sReqTimeStamp = self.sVerifyTimeStamp
sReqNonce = self.sVerifyNonce
# Decryption function
ret, sMsg = self.wxcpt.DecryptMsg(
sReqData, sReqMsgSig, sReqTimeStamp, sReqNonce)
print("=>", ret, sMsg)
# here sMsg In plain text
return ret, sMsg
except Exception as e:
raise e
def responseInfo(self, sEncryptMsg):
result = xmltodict.parse(sEncryptMsg)
xml = result["xml"]
# Parsing content
content = xml['Content']
fromUserName = xml['FromUserName']
# Custom message
if content == "test":
message = "this is success test"
else:
message = "please check document"
return self.customMessage(fromUserName, message)
def customMessage(self, user, content):
try:
response_data = "<xml><ToUserName><![CDATA[" + user + \
"]]></ToUserName><FromUserName><![CDATA[wx7fc55822f12887ad]]></FromUserName><CreateTime>1476422779</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[" + content + "]]></Content></xml>"
# response_data = unicode(response_data).encode('utf8') # python2 Handle
print("data=>", response_data)
ret, sEncryptMsg = self.wxcpt.EncryptMsg(
response_data, self.sVerifyNonce, self.sVerifyTimeStamp)
if(ret != 0):
raise Exception
# Return the encrypted reply message
final_data = {
"code": 200,
"sEncryptMsg": sEncryptMsg
}
return HttpResponse(json.dumps(final_data))
except Exception:
raise Exception