说明:我写这篇文章的主要目的是因为我在做这块的时候遇到过一些坑,也是希望后来者能少走一些弯路。
科大讯飞AIUI开放平台地址
科大讯飞AIUI开放平台后处理地址
AIUI后处理开放平台协议
1. 科大讯飞接口服务类:
- <?php
- namespace service;
-
- /**
- * 科大讯飞AIUI服务
- * Class AIUIService
- * @package service
- */
- class AIUIService
- {
- const APP_ID = '*****'; //讯飞AIUI开放平台注册申请应用的应用ID(appid)
- const API_KEY = '****'; //接口密钥,由讯飞AIUI开放平台提供,调用方管理
- const TOKEN = '*****'; //后处理token
- const AES_KEY = '*****'; //加密AES KEY
-
- /**
- * @title 构造函数
- * @param string $key 密钥
- * @param string $method 加密方式
- * @param string $iv iv向量
- * @param mixed $options 还不是很清楚
- */
- public function __construct()
- {
- $this->token = self::TOKEN;
-
- // key是必须要设置的
- $this->secret_key = self::AES_KEY;
- $this->method = "AES-128-CBC";
- $this->iv = self::AES_KEY;
- $this->options = OPENSSL_RAW_DATA;
- }
-
- /**
- * @title 签名验证
- * @param $token token
- * @param $timestamp 时间戳
- * @param $rand 随机数
- * @param $aesKey $aesKey
- * @param $sign 客户端请求接口sign参数值
- * @return INT
- */
- public function checkAuth($sign,$timestamp,$rand,$key='')
- {
- //按规则拼接为字符串
- $str = self::createSignature($this->token,$timestamp,$rand,$key);
- ///校验签名字符串:0为一致、-1为不一致
- if ($str !== $sign) {
- return -1;
- }
- return 0;
- }
-
- /**
- * @title 生成签名
- * @param $token
- * @param $timestamp
- * @param $rand
- * @param string $aesKey
- * @return string
- */
- private static function createSignature($token,$timestamp,$rand,$key='')
- {
- //组装要排序的数组
- $arr = [$timestamp,$token,$rand];
- //字典序排序
- sort($arr);
- //拼接为一个字符串
- $str = implode('',$arr);
- //sha1加密
- return sha1($str);
- }
-
- /**
- * @title 加密
- * @param $plaintext string 要加密的字符串
- * @return string
- */
- public function encrypt($plaintext){
- //加密采用AES的CBC加密方式,秘钥为16字节(128bit),初始化向量复用秘钥,填充方式为PKCS7Padding。
- //返回的消息要以同样的方式进行加密。
- //加密过程:padding->CBC加密->base64编码
- //$option 以下标记的按位或: OPENSSL_RAW_DATA 原生数据,对应数字1,不进行 base64 编码。OPENSSL_ZERO_PADDING 数据进行 base64 编码再返回,对应数字0。
- return openssl_encrypt($plaintext, $this->method, $this->secret_key,$this->options, $this->iv);
- }
-
- /**
- * @title 解密
- * @param $ciphertext string 要解密的字符串
- * @return string
- */
- public function decrypt($ciphertext){
- //解密过程:base64解码->CBC解密->unpadding
- return openssl_decrypt($ciphertext, $this->method, $this->secret_key, $this->options, $this->iv);
- }
- }
2. 控制器处理:
接口调用示例:
注: 其他具体接入过程可参见文档:https://aiui.xfyun.cn/docs/access_docs
- <?php
- namespace app\api\controller;
-
- use service\AIUIService;
- use service\SimilarityMatch;
- use think\Db;
-
- /**
- * @title 科大讯飞自定义语义库
- * @class AiUi
- * @auth 邹柯
- * @date 2018-11-19
- */
- class AiUi
- {
- /**
- * @title 科大讯飞自定义语义库
- * @return json
- */
- public function accessVerification()
- {
- //接收参数
- $param = request()->param(false);
- //判断接口访问方式:POST/GET
- $res = isset($_SERVER['REQUEST_METHOD']) && !strcasecmp($_SERVER['REQUEST_METHOD'],'POST');
- if($res) { //POST
- //是否加密:encrypttype=aes-加密、raw-不加密
- $encrypttype = $param[ 'encrypttype'];
-
- //解密
- if($encrypttype == "aes"){
- $DeMsgContent = (new AIUIService())->decrypt(file_get_contents("php://input"));
- $DeMsgContent = json_decode($DeMsgContent,true);
- }else{
- //消息内容
- $MsgContent = $param['Msg']['Content'];
- $DeMsgContent = json_decode(base64_decode($MsgContent),true);
- }
-
- //这个地方是个坑,为空时必须返回'{"intent":{}}' 不能是'{"intent":[]}' 否则会报错,切记
- if(empty($DeMsgContent["intent"])){
- return '{"intent":{}}';
- }
-
- //组装要返回的问题答案
- //应答码(response code),0-操作成功、4-文本没有匹配的技能场景,技能不理解或不能处理该文本
- if(!empty($DeMsgContent["intent"]) && $DeMsgContent["intent"]["rc"] == 4){
- $msg = $this->getMsg($DeMsgContent["intent"]["text"]);
- if(empty($msg)){
- $msg_text = $DeMsgContent["intent"]["text"];
- $keywords = ["返回"];
- if(!in_array($msg_text,$keywords)){
- $msg_text = "这个技能我还没学会呢";
- $DeMsgContent["intent"]["service"] = "openQA";
- $DeMsgContent["intent"]["operation"] = "ANSWER";
- //入库未学会的问题
- $this->insertUndefineQuestion($DeMsgContent["intent"]['text']);
- $DeMsgContent["intent"]["semantic"] = [
- 'slots'=>[
- 'name'=>$DeMsgContent["intent"]["text"],
- 'operation'=>'ANSWER'
- ],
- ];
- }else{
- $DeMsgContent["intent"]["service"] = "app";
- $DeMsgContent["intent"]["operation"] = "EXIT";
- $DeMsgContent["intent"]["semantic"] = [
- 'slots'=>[
- 'name'=>$msg_text,
- 'operation'=>'EXIT'
- ],