unity 接入火山引擎API,包括即梦AI
风格化图生图
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Security.Cryptography;
using System.Text;
using UnityEngine.Networking;
using Newtonsoft.Json;//
[Serializable]
public class AlgorithmBaseResp
{public int status_code;public string status_message;
}
[Serializable]
public class Data
{public AlgorithmBaseResp algorithm_base_resp;public List<string> binary_data_base64;public List<string> image_urls;
}
[Serializable]
public class Result
{public int code;public Data data;public string message;public string request_id;public int status;public string time_elapsed;
}public class PicToPic : MonoBehaviour
{public Result result;private static readonly char[] HexDigits = "0123456789ABCDEF".ToCharArray();private string _region= "cn-north-1";private string _service= "cv";private string _schema;private string _host= "visual.volcengineapi.com";private string _path= "/";private string _ak = "替换你自己的Access Key ID";private string _sk= "替换你自己的Secret Access Key";public string req_key;public string sub_req_key;public Texture2D texture2D;public void SignMenthod(string region, string service, string schema, string host, string path, string ak, string sk){_region = region;_service = service;_schema = schema;_host = host;_path = path;_ak = ak;_sk = sk;}[ContextMenu("StartUpload")]public void StartUpload(){ImgToImg(req_key, sub_req_key);}public void ImgToImg(string key, string value){try{string filePath = Application.dataPath + "/chooseState/1.png";// string baseImage = ImageToBase64(filePath);string baseImage = T2dToBase64(texture2D); // 火山官网密钥写入string AccessKeyID = _ak;string SecretAccessKey = _sk;// 请求域名string endpoint = "visual.volcengineapi.com";string path = "/"; // 路径,不包含 Query// 请求接口信息string service = "cv";string region = "cn-north-1";string schema = "https";SignMenthod(region, service, schema, endpoint, path, AccessKeyID, SecretAccessKey);// 参考接口文档Query参数string action = "CVProcess";string version = "2022-08-31";DateTime date = DateTime.UtcNow;// 参考接口文档Body参数var req = new Dictionary<string, object>{{ "req_key", key},{ "sub_req_key",value},{ "binary_data_base64", new List<string> { baseImage } },{ "return_url",true}};StopCoroutine("DoRequest2");StartCoroutine(DoRequest2("POST", new Dictionary<string, string>(), Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(req)), date, action, version));}catch (Exception e){Console.WriteLine(e.Message);}}//public string ImageToBase64(string filepath)//{// using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(filepath))// {// MemoryStream ms = new MemoryStream();// bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);// byte[] arr = new byte[ms.Length];// ms.Position = 0;// ms.Read(arr, 0, (int)ms.Length);// ms.Close();// return Convert.ToBase64String(arr);// }//}public string T2dToBase64(Texture2D texture2D){// 将 Texture2D 编码成 PNG 或 JPGbyte[] imageBytes = texture2D.EncodeToJPG(100); // 或使用 EncodeToJPG()// 转换为 Base64 字符串return Convert.ToBase64String(imageBytes);}public IEnumerator DoRequest2(string method, Dictionary<string, string> queryList, byte[] body,DateTime date, string action, string version){if (body == null){body = new byte[0];}string xContentSha256 = HashSHA256(body);string xDate = date.ToString("yyyyMMddTHHmmssZ");string shortXDate = xDate.Substring(0, 8);string contentType = "application/json";string signHeader = "host;x-date;x-content-sha256;content-type";var realQueryList = new SortedDictionary<string, string>(queryList){{ "Action", action },{ "Version", version }};var queryStringBuilder = new StringBuilder();foreach (var kvp in realQueryList){queryStringBuilder.Append(UrlEncode(kvp.Key)).Append("=").Append(UrlEncode(kvp.Value)).Append("&");}queryStringBuilder.Length--; // Remove the last '&'string canonicalStringBuilder = $"{method}\n{_path}\n{queryStringBuilder}\n" +$"host:{_host}\n" +$"x-date:{xDate}\n" +$"x-content-sha256:{xContentSha256}\n" +$"content-type:{contentType}\n" +"\n" +$"{signHeader}\n" +$"{xContentSha256}";Debug.Log(canonicalStringBuilder);string hashCanonicalString = HashSHA256(Encoding.UTF8.GetBytes(canonicalStringBuilder));string credentialScope = $"{shortXDate}/{_region}/{_service}/request";string signString = $"HMAC-SHA256\n{xDate}\n{credentialScope}\n{hashCanonicalString}";byte[] signKey = GenSigningSecretKeyV4(_sk, shortXDate, _region, _service);string signature = BitConverter.ToString(HmacSHA256(signKey, signString)).Replace("-", "").ToLower();var url = $"{_schema}://{_host}{_path}?{queryStringBuilder}";url = "https://visual.volcengineapi.com?Action=CVProcess&Version=2022-08-31";using (UnityWebRequest webRequest = new UnityWebRequest(url, "POST")){// 设置请求内容webRequest.uploadHandler = (UploadHandler)new UploadHandlerRaw(body);webRequest.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();webRequest.SetRequestHeader("Content-Type", "application/json");webRequest.SetRequestHeader("Host", _host);webRequest.SetRequestHeader("X-Date", xDate);webRequest.SetRequestHeader("X-Content-Sha256", xContentSha256);webRequest.SetRequestHeader("Authorization",$"HMAC-SHA256 Credential={_ak}/{credentialScope}, SignedHeaders={signHeader}, Signature={signature}");yield return webRequest.SendWebRequest();if (webRequest.result != UnityWebRequest.Result.ConnectionError || webRequest.result != UnityWebRequest.Result.ProtocolError){try{string responseText = webRequest.downloadHandler.text;Debug.Log(responseText);//print(responseText);result = JsonConvert.DeserializeObject<Result>(responseText);//Data.Binarycount = result.data.binary_data_base64;//Base64ToSave(result.data.binary_data_base64[0], null);//显示以及后续处理 }catch (Exception ex){Debug.Log($"发送失败:{ex.Message}");}}else{//失败提示处理}webRequest.Dispose();}}//public void Base64ToSave(string base64, Action<Bitmap> action)//{// try// {// string imgPath = $"{Application.dataPath}\\saveImg\\" + "XXX.png";// string imgeName = DateTime.Now.ToString("hh_mm_ss") + ".png";// byte[] bytes = Convert.FromBase64String(base64);// using (MemoryStream mStream = new MemoryStream(bytes))// {// System.Drawing.Image mImage = System.Drawing.Image.FromStream(mStream);// Bitmap bmp = new Bitmap(mImage);// bmp.Save(imgPath, System.Drawing.Imaging.ImageFormat.Png);// action((Bitmap)bmp.Clone());// bmp.Dispose();// mImage.Dispose();// }// }// catch (Exception ex)// {// Debug.Log($"保存图片出现异常:{ex.Message}");// }//}private string UrlEncode(string source){if (string.IsNullOrEmpty(source)){return source;}var encoded = new StringBuilder(source.Length);foreach (var symbol in Encoding.UTF8.GetBytes(source)){if (symbol >= 97 && symbol <= 122 || symbol >= 65 && symbol <= 90 || symbol >= 48 && symbol <= 57 ||symbol == (byte)'-' || symbol == (byte)'_' || symbol == (byte)'.' || symbol == (byte)'~'){encoded.Append((char)symbol);}else if (symbol == 32){encoded.Append("%20");}else{encoded.Append('%');encoded.Append(HexDigits[symbol >> 4]);encoded.Append(HexDigits[symbol & 15]);}}return encoded.ToString();}public static string HashSHA256(byte[] content){using (SHA256 sha256 = SHA256.Create()){byte[] hash = sha256.ComputeHash(content);return BitConverter.ToString(hash).Replace("-", "").ToLower();}}public static byte[] HmacSHA256(byte[] key, string content){using (HMACSHA256 hmac = new HMACSHA256(key)){return hmac.ComputeHash(Encoding.UTF8.GetBytes(content));}}private byte[] GenSigningSecretKeyV4(string secretKey, string date, string region, string service){byte[] kDate = HmacSHA256(Encoding.UTF8.GetBytes(secretKey), date);byte[] kRegion = HmacSHA256(kDate, region);byte[] kService = HmacSHA256(kRegion, service);return HmacSHA256(kService, "request");}
}
即梦AI图生图
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Security.Cryptography;
using System.Text;
using UnityEngine.Networking;
using Newtonsoft.Json;[Serializable]
public class JMData
{public List<string> PreviewImage_121;public AlgorithmBaseResp algorithm_base_resp;public List<object> binary_data_base64;public double comfyui_cost;public List<string> image_urls;
}
[Serializable]
public class JMResult
{public int code;public JMData data;public string message;public string request_id;public int status;public string time_elapsed;
}public class JMAI : MonoBehaviour
{public JMResult result;private static readonly char[] HexDigits = "0123456789ABCDEF".ToCharArray();private string _region = "cn-north-1";private string _service = "cv";private string _schema;private string _host = "visual.volcengineapi.com";private string _path = "/";private string _ak = "替换你自己的Access Key ID";private string _sk= "替换你自己的Secret Access Key";public string prompt;public Texture2D texture2D;public void SignMenthod(string region, string service, string schema, string host, string path, string ak, string sk){_region = region;_service = service;_schema = schema;_host = host;_path = path;_ak = ak;_sk = sk;}[ContextMenu("StartUpload")]public void StartUpload(){ImgToImg(prompt);}public void ImgToImg(string prompt){try{string filePath = Application.dataPath + "/chooseState/1.png";// string baseImage = ImageToBase64(filePath);string baseImage = T2dToBase64(texture2D);// 火山官网密钥写入string AccessKeyID = _ak;string SecretAccessKey = _sk;// 请求域名string endpoint = "visual.volcengineapi.com";string path = "/"; // 路径,不包含 Query// 请求接口信息string service = "cv";string region = "cn-north-1";string schema = "https";SignMenthod(region, service, schema, endpoint, path, AccessKeyID, SecretAccessKey);// 参考接口文档Query参数string action = "CVProcess";string version = "2022-08-31";DateTime date = DateTime.UtcNow;// 参考接口文档Body参数var req = new Dictionary<string, object>{{ "req_key", "jimeng_i2i_v30"},{ "prompt",prompt},{ "binary_data_base64", new List<string> { baseImage } },{ "return_url",true}};StopCoroutine("DoRequest2");StartCoroutine(DoRequest2("POST", new Dictionary<string, string>(), Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(req)), date, action, version));}catch (Exception e){Console.WriteLine(e.Message);}}//public string ImageToBase64(string filepath)//{// using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(filepath))// {// MemoryStream ms = new MemoryStream();// bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);// byte[] arr = new byte[ms.Length];// ms.Position = 0;// ms.Read(arr, 0, (int)ms.Length);// ms.Close();// return Convert.ToBase64String(arr);// }//}public string T2dToBase64(Texture2D texture2D){// 将 Texture2D 编码成 PNG 或 JPGbyte[] imageBytes = texture2D.EncodeToJPG(100); // 或使用 EncodeToJPG()// 转换为 Base64 字符串return Convert.ToBase64String(imageBytes);}public IEnumerator DoRequest2(string method, Dictionary<string, string> queryList, byte[] body,DateTime date, string action, string version){if (body == null){body = new byte[0];}string xContentSha256 = HashSHA256(body);string xDate = date.ToString("yyyyMMddTHHmmssZ");string shortXDate = xDate.Substring(0, 8);string contentType = "application/json";string signHeader = "host;x-date;x-content-sha256;content-type";var realQueryList = new SortedDictionary<string, string>(queryList){{ "Action", action },{ "Version", version }};var queryStringBuilder = new StringBuilder();foreach (var kvp in realQueryList){queryStringBuilder.Append(UrlEncode(kvp.Key)).Append("=").Append(UrlEncode(kvp.Value)).Append("&");}queryStringBuilder.Length--; // Remove the last '&'string canonicalStringBuilder = $"{method}\n{_path}\n{queryStringBuilder}\n" +$"host:{_host}\n" +$"x-date:{xDate}\n" +$"x-content-sha256:{xContentSha256}\n" +$"content-type:{contentType}\n" +"\n" +$"{signHeader}\n" +$"{xContentSha256}";Debug.Log(canonicalStringBuilder);string hashCanonicalString = HashSHA256(Encoding.UTF8.GetBytes(canonicalStringBuilder));string credentialScope = $"{shortXDate}/{_region}/{_service}/request";string signString = $"HMAC-SHA256\n{xDate}\n{credentialScope}\n{hashCanonicalString}";byte[] signKey = GenSigningSecretKeyV4(_sk, shortXDate, _region, _service);string signature = BitConverter.ToString(HmacSHA256(signKey, signString)).Replace("-", "").ToLower();var url = $"{_schema}://{_host}{_path}?{queryStringBuilder}";url = "https://visual.volcengineapi.com?Action=CVProcess&Version=2022-08-31";using (UnityWebRequest webRequest = new UnityWebRequest(url, "POST")){// 设置请求内容webRequest.uploadHandler = (UploadHandler)new UploadHandlerRaw(body);webRequest.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();webRequest.SetRequestHeader("Content-Type", "application/json");webRequest.SetRequestHeader("Host", _host);webRequest.SetRequestHeader("X-Date", xDate);webRequest.SetRequestHeader("X-Content-Sha256", xContentSha256);webRequest.SetRequestHeader("Authorization",$"HMAC-SHA256 Credential={_ak}/{credentialScope}, SignedHeaders={signHeader}, Signature={signature}");yield return webRequest.SendWebRequest();if (webRequest.result != UnityWebRequest.Result.ConnectionError || webRequest.result != UnityWebRequest.Result.ProtocolError){try{string responseText = webRequest.downloadHandler.text;Debug.Log(responseText);//print(responseText);result = JsonConvert.DeserializeObject<JMResult>(responseText);//Data.Binarycount = result.data.binary_data_base64;//Base64ToSave(result.data.binary_data_base64[0], null);//显示以及后续处理 }catch (Exception ex){Debug.Log($"发送失败:{ex.Message}");}}else{//失败提示处理}webRequest.Dispose();}}//public void Base64ToSave(string base64, Action<Bitmap> action)//{// try// {// string imgPath = $"{Application.dataPath}\\saveImg\\" + "XXX.png";// string imgeName = DateTime.Now.ToString("hh_mm_ss") + ".png";// byte[] bytes = Convert.FromBase64String(base64);// using (MemoryStream mStream = new MemoryStream(bytes))// {// System.Drawing.Image mImage = System.Drawing.Image.FromStream(mStream);// Bitmap bmp = new Bitmap(mImage);// bmp.Save(imgPath, System.Drawing.Imaging.ImageFormat.Png);// action((Bitmap)bmp.Clone());// bmp.Dispose();// mImage.Dispose();// }// }// catch (Exception ex)// {// Debug.Log($"保存图片出现异常:{ex.Message}");// }//}private string UrlEncode(string source){if (string.IsNullOrEmpty(source)){return source;}var encoded = new StringBuilder(source.Length);foreach (var symbol in Encoding.UTF8.GetBytes(source)){if (symbol >= 97 && symbol <= 122 || symbol >= 65 && symbol <= 90 || symbol >= 48 && symbol <= 57 ||symbol == (byte)'-' || symbol == (byte)'_' || symbol == (byte)'.' || symbol == (byte)'~'){encoded.Append((char)symbol);}else if (symbol == 32){encoded.Append("%20");}else{encoded.Append('%');encoded.Append(HexDigits[symbol >> 4]);encoded.Append(HexDigits[symbol & 15]);}}return encoded.ToString();}public static string HashSHA256(byte[] content){using (SHA256 sha256 = SHA256.Create()){byte[] hash = sha256.ComputeHash(content);return BitConverter.ToString(hash).Replace("-", "").ToLower();}}public static byte[] HmacSHA256(byte[] key, string content){using (HMACSHA256 hmac = new HMACSHA256(key)){return hmac.ComputeHash(Encoding.UTF8.GetBytes(content));}}private byte[] GenSigningSecretKeyV4(string secretKey, string date, string region, string service){byte[] kDate = HmacSHA256(Encoding.UTF8.GetBytes(secretKey), date);byte[] kRegion = HmacSHA256(kDate, region);byte[] kService = HmacSHA256(kRegion, service);return HmacSHA256(kService, "request");}
}
即梦图生视频
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
[Serializable]
public class JMVideoData
{public List<object> binary_data_base64 ;public object image_urls ;public string resp_data ;public string status ;public string video_url ;
}
[Serializable]
public class JMVideoResult
{public int code ;public JMVideoData data ;public string message ;public string request_id ;public int status ;public string time_elapsed ;
}
public class JMVideo : MonoBehaviour
{public JMVideoResult result;private static readonly char[] HexDigits = "0123456789ABCDEF".ToCharArray();private string _region = "cn-north-1";private string _service = "cv";private string _schema;private string _host = "visual.volcengineapi.com";private string _path = "/";private string _ak = "替换你自己的Access Key ID";private string _sk= "替换你自己的Secret Access Key";public string prompt;public Texture2D texture2D;public string taskId;public void SignMenthod(string region, string service, string schema, string host, string path, string ak, string sk){_region = region;_service = service;_schema = schema;_host = host;_path = path;_ak = ak;_sk = sk;}[ContextMenu("StartUpload")]public void StartUpload(){ImgToImg(prompt);}[ContextMenu("CheckTask")]public void CheckTask(){try{// 火山官网密钥写入string AccessKeyID = _ak;string SecretAccessKey = _sk;// 请求域名string endpoint = "visual.volcengineapi.com";string path = "/"; // 路径,不包含 Query// 请求接口信息string service = "cv";string region = "cn-north-1";string schema = "https";SignMenthod(region, service, schema, endpoint, path, AccessKeyID, SecretAccessKey);// 参考接口文档Query参数string action = "CVSync2AsyncGetResult";string version = "2022-08-31";DateTime date = DateTime.UtcNow;// 参考接口文档Body参数var req = new Dictionary<string, object>{{ "req_key", "jimeng_vgfm_i2v_l20"},{ "task_id",taskId}};StopCoroutine("DoRequest2");StartCoroutine(DoRequest2("POST", new Dictionary<string, string>(), Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(req)), date, action, version));}catch (Exception e){Console.WriteLine(e.Message);}}public void ImgToImg(string prompt){try{//string filePath = Application.dataPath + "/chooseState/1.png";// string baseImage = ImageToBase64(filePath);string baseImage = T2dToBase64(texture2D);// 火山官网密钥写入string AccessKeyID = _ak;string SecretAccessKey = _sk;// 请求域名string endpoint = "visual.volcengineapi.com";string path = "/"; // 路径,不包含 Query// 请求接口信息string service = "cv";string region = "cn-north-1";string schema = "https";SignMenthod(region, service, schema, endpoint, path, AccessKeyID, SecretAccessKey);// 参考接口文档Query参数string action = "CVSync2AsyncSubmitTask";string version = "2022-08-31";DateTime date = DateTime.UtcNow;// 参考接口文档Body参数var req = new Dictionary<string, object>{{ "req_key", "jimeng_vgfm_i2v_l20"},{ "prompt",prompt},{ "binary_data_base64", new List<string> { baseImage } },{ "aspect_ratio","16:9"}};StopCoroutine("DoRequest2");StartCoroutine(DoRequest2("POST", new Dictionary<string, string>(), Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(req)), date, action, version));}catch (Exception e){Console.WriteLine(e.Message);}}//public string ImageToBase64(string filepath)//{// using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(filepath))// {// MemoryStream ms = new MemoryStream();// bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);// byte[] arr = new byte[ms.Length];// ms.Position = 0;// ms.Read(arr, 0, (int)ms.Length);// ms.Close();// return Convert.ToBase64String(arr);// }//}public string T2dToBase64(Texture2D texture2D){// 将 Texture2D 编码成 PNG 或 JPGbyte[] imageBytes = texture2D.EncodeToJPG(100); // 或使用 EncodeToJPG()// 转换为 Base64 字符串return Convert.ToBase64String(imageBytes);}public IEnumerator DoRequest2(string method, Dictionary<string, string> queryList, byte[] body,DateTime date, string action, string version){if (body == null){body = new byte[0];}string xContentSha256 = HashSHA256(body);string xDate = date.ToString("yyyyMMddTHHmmssZ");string shortXDate = xDate.Substring(0, 8);string contentType = "application/json";string signHeader = "host;x-date;x-content-sha256;content-type";var realQueryList = new SortedDictionary<string, string>(queryList){{ "Action", action },{ "Version", version }};var queryStringBuilder = new StringBuilder();foreach (var kvp in realQueryList){queryStringBuilder.Append(UrlEncode(kvp.Key)).Append("=").Append(UrlEncode(kvp.Value)).Append("&");}queryStringBuilder.Length--; // Remove the last '&'string canonicalStringBuilder = $"{method}\n{_path}\n{queryStringBuilder}\n" +$"host:{_host}\n" +$"x-date:{xDate}\n" +$"x-content-sha256:{xContentSha256}\n" +$"content-type:{contentType}\n" +"\n" +$"{signHeader}\n" +$"{xContentSha256}";Debug.Log(canonicalStringBuilder);string hashCanonicalString = HashSHA256(Encoding.UTF8.GetBytes(canonicalStringBuilder));string credentialScope = $"{shortXDate}/{_region}/{_service}/request";string signString = $"HMAC-SHA256\n{xDate}\n{credentialScope}\n{hashCanonicalString}";byte[] signKey = GenSigningSecretKeyV4(_sk, shortXDate, _region, _service);string signature = BitConverter.ToString(HmacSHA256(signKey, signString)).Replace("-", "").ToLower();var url = $"{_schema}://{_host}{_path}?{queryStringBuilder}";url = "https://visual.volcengineapi.com?Action="+action+"&Version=2022-08-31";using (UnityWebRequest webRequest = new UnityWebRequest(url, "POST")){// 设置请求内容webRequest.uploadHandler = (UploadHandler)new UploadHandlerRaw(body);webRequest.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();webRequest.SetRequestHeader("Content-Type", "application/json");webRequest.SetRequestHeader("Host", _host);webRequest.SetRequestHeader("X-Date", xDate);webRequest.SetRequestHeader("X-Content-Sha256", xContentSha256);webRequest.SetRequestHeader("Authorization",$"HMAC-SHA256 Credential={_ak}/{credentialScope}, SignedHeaders={signHeader}, Signature={signature}");yield return webRequest.SendWebRequest();if (webRequest.result != UnityWebRequest.Result.ConnectionError || webRequest.result != UnityWebRequest.Result.ProtocolError){try{string responseText = webRequest.downloadHandler.text;Debug.Log(responseText);// result = JsonConvert.DeserializeObject<JMVideoResult>(responseText);}catch (Exception ex){Debug.Log($"发送失败:{ex.Message}");}}else{//失败提示处理}webRequest.Dispose();}}//public void Base64ToSave(string base64, Action<Bitmap> action)//{// try// {// string imgPath = $"{Application.dataPath}\\saveImg\\" + "XXX.png";// string imgeName = DateTime.Now.ToString("hh_mm_ss") + ".png";// byte[] bytes = Convert.FromBase64String(base64);// using (MemoryStream mStream = new MemoryStream(bytes))// {// System.Drawing.Image mImage = System.Drawing.Image.FromStream(mStream);// Bitmap bmp = new Bitmap(mImage);// bmp.Save(imgPath, System.Drawing.Imaging.ImageFormat.Png);// action((Bitmap)bmp.Clone());// bmp.Dispose();// mImage.Dispose();// }// }// catch (Exception ex)// {// Debug.Log($"保存图片出现异常:{ex.Message}");// }//}private string UrlEncode(string source){if (string.IsNullOrEmpty(source)){return source;}var encoded = new StringBuilder(source.Length);foreach (var symbol in Encoding.UTF8.GetBytes(source)){if (symbol >= 97 && symbol <= 122 || symbol >= 65 && symbol <= 90 || symbol >= 48 && symbol <= 57 ||symbol == (byte)'-' || symbol == (byte)'_' || symbol == (byte)'.' || symbol == (byte)'~'){encoded.Append((char)symbol);}else if (symbol == 32){encoded.Append("%20");}else{encoded.Append('%');encoded.Append(HexDigits[symbol >> 4]);encoded.Append(HexDigits[symbol & 15]);}}return encoded.ToString();}public static string HashSHA256(byte[] content){using (SHA256 sha256 = SHA256.Create()){byte[] hash = sha256.ComputeHash(content);return BitConverter.ToString(hash).Replace("-", "").ToLower();}}public static byte[] HmacSHA256(byte[] key, string content){using (HMACSHA256 hmac = new HMACSHA256(key)){return hmac.ComputeHash(Encoding.UTF8.GetBytes(content));}}private byte[] GenSigningSecretKeyV4(string secretKey, string date, string region, string service){byte[] kDate = HmacSHA256(Encoding.UTF8.GetBytes(secretKey), date);byte[] kRegion = HmacSHA256(kDate, region);byte[] kService = HmacSHA256(kRegion, service);return HmacSHA256(kService, "request");}
}