声明:此内容仅供学习交流使用,不用于商业用途,如果涉及侵权,联系作者删除。
最近在调用腾讯云的人像动漫化接口,感觉挺好玩的,自己去看文档写了一下,遇到了各种问题,最后都解决了 ,遇到最多的就是签名错误(AuthFailure.SignatureFailure),都是看文档不看完导致的,要注意签名参数的顺序、请求参数的值必须进行url编码之内的,甚至我还sb的把调用签名加密方法的参数顺序搞混了,害得我找了好久 -_-|| ,还好都解决了。下面展示代码:
常规的GET和POST的请求方式:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace ConsoleApp2
{
class Main_3
{
static void Main(string[] args)
{
string action = "FaceCartoonPic";//接口名称
string secretid = "你的SecretId";//SecretId
string secretKey = "你的SecretKey";//SecretKey
string version = "2020-03-04";//版本
string region = "ap-guangzhou";//云服务器区域,离你越近越好
string url = "https://ft.tencentcloudapi.com/";//接口地址
string host = "ft.tencentcloudapi.com";//域名
Random rd = new Random();
string nonce = rd.Next().ToString();///随机正整数,用于防止重放攻击
string timestamp = GetCurrentTimestamp();//时间戳
string filename = @"F:\XXX\XXX\xy.jpg";//图片路径
string imgbase64 = ImgToBase64(filename);//base64字串要是图片转base64的方式才行,文件转base64的方式会报URL过长的错
Dictionary<string, string> postdata = new Dictionary<string, string>();
postdata.Add("Action", action);
postdata.Add("Image", imgbase64);
postdata.Add("Language", "zh-CN");
postdata.Add("Nonce", nonce);
postdata.Add("Region", region);
postdata.Add("SecretId", secretid);
//dic.Add("SignatureMethod", "HmacSHA1");//加密方式 默认HmacSHA1
postdata.Add("Timestamp", timestamp);
postdata.Add("Version", version);
string data = string.Empty;
SortedDictionary<string, string> sortDc = new SortedDictionary<string, string>(postdata, StringComparer.Ordinal);//排序 加密的数据必须排序
foreach (var item in sortDc)
{
if (!string.IsNullOrEmpty(data))
{
data += "&";
}
data += string.Format("{0}={1}", item.Key, item.Value);
}
string qm = $"POST{host}/?" + data;//POST请求的加密前字串
string signature = Sign(secretKey, qm);
postdata.Add("Signature", signature);//添加上签名字段
data = string.Empty;
foreach (var item in postdata)
{
if (!string.IsNullOrEmpty(data))
{
data += "&";
}
data += string.Format("{0}={1}", item.Key, HttpUtility.UrlEncode(item.Value));//参数的值必须要进行URL编码
}
Dictionary<string, string> headers = new Dictionary<string, string>();
//headers.Add("Host", host);//请求头带有Host
string res = Post(url, data);//Post的请求方式
//string res = Get(url + "?" + data);Get的请求方式
Console.WriteLine(res);
Console.ReadKey();
}
/// <summary>
/// 进行SHA1签名加密
/// </summary>
/// <param name="signKey">secretKey</param>
/// <param name="secret">需要加密的字符串</param>
/// <returns></returns>
public static string Sign(string signKey, string secret)
{
string signRet = string.Empty;
using (HMACSHA1 mac = new HMACSHA1(Encoding.UTF8.GetBytes(signKey)))
{
byte[] hash = mac.ComputeHash(Encoding.UTF8.GetBytes(secret));
signRet = Convert.ToBase64String(hash);
}
return signRet;
}
/// <summary>
/// 图片转Base64
/// </summary>
/// <param name="filename">文件路径</param>
/// <returns></returns>
public static string ImgToBase64(string filename)
{
string base64_3;
MemoryStream ms = new MemoryStream();
try
{
Bitmap bmp = new Bitmap(filename);
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] arr = new byte[ms.Length];
ms.Position = 0;
ms.Read(arr, 0, (int)ms.Length);
base64_3 = Convert.ToBase64String(arr);
bmp.Dispose();
return base64_3;
}
catch (Exception ex)
{
return ex.Message;
}
finally
{
ms.Close();
}
}
/// <summary>
/// 获取时间戳
/// </summary>
/// <returns></returns>
public static string GetCurrentTimestamp()
{
//TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
//return Convert.ToInt64(ts.TotalSeconds).ToString();
var number = 10000 * 1000;
return ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / number).ToString();
}
/// <summary>
/// 常规Post请求
/// </summary>
/// <param name="url"></param>
/// <param name="content"></param>
/// <returns></returns>
public static string Post(string url, string postData)
{
// 创建一个WebRequest对象
WebRequest request = WebRequest.Create(url);
// 设置请求方法为POST
request.Method = "POST";
// 将数据转换为字节数组
byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(postData);
// 设置请求内容类型
request.ContentType = "application/x-www-form-urlencoded";
//设置代理
request.Proxy = new WebProxy("代理IP", 端口);
// 设置请求内容长度
request.ContentLength = byteArray.Length;
// 获取请求流并写入数据
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
// 发送请求并获取响应
WebResponse response = request.GetResponse();
// 读取响应流
StreamReader reader = new StreamReader(response.GetResponseStream());
string responseText = reader.ReadToEnd();
// 关闭响应流和请求对象
reader.Close();
response.Close();
return responseText;
}
/// <summary>
/// 常规Get请求
/// </summary>
/// <param name="url"></param>
/// <param name="content"></param>
/// <returns></returns>
public static string Get(string url)
{
string result = "";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.Proxy = new WebProxy("代理IP", 端口);//设置代理
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
using (StreamReader reader = new StreamReader(stream))
{
result = reader.ReadToEnd();
}
}
}
return result;
}
}
}
使用SDK的方式:
需要去neget上安装:TencentCloud
然后引用上,下面是代码:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using TencentCloud.Common;
using TencentCloud.Common.Profile;
using TencentCloud.Ft.V20200304;
using TencentCloud.Ft.V20200304.Models;
namespace ConsoleApp2
{
class Main_1
{
static void Main(string[] args)
{
try
{
// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
Credential cred = new Credential
{
SecretId = "你的SecretId",
SecretKey = "你的SecretKey"
};
// 实例化一个client选项,可选的,没有特殊需求可以跳过
ClientProfile clientProfile = new ClientProfile();
// 实例化一个http选项,可选的,没有特殊需求可以跳过
HttpProfile httpProfile = new HttpProfile();
httpProfile.Endpoint = ("ft.tencentcloudapi.com");
clientProfile.HttpProfile = httpProfile;
clientProfile.HttpProfile.WebProxy = "http://你的代理IP:端口";//设置代理
// 实例化要请求产品的client对象,clientProfile是可选的
FtClient client = new FtClient(cred, "ap-guangzhou", clientProfile);
// 实例化一个请求对象,每个接口都会对应一个request对象
FaceCartoonPicRequest req = new FaceCartoonPicRequest();
string filename = @"F:\XXX\XXX\xy.jpg";//图片路径
string imgbase64 = ImgToBase64(filename);
req.Image = imgbase64;
// 返回的resp是一个FaceCartoonPicResponse的实例,与请求对象对应
FaceCartoonPicResponse resp = client.FaceCartoonPicSync(req);
// 输出json格式的字符串回包
string res = AbstractModel.ToJsonString(resp);
Console.WriteLine(res);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.ReadKey();
}
static string ImgToBase64(string filename)
{
string base64_3;
MemoryStream ms = new MemoryStream();
try
{
Bitmap bmp = new Bitmap(filename);
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] arr = new byte[ms.Length];
ms.Position = 0;
ms.Read(arr, 0, (int)ms.Length);
base64_3 = Convert.ToBase64String(arr);
bmp.Dispose();
return base64_3;
}
catch (Exception ex)
{
return ex.Message;
}
finally
{
ms.Close();
}
}
}
}
代码就是这些,挺简单的,就是调接口时一些小细节没注意到,导致了很多次都是失败。