所有请求为http请求,请求协议头需要增加自定义header:pod动态的secret
从专区访问specapi.weixin.qq.com
的所有接口均需要进行签名认证,要求在http请求的基础上而外在header中携带用于校验请求合法的必要参数:
timestamp
:请求时间戳nonce
:防重放随机串signature
:请求签名签名方法采用hmac_sha256,签名密钥可在专区中读取文件/static_config/secret_key
获取
下面用一个请求示例来介绍签名的完整过程。
请求示例
POST /api/data?a=x&b=y HTTP/1.1
Host: specapi.weixin.qq.com
Content-Type: application/json
Content-Length: 27
auth-corpid: wpaaaaaaa
nonce: abcdefge
timestamp: 1700000000
signature: aabbccddeeffgghhiijjkkll
{
"key": "value"
}
需要参与签名的数据
请求行:
请求头:
请求体:
具体过程
key=value
形式的字符串,如method=POST
:method=POST
url=/api/data
query-string=a=x&b=y
nonce=123123123
timestamp=1700000000
auth-corpid=wpAAAAAA
body-md5=aabbccdd
key=value
字符串按字典序排序后按照每行一串构造成完整的待签名数据块data(包含末尾换行符)auth-corpid=wpAAAAAA
body-md5=aabbccdd
timestamp=1700000000
method=POST
nonce=123123123
url=/api/data
query-string=a=x&b=y
signature = hmac_sha256(sign_secret, data)
签名示例代码
#!/usr/bin/env python3
# coding=utf-8
import hmac
import hashlib
import time
import random
import requests
import json
timestamp = str(int(time.time()))
nonce = str(random.randint(1, 1 << 64))
auth_corpid = '' #该示例spec/gettoken接口不需要带上auth_corpid
host = 'specapi.weixin.qq.com'
url = '/spec/gettoken'
body = '{"corpid": "CORPID", "secret": "SECRET"}'
class HMAC_SHA256Signer:
def __init__(self, key):
self.key = key
self.kv_list = []
def add(self, key, value):
if value != "":
self.kv_list.append("%s=%s\n" % (key, value))
def get_signature(self):
self.kv_list.sort()
return hmac.new(self.key.encode('utf-8'), ''.join(self.kv_list).encode('utf-8'), hashlib.sha256).hexdigest()
with open('/static_config/secret_key') as f:
signer = HMAC_SHA256Signer(f.read())
signer.add('method', 'POST')
signer.add('url', '/spec/gettoken')
signer.add('query-string', '')
signer.add('timestamp', timestamp)
signer.add('nonce', nonce)
body_md5 = hashlib.md5(body.encode('utf-8')).hexdigest()
signer.add('body-md5', body_md5)
signer.add('auth-corpid', auth_corpid)
sign = signer.get_signature();
print("got sign: " + sign)
headers = {
'Content-Type': 'application/json',
'Content-Length': str(len(body)),
'timestamp': timestamp,
'nonce': nonce,
'signature': sign
}
response = requests.post('http://%s%s' % (host, url), data = body, headers = headers)
print(response.content.decode('utf-8'))