小程序场景下直接调用
视觉智能开放平台的API接口推荐使用SDK进行调用,因为调用需要使用AccessKey ID和AccessKey Secret,推荐在服务端进行接入,在客户端直接接入有AccessKey ID和AccessKey Secret泄漏风险,请自行评估风险范围。
阿里云视觉智能开放平台各类目视觉AI能力API接入、接口使用或问题咨询等,请通过钉钉群(23109592)加入阿里云视觉智能开放平台咨询群联系我们。
使用小程序直接调用,请参见请求签名。
使用签名机制调用,文件参数当前系统推荐使用上海OSS链接,您需要将文件放入到上海OSS中,具体操作,请参见开通OSS服务。具体调用方式,请参见文件在同地域OSS。
如果是其他情况(如本地文件或者其他链接),您需要先显式地将文件转换成上海OSS链接,具体操作,请参见文件URL处理。具体调用方式,请参见文件在本地或不在同一地域 OSS。
配置环境变量
配置环境变量ALIBABA_CLOUD_ACCESS_KEY_ID和ALIBABA_CLOUD_ACCESS_KEY_SECRET。
阿里云账号AccessKey拥有所有API的访问权限,建议您使用RAM用户进行API访问或日常运维,具体操作,请参见创建RAM用户。
请不要将AccessKey ID和AccessKey Secret保存到工程代码里,否则可能导致AccessKey泄露,威胁您账号下所有资源的安全。
Linux和macOS系统配置方法
在IntelliJ IDEA中打开终端Terminal。
执行以下命令,配置环境变量。
<access_key_id>
需替换为您RAM用户的AccessKey ID,<access_key_secret>
替换为您RAM用户的AccessKey Secret。如果后续需要进行更多权限相关的配置,具体操作请参见使用RAM Policy控制访问权限。export ALIBABA_CLOUD_ACCESS_KEY_ID=<access_key_id> export ALIBABA_CLOUD_ACCESS_KEY_SECRET=<access_key_secret>
Windows系统配置方法
新建环境变量文件,添加环境变量
ALIBABA_CLOUD_ACCESS_KEY_ID
和ALIBABA_CLOUD_ACCESS_KEY_SECRET
,并写入已准备好的AccessKey ID和AccessKey Secret。然后重启Windows系统。本操作以Windows 10为例进行说明。打开文件资源管理器,在此电脑上右键单击属性。
在右侧导航栏,单击高级系统配置。
在系统属性对话框的高级页签下,单击环境变量。
在环境变量对话框中,单击新建(W)。
在弹出的新建系统变量对话框中,添加环境变量
ALIBABA_CLOUD_ACCESS_KEY_ID
和ALIBABA_CLOUD_ACCESS_KEY_SECRET
,并写入已准备好的AccessKey ID和AccessKey Secret。重启Windows系统,使配置生效。
文件在同地域OSS
如果您的文件存放在上海OSS中,可以参考请求签名进行调用。本文以银行卡识别(RecognizeBankCard)为例,仅展示关键步骤及关键代码,完整示例可下载MiniprogramDemo。您如果调用其他算法,请参考注释和实际业务修改相应代码。
安装crypto-js依赖,该库在计算签名时使用。
npm install crypto-js
计算签名。
/** * ======================================================================================================================== * 以下代码仅仅为了调用服务端接口计算签名,其逻辑可参考文档:https://help.aliyun.com/document_detail/144904.html * 这里只是为了Web前端演示,所以将代码写在了Web前端 * 真正上线不建议将ACCESS_KEY_ID和ACCESS_KEY_SECRET写在Web前端上,会有泄漏风险,建议将请求API接口代码写到您的服务端 * ======================================================================================================================== */ //随机数字 function signNRandom() { const Rand = Math.random() const mineId = Math.round(Rand * 100000000000000) return mineId; }; //Timestamp function getTimestamp() { let date = new Date(); let YYYY = pad2(date.getUTCFullYear()); let MM = pad2(date.getUTCMonth() + 1); let DD = pad2(date.getUTCDate()); let HH = pad2(date.getUTCHours()); let mm = pad2(date.getUTCMinutes()); let ss = pad2(date.getUTCSeconds()); return `${YYYY}-${MM}-${DD}T${HH}:${mm}:${ss}Z`; } function pad2(num) { if (num < 10) { return '0' + num; } return '' + num; }; function ksort(params) { let keys = Object.keys(params).sort(); let newParams = {}; keys.forEach((key) => { newParams[key] = params[key]; }); return newParams; }; function createHmac(stringToSign, key) { const CrypStringToSign = CryptoJS.HmacSHA1(CryptoJS.enc.Utf8.parse(stringToSign), key); const base64 = CryptoJS.enc.Base64.stringify(CrypStringToSign); return base64; }; function encode(str) { var result = encodeURIComponent(str); return result.replace(/!/g, '%21') .replace(/'/g, '%27') .replace(/\(/g, '%28') .replace(/\)/g, '%29') .replace(/\*/g, '%2A'); }; function sha1(stringToSign, key) { return createHmac(stringToSign, key); }; function getSignature(signedParams, method, secret) { var stringToSign = `${method}&${encode('/')}&${encode(signedParams)}`; const key = secret + "&"; return sha1(stringToSign, key); }; //参数拼接 function objToParam(param) { if (Object.prototype.toString.call(param) !== '[object Object]') { return ''; } let queryParam = ''; for (let key in param) { if (param.hasOwnProperty(key)) { let value = param[key]; queryParam += toQueryPair(key, value); } } return queryParam; }; function toQueryPair(key, value) { if (typeof value == 'undefined') { return `&${key}=`; } return `&${encodeURIComponent(key)}=${encode(value)}`; }; function generateUrl(request, httpMethod, endpoint, accessKeySecret) { //参数中key排序 const sortParams = ksort(request); //拼成参数 const sortQueryStringTmp = objToParam(sortParams); const sortedQueryString = sortQueryStringTmp.substring(1);// 去除第一个多余的&符号 //构造待签名的字符串 const Signature = getSignature(sortedQueryString, httpMethod, accessKeySecret) //签名最后也要做特殊URL编码 request["Signature"] = encodeURIComponent(Signature); //最终生成出合法请求的URL const finalUrl = "https://" + endpoint + "/?Signature=" + encodeURIComponent(Signature) + sortQueryStringTmp; return finalUrl; }
说明计算签名的逻辑详情请参见请求签名。
封装接口。
import CryptoJS from 'crypto-js'; /** * ======================================================================================================================== * 以RecognizeBankCard为例。 * 这里只是为了小程序端演示流程,所以将代码写在了小程序端 * 真正上线不建议将ACCESS_KEY_ID和ACCESS_KEY_SECRET写在小程序端,会有泄漏风险,建议将请求API接口代码写到您的服务端 * 请求银行卡识别:https://help.aliyun.com/document_detail/151893.html * ======================================================================================================================== */ // 参数说明: // miniProgramType:小程序类型,比如:微信小程序传参数:wx,支付宝/钉钉传参数:my,注意不要传字符串; // callback:结果的回调 function callRecognizeBankCard(miniProgramType, callback) { /* 创建AccessKey ID和AccessKey Secret,请参考https://help.aliyun.com/document_detail/175144.html。 如果您用的是RAM用户AccessKey,还需要为RAM用户授予权限AliyunVIAPIFullAccess,请参考https://help.aliyun.com/document_detail/145025.html。 从环境变量读取配置的AccessKey ID和AccessKey Secret。运行示例前必须先配置环境变量。 */ const accessKeyId = process.env.ALIBABA_CLOUD_ACCESS_KEY_ID; const accessKeySecret = process.env.ALIBABA_CLOUD_ACCESS_KEY_SECRET; // 这里endpoint为API访问域名,与类目相关,具体类目的API访问域名请参考:https://help.aliyun.com/document_detail/143103.html const endpoint = "ocr.cn-shanghai.aliyuncs.com"; // API Action,能力名称,请参考具体算法文档详情页中的Action参数,这里以银行卡识别为例:https://help.aliyun.com/document_detail/151893.html const Action = "RecognizeBankCard"; // API_HTTP_METHOD推荐使用POST const API_HTTP_METHOD = "POST"; // API_VERSION为API版本,与类目相关,具体类目的API版本请参考:https://help.aliyun.com/document_detail/464194.html const API_VERSION = "2019-12-30"; const request_ = {}; //系统参数 request_["SignatureMethod"] = "HMAC-SHA1", request_["SignatureNonce"] = signNRandom(), request_["AccessKeyId"] = accessKeyId, request_["SignatureVersion"] = "1.0", request_["Timestamp"] = getTimestamp(), request_["Format"] = "JSON", request_["RegionId"] = "cn-shanghai", request_["Version"] = API_VERSION, request_["Action"] = Action; //业务参数,请参考具体的AI能力的API文档进行修改,需要注意在调用其他能力时,这里的入参要根据API文档的入参名进行修改,如人脸活体检测API文档里面的参数名称是“Tasks.N.ImageURL”形式的,因为是支持同时检测多个Task的情况,所以入参时是从“Tasks.1.ImageURL”开始的。 //举例 request_["Tasks.1.ImageURL"] = "传入您的url"; request_["ImageURL"] = "http://viapi-test.oss-cn-shanghai.aliyuncs.com/viapi-3.0domepic/ocr/RecognizeBankCard/yhk3.jpg"; callApiRequest(miniProgramType, request_, API_HTTP_METHOD, endpoint, accessKeySecret, callback); } //请求数据 function callApiRequest(miniProgramType, request_, API_HTTP_METHOD, endpoint, accessKeySecret, callback) { const url = generateUrl(request_, API_HTTP_METHOD, endpoint, accessKeySecret); miniProgramType.request({ url: url, method: 'POST', header: { "ContentType": "application/json" }, success: (result) => { // 获取结果 return typeof callback == "function" && callback(result.data) }, fail: (error) => { // 获取报错信息 return typeof callback == "function" && callback(error.data) } }) } // 导出方法 module.exports = { callRecognizeBankCard: callRecognizeBankCard }
说明本文以银行卡识别(RecognizeBankCard)为例,如果调用其他算法,请参考注释和实际业务修改相应代码。
调用接口。
const client = require("../../utils/client.js"); // index.js Page({ data: { cardNumber: '', errorMessage: '', }, callApi: function() { client.callRecognizeBankCard(wx, function(result) { if(result.Code) { // 请处理错误 } else { // 获取银行卡号,这里只是示例,请根据文档获取自己想要的出参 this.setData({'cardNumber': result.Data.CardNumber}); } }.bind(this)); } })
说明本文以银行卡识别(RecognizeBankCard)为例,如果调用其他算法,请参考注释和实际业务修改相应代码。
Request合法域名配置。
小程序中请求接口需要配置服务器域名。不同的AI类目对应的域名不一样,详情请参见访问域名。
以微信小程序为例,配置Request合法域名,如下图所示。
说明在微信小程序中,将代码中的
<your appid>
需要更换为您的appid。
完整的示例可下载MiniprogramDemo。
完整工程仅以银行卡识别(RecognizeBankCard)为例,如果调用其他算法,请参考注释进行相应代码修改。
utils/client.js文件中,callRecognizeBankCard函数的accessKeyId、accessKeySecret、endpoint、Action、API_VERSION参数及request_["ImageURL"]这一行代表业务参数。
例如,您想使用通用分割能力,通过通用分割API文档可知该能力属于分割抠图类目(imageseg20191230),能力名称为SegmentCommonImage,您需要将endpoint改为imageseg.cn-shanghai.aliyuncs.com(注意该域名需要加入小程序白名单),Action改为SegmentCommonImage,API_VERSION为2019-12-30不用修改,request_["ImageURL"]参数名为ImageURL不用修改。获取结果的时候,需要获取ImageURL,其含义不是银行卡号,而是分割后的图片地址。
文件在本地或不在同一地域OSS
如果您的文件在本地或不在同一地域OSS,请参见文件URL处理,显式地将文件转换成上海OSS链接,再进行调用。
本文以银行卡识别(RecognizeBankCard)为例,仅展示关键步骤及关键代码,完整的示例可下载MiniprogramDemo。您如果调用其他算法,请参考注释和实际业务修改相应代码。
安装js-base64依赖,该库在计算OSS签名时使用。
npm install js-base64
说明此处仅以微信小程序为例,关于支付宝或者钉钉小程序,请参见小程序中 base64 数据解码&编码示例。
调用GetOssStsToken接口获取临时的OSS STS Token。
/** * ======================================================================================================================== * 获取oss sts token,使用阿里云视觉智能开放平台官方OSS-Bucket作为临时存储,仅为方便用户方便调试接口使用,文件存储有效期为1天。 * 这里只是为了Web前端演示流程,所以将代码写在了Web前端 * 真正上线不建议将ACCESS_KEY_ID和ACCESS_KEY_SECRET写在Web前端,会有泄漏风险,建议将请求API接口代码写到您的服务端 * ossStsToken获取原理:请参考文档https://help.aliyun.com/document_detail/155645.html,方式二中的其他语言 * ======================================================================================================================== */ function getOssStsToken(callback) { // 这里endpoint为API访问域名,与类目相关,具体类目的API访问域名请参考:https://help.aliyun.com/document_detail/143103.html const endpoint = "viapiutils.cn-shanghai.aliyuncs.com"; // API Action,能力名称,请参考具体算法文档详情页中的Action参数,这里以银行卡识别为例:https://help.aliyun.com/document_detail/151893.html const Action = "GetOssStsToken"; // API_VERSION为API版本,与类目相关,具体类目的API版本请参考:https://help.aliyun.com/document_detail/464194.html const API_VERSION = "2020-04-01"; callApi(endpoint, Action, API_VERSION, null, callback); } /** * ======================================================================================================================== * 通过签名方式调用API,支持平台的任意API。 * 这里只是为了小程序端演示流程,所以将代码写在了小程序端 * 真正上线不建议将ACCESS_KEY_ID和ACCESS_KEY_SECRET写在小程序端,会有泄漏风险,建议将请求API接口代码写到您的服务端 * 签名文档:https://help.aliyun.com/document_detail/144904.html * ======================================================================================================================== */ function callApi(endpoint, action, version, params, callback) { // API_HTTP_METHOD推荐使用POST const API_HTTP_METHOD = "POST"; const request_ = {}; //系统参数 request_["SignatureMethod"] = "HMAC-SHA1", request_["SignatureNonce"] = signNRandom(), request_["AccessKeyId"] = accessKeyId, request_["SignatureVersion"] = "1.0", request_["Timestamp"] = getTimestamp(), request_["Format"] = "JSON", request_["RegionId"] = "cn-shanghai", request_["Version"] = version, request_["Action"] = action; // 业务参数,请参考具体的AI能力的API文档进行修改 if(params) { for(let key in params) { request_[key] = params[key]; } } callApiRequest(miniProgramType, request_, API_HTTP_METHOD, endpoint, accessKeySecret, callback); }
说明更多关于本步骤的原理详情,请参见文件URL处理。
使用临时的OSS STS Token将文件上传到阿里云视觉智能开放平台官方OSS Bucket。
/** * ======================================================================================================================== * 处理文件和URL,将其上传到阿里云视觉智能开放平台官方OSS-Bucket作为临时存储,该方式仅为方便用户方便调试接口使用,文件存储有效期为1天。 * ======================================================================================================================== */ // 使用oss-client-sdk进行文件上传 function uploadToTempOss(ossStsToken, tempFilePath, fileName, callback) { const host = 'https://viapi-customer-temp.oss-cn-shanghai.aliyuncs.com'; let formDataParams = getFormDataParams(ossStsToken.AccessKeyId,ossStsToken.AccessKeySecret,ossStsToken.SecurityToken); const signature = formDataParams.signature; const ossAccessKeyId = ossStsToken.AccessKeyId; const policy = formDataParams.policy; const key = accessKeyId+'/'+getNonce(6)+'/'+fileName; const securityToken = formDataParams['x-oss-security-token']; miniProgramType.uploadFile({ url: host, // 开发者服务器的URL。 filePath: tempFilePath, name: 'file', // 必须填file。 formData: { key, policy, OSSAccessKeyId: ossAccessKeyId, signature, 'x-oss-security-token': securityToken // 使用STS签名时必传。 }, success: (res) => { if (res.statusCode === 204 || res.statusCode === '204') { let result = 'https://viapi-customer-temp.oss-cn-shanghai.aliyuncs.com/'+key; callback && callback(result); } else { console.log('upload error', res); } }, fail: err => { console.log(err); } }); } /** * ======================================================================================================================== * 以下代码仅仅为了调用OSS上传文件计算签名,其逻辑可参考文档:https://help.aliyun.com/document_detail/92883.html#section-mx7-v31-uy7,客户端签名第二步 * 这里只是为了Web前端演示,所以将代码写在了Web前端 * 真正上线不建议将ACCESS_KEY_ID和ACCESS_KEY_SECRET写在Web前端上,会有泄漏风险,建议将请求API接口代码写到您的服务端 * ======================================================================================================================== */ // 计算签名 function computeSignature(accessKeySecret, canonicalString) { return CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA1(canonicalString, accessKeySecret)); } // 随机字符串 function getNonce(length) { var str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; var result = ''; for (var i = length; i > 0; --i) result += str[Math.floor(Math.random() * str.length)]; return result; } // 计算上传OSS的计算签名 function getFormDataParams(stsAccessKeyId,stsAccessKeySecret,securityToken) { const date = new Date(); date.setHours(date.getHours() + 1); const policyText = { expiration: date.toISOString(), // 设置policy过期时间。 conditions: [ // 限制上传大小。 ["content-length-range", 0, 1024 * 1024 * 1024], ], }; const policy = Base64.encode(JSON.stringify(policyText)) // policy必须为base64的string。 const signature = computeSignature(stsAccessKeySecret, policy) const formData = { OSSAccessKeyId: stsAccessKeyId, signature, policy, 'x-oss-security-token': securityToken } return formData }
更多详情,请参见OSS微信小程序直传实践步骤3:获取签名中的客户端签名下的客户端获取STS临时账号并生成签名,以及步骤4:使用微信小程序上传。
对于支付宝或者钉钉小程序,代码中第18行的
name: 'file',
需要改成fileName: 'file', fileType: 'image',
,请参见OSS支付宝小程序直传实践步骤2:获取签名中的客户端签名下的客户端获取STS临时账号并生成签名,以及步骤3:使用支付宝小程序上传。上传完成之后得到OSS URL地址,按照文件在同地域OSS方式进行调用。
/** * ======================================================================================================================== * 以RecognizeBankCard为例。 * 这里只是为了小程序端演示流程,所以将代码写在了小程序端 * 真正上线不建议将ACCESS_KEY_ID和ACCESS_KEY_SECRET写在小程序端,会有泄漏风险,建议将请求API接口代码写到您的服务端 * 请求银行卡识别:https://help.aliyun.com/document_detail/151893.html * ======================================================================================================================== */ // 参数说明: // imageUrl:图片url // callback:结果的回调 function callRecognizeBankCard(imageUrl, callback) { // 这里endpoint为API访问域名,与类目相关,具体类目的API访问域名请参考:https://help.aliyun.com/document_detail/143103.html const endpoint = "ocr.cn-shanghai.aliyuncs.com"; // API Action,能力名称,请参考具体算法文档详情页中的Action参数,这里以银行卡识别为例:https://help.aliyun.com/document_detail/151893.html const Action = "RecognizeBankCard"; // API_HTTP_METHOD推荐使用POST const API_HTTP_METHOD = "POST"; // API_VERSION为API版本,与类目相关,具体类目的API版本请参考:https://help.aliyun.com/document_detail/464194.html const API_VERSION = "2019-12-30"; const params = {}; //业务参数,请参考具体的AI能力的API文档进行修改,需要注意在调用其他能力时,这里的入参要根据API文档的入参名进行修改,如人脸活体检测API文档里面的参数名称是“Tasks.N.ImageURL”形式的,因为是支持同时检测多个Task的情况,所以入参时是从“Tasks.1.ImageURL”开始的。 //举例 params["Tasks.1.ImageURL"] = imageUrl; params["ImageURL"] = imageUrl; callApi(endpoint, Action, API_VERSION, params, callback); }
说明本文以银行卡识别(RecognizeBankCard)为例,如果调用其他算法,请参考注释和实际业务修改相应代码。
Request合法域名配置。
小程序中请求接口需要配置服务器域名。不同的AI类目对应的域名不一样,详情请参见访问域名。
以微信小程序为例,配置Request合法域名,如下图所示。
完整的示例可下载MiniprogramDemo。
在微信小程序中,将代码中的
<your appid>
需要更换为您的appid。完整工程仅以银行卡识别(RecognizeBankCard)为例,如果调用其他算法,请参考注释进行相应代码修改。
utils/client.js文件中的accessKeyId、accessKeySecret,callRecognizeBankCard函数的endpoint、Action、API_VERSION参数及request_["ImageURL"]这一行代表业务参数。
例如,您想使用通用分割能力,通过通用分割API文档可知该能力属于分割抠图类目(imageseg20191230),能力名称为SegmentCommonImage,您需要将endpoint改为imageseg.cn-shanghai.aliyuncs.com(注意该域名需要加入小程序白名单),Action改为SegmentCommonImage,API_VERSION为2019-12-30不用修改,request_["ImageURL"]参数名为ImageURL不用修改。获取结果的时候,需要获取ImageURL,其含义不是银行卡号,而是分割后的图片地址。