文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
服务器地址配置
服务器地址配置介绍
开发者可使用服务器地址配置功能,将开发者服务器的URL填写到到开发者配置中,用于接收百家号推送的消息通知。
服务器配置
使用消息管理能力需要在开发者设置里面启用服务器配置,服务器配置需要填写:
- 服务器地址URL。(必须以http://或https://开头、不包含中文)
- Token,用作生成签名,需用户自行保存。
- Encoding AESKey,将用作消息体加解密密钥,需用户自行保存。
- 数据格式(选择百度与开发者服务器之间传输的数据格式,可选xml或者json)。
验证消息有效性
1.百家号侧服务器将使用post请求,发送消息。
参数如下:
参数名 | 类型 | 是否必须 | 描述 |
---|---|---|---|
signature | string | 是 | 对传参的加密签名值,用来确认请求是来自开放平台的必要校验 |
timestamp | string | 是 | 时间戳 |
nonce | string | 是 | 随机数 |
encrypt | string | 是 | 加密内容(消息内容,为传送消息的xml或者json字符串) |
2.signature标签加密
加密/校验算法:
- 将token、timestamp、nonce、encrypt四个参数进行字典序排序;
- 将四个参数字符串拼接成一个字符串进行sha1加密;
- 开发者获得加密后的字符串可与signature对比,标识该请求来源于百度。
PHP代码示例
<?php
//此处的token是开发者服务器配置中填写的Token
$TOKEN = 'your_token';
$strSignature = getSHA1($TOKEN, $_POST['timestamp'], $_POST['nonce']);
if ($strSignature == $_POST['signature']) {
echo $_POST['encrypt'];
} else {
//校验失败
echo 'failed';
}
/**
* 用sha1算法生成安全签名
* @param string $strToken message_token
* @param string $intTimeStamp 时间戳
* @param string $strNonce 随机字符串
* @param string $strEncryptMsg 密文消息
* @return string
*/
function getSHA1($strToken, $intTimeStamp, $strNonce, $strEncryptMsg = '')
{
$arrParams = array(
$strToken,
$intTimeStamp,
$strNonce,
);
if (!empty($strEncryptMsg)) {
array_unshift($arrParams, $strEncryptMsg);
}
sort($arrParams, SORT_STRING);
$strParam = implode($arrParams);
return sha1($strParam);
}
消息内容加解密方式
1.消息加解密是为了进一步加强消息的安全性和隐私性提供的机制。需注意:
- 消息加解密,会对所有消息实际内容数据进行加密,并存放在请求的encrypt参数中。
- 消息加解密使用AES加解密方式。
<?php
class Lib_Util_AesEncrypt {
/**
* @var int
*/
public static $blockSize = 32;
/**
* @var
*/
private $appId;
/**
* aes key
* @var bool|string
*/
private $aesKey;
/**
* AesEncryptNewUtilUtil constructor.
* @param $appId
* @param $encodingAesKey
*/
public function __construct($appId, $encodingAesKey)
{
$this->appId = $appId;
$this->aesKey = base64_decode($encodingAesKey . "=");
}
/**
* 对明文进行加密
* @param $text
* @return string
* @throws XzhException
*/
public function encrypt($text)
{
// 获得16位随机字符串,填充到明文之前
$random = $this->getRandomStr();
$text = $random . pack("N", strlen($text)) . $text . $this->appId;
$iv = substr($this->aesKey, 0, 16);
// 对明文进行补位填充
$text = $this->encode($text);
// 加密
$encrypted = openssl_encrypt($text, 'aes-256-cbc', $this->aesKey, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
// 使用BASE64对加密后的字符串进行编码
return base64_encode($encrypted);
}
/**
* 对密文进行解密
* @param $encrypted
* @return bool|string
* @throws XzhException
*/
public function decrypt($encrypted, $isCheckAppId = true)
{
// 使用BASE64对需要解密的字符串进行解码
$ciphertextDec = base64_decode($encrypted);
$iv = substr($this->aesKey, 0, 16);
// 解密
$decrypted = openssl_decrypt($ciphertextDec, 'aes-256-cbc', $this->aesKey, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
// 去除补位字符
$result = $this->decode($decrypted);
// 去除16位随机字符串,网络字节序和appId
if (strlen($result) < 16) {
Bingo_Log::warning("AesEncryptUtil AES解密串非法,小于16位;");
return false;
}
$content = substr($result, 16, strlen($result));
$lenList = unpack("N", substr($content, 0, 4));
$xmlLen = $lenList[1];
$xmlContent = substr($content, 4, $xmlLen);
$fromAppId = substr($content, $xmlLen + 4);
if ($isCheckAppId && ($fromAppId != $this->appId)) {
Bingo_Log::warning("不符合AesEncrypt AES解密规范");
return false;
}
return $xmlContent;
}
/**
* 对需要加密的明文进行填充补位
* @param $text
* @return string
*/
private function encode($text)
{
$textLength = strlen($text);
//计算需要填充的位数
$amountToPad = self::$blockSize - ($textLength % self::$blockSize);
if ($amountToPad == 0) {
$amountToPad = self::$blockSize;
}
//获得补位所用的字符
$padChr = chr($amountToPad);
$tmp = "";
for ($index = 0; $index < $amountToPad; $index++) {
$tmp .= $padChr;
}
return $text . $tmp;
}
/**
* 对解密后的明文进行补位删除
* @param $text
* @return bool|string
*/
private function decode($text)
{
$pad = ord(substr($text, -1));
if ($pad < 1 || $pad > self::$blockSize) {
$pad = 0;
}
return substr($text, 0, (strlen($text) - $pad));
}
/**
* 随机生成16位字符串
* @return string
*/
private function getRandomStr()
{
$strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
$max = strlen($strPol) - 1;
$str = "";
for ($i = 0; $i < 16; $i++) {
$str .= $strPol[mt_rand(0, $max)];
}
return $str;
}
}
2.json数据加解密示例:
数据解密:
//数据解密
$appId = 'your appId';
$aes_key = 'your aesKey';
$dataCoder = new AesEncryptUtil($appId, $aes_key);
//百家号服务器发送的消息
$str = "{
"signature":"bcd6a8ee6c6a542c0c2fa8813b54802835e31273",
"timestamp":"2019-03-19 17:03:26",
"nonce":"KvQCIstHlT2SiRbrxJU1",
"encrypt":
"ZgI+FCQPbQ7vWV4GBDU1i8jOP2leMJtpHfGLdCVUwMHpzrz7FS68HNHflm8nmYnUzmR+LWZXl2dB6vBW9M04GBiMOvR5gbLdeXX+EbLrV2xo4COu36oozDESQ85iSXOSgJ6GUHk2T8/36K1ff3Qty2n+h2Jgjno+8gmB9feEmvHOlOT4lPq8wyJbKa8tjJn1kaDucJhnbVgDs7YoMpqx2ESgEfwwZHn2pLu5zb4OPXrhhMlXk9Px/pK15YFve6WUDJ0+ce+fhyx9n+3EVFbCJ7qt5mY8fhOTJ7UdWDBHtajC4Dr4yvEMWxAA9oge2cUBoPU8gnaHOjvnPymaidsTycVTiIIawvwPRzJel1ArtypiZHVkB9w/xvSqILoF5JjUxeUljx0+wjTUAUmXdctaX8/kH7Bk0p2W3qN31GWVIY4/MkaWIi1o7BBvawNXx+2VBqR4c+ZZh62al25CfoX7W4r1Y8jnvuMHqa1ZJFrk5CR9HqL76Phib03u/KNKYEKfUK4VdlXnp5WbAwtEMfg807uqXEWSC6/egYHRIWReScTr37JlSwBjXRZ5ufDAZ3cjW1jcN51rDdo+U7t/mXdq50N+6aFxNBQkUV4Ddwo6JbBvKoh34ZFeV/g04jH4+izD5p2jj6v1wpWmDskqziu1Vn0heiqQh7RXCYdL++S/lo8K3QclZ52u0u2Nd5Ns/zy01EdHLG0p++u+suPp9NRGhTH9z9KYeSPsywzuSd3ZAIiMrBhvs0wZGLPIgaIn2oJpKBnejw3aitScbKEmNVO0ufkkj+XFdEorAkeuZt1Ojj+EBOzB6clfbY7L133oWawZ9XIvsL9DAkZxyb8yZbNgZ8oqQt8+MIT5z3s6sgKZF3irqKgpwIoDtwSNpogDruHN"}";
$data = json_decode($str, true);
print_r($dataCoder->decrypt($data['encrypt']));
消息服务器对获取内容处理样例
<?php
//此处的token是开发者服务器配置中填写的Token
$TOKEN = 'your_token';
$strSignature = getSHA1($TOKEN, $_POST['timestamp'], $_POST['nonce']);
if ($strSignature == $_POST['signature']) {
$appId = 'your appId';
$aes_key = 'your aesKey';
$dataCoder = new AesEncryptUtil($appId, $aes_key);
print_r($dataCoder->decrypt($_POST['encrypt']));
} else {
//校验失败
echo 'failed';
}
服务器收到的格式
{
"signature":"cdd3b55b040385b57fa4566e612dfa25b6c43747",
"timestamp":"2019-03-25 16:56:40",
"nonce":"6Q7H1eRf2KQSfipGGRdZ",
"encrypt":
"3/4zeQN8zRIFxLcDHqyJawOaMX/DDrXcb8c2mCq49gH7t8ax+Ozc89rx6YxCB7+3fIehUsmptI/LB0pC0gr30HfFcik9xBCN30k7P/8LFcmGjbCxG9b3ZG/XaJ46kTyFQ5+FzhvHUaeJoGimVSoQpTxUe2BmWhVTsHEixXpiUsHJA87iUFlMhUenKzLJ2eQvZSPh1RELG3fVvYLEt47rZbPaqGTSnVj/R+tWerrVA/l/sioIkmj23ALqIssmtIDIDCqUTfXWiByoKW0i4O0Fz3JFFoS51BCAx6DmCkyWdAv4DBPNXTuS1vrDQyTCsXPnkJXsXJmhjnipoPFw9Xop+7I22lL7jvES7lkp1JZCbpzJEJjE2AGCKqi6kivW5FlY1Jp4kCYIxps/28nayxV9jwrizcaZqYVS/o4x5pBzDAfaQ0c4lh1lyl7bJLha+3HsvPhEQTXymtY0lTKyWFGfZg=="
}
encrypt字段解密后的xml格式
<?xml version="1.0" encoding="utf-8"?>
<xml>
<app_id><![CDATA[$app_id]]></app_id>
<data>
<title><![CDATA[$title]]></title>
<content><![CDATA[$content]]></content>
</data>
<type>
<type_id><![CDATA[$id]]></type_id>
<desc><![CDATA[$desc]]></desc>
</type>
<msg_id><![CDATA[$msgId]]></msg_id>
<article_id><![CDATA[$articleId]]></article_id>
</xml>
encrypt字段解密后的json格式
{
"app_id":"$appId",
"data":{"title":"$title","content":"$content"},
"type":{"type_id":$id,"desc":"$desc"},
"msg_id":"$msgId",
"article_id":"$articleId"
}
字段属性:
参数名 | 类型 | 描述 |
---|---|---|
app_id | string | 作者帐号ID |
data | dict | 消息内容 |
-title | string | 消息标题 |
-content | string | 消息正文 |
type | dict | 消息类型 |
-type_id | int | 消息类型ID |
-desc | string | 消息类型简介 |
msg_id | string | 预留字段 |
article_id | string | 文章ID |
消息ID对应关系
ID | 简介 |
---|---|
1 | 系统消息(主要包括了封禁等一系列通知消息) |
暂支持系统消息通知,后续将开放更多类型的消息通知
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论