最近项目有用到腾讯云的身份识别接口,话不多说,直接上代码:
1 private void IDCardVerification(HttpContext context) 2 { 3 4 string imgStr = context.Request["ImageBase64"]; 5 if (!string.IsNullOrEmpty(imgStr)) 6 { 7 try 8 { 9 //请求地址 10 string settingUrl = ConfigurationManager.AppSettings.Get("IDCardVerifUrl"); 11 //应用ID 12 string secretId = ConfigurationManager.AppSettings.Get("TcCloudSecretId"); 13 //应用key 14 string secretKey = ConfigurationManager.AppSettings.Get("TcCloudSecretKey"); 15 //时间戳 16 string timesTamp = GetTimeStamp(); 17 //Nonce 18 var nonce = new Random().Next(10000, 99999); 19 //拼接参数 20 string paramsStr = string.Format(@"Action=IDCardOCR&CardSide=FRONT&ImageBase64={0}&Nonce={1}&Region=ap-guangzhou&SecretId={2}&SignatureMethod=HmacSHA1&Timestamp={3}&Version=2018-11-19", 21 imgStr, nonce, secretId, timesTamp); 22 //生成签名参数 23 string requestText = "POST" + settingUrl.Replace("https://", "") + "?" + paramsStr; 24 //获得请求签名 25 string signText = GetHmacSha1Sign(secretKey, requestText); 26 //这里一定要进行URL编码,不然调用API会报错 27 signText = HttpUtility.UrlEncode(signText, Encoding.UTF8); 28 imgStr = HttpUtility.UrlEncode(imgStr, Encoding.UTF8); 29 paramsStr = string.Format(@"Action=IDCardOCR&CardSide=FRONT&ImageBase64={0}&Nonce={1}&Region=ap-guangzhou&SecretId={2}&Signature={3}&SignatureMethod=HmacSHA1&Timestamp={4}&Version=2018-11-19", 30 imgStr, nonce, secretId, signText, timesTamp); 31 //请求腾讯API,返回身份证信息 32 string resultStr = Globals.SendRequest(settingUrl, paramsStr); 33 var idCard = new JavaScriptSerializer().Deserialize<IDCardVerif>(resultStr); 34 var iDCardInfo = idCard.Response; 35 if (iDCardInfo.Error != null) 36 { 37 context.Response.Write("{\"Status\":\"fail\",\"errorMsg\":\"身份证识别出错: " + iDCardInfo.Error.Message + " \"}"); 38 } 39 else 40 { 41 var result = new { Status = "success", data = new { iDCardInfo.name, iDCardInfo.Sex, iDCardInfo.Nation, iDCardInfo.IdNum, iDCardInfo.Address, iDCardInfo.Birth } }; 42 context.Response.Write(new JavaScriptSerializer().Serialize(result)); 43 } 44 } 45 catch (Exception ex) 46 { 47 context.Response.Write("{\"Status\":\"fail\",\"errorMsg\":\"请求接口出错 \"}"); 48 } 49 } 50 else 51 { 52 context.Response.Write("{\"Status\":\"fail\",\"errorMsg\":\"请选择上传的图片!\"}"); 53 } 54 55 56 } 57 58 59 /// <summary> 60 /// 获取时间戳 61 /// </summary> 62 /// <returns></returns> 63 public static string GetTimeStamp() 64 { 65 TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); 66 return Convert.ToInt64(ts.TotalSeconds).ToString(); 67 } 68 69 /// <summary> 70 /// HMAC-SHA1加密返回签名 71 /// </summary> 72 /// <param name="secret">密钥</param> 73 /// <param name="strOrgData">源文</param> 74 /// <returns></returns> 75 public static string GetHmacSha1Sign(string secret, string strOrgData) 76 { 77 var hmacsha1 = new HMACSHA1(Encoding.UTF8.GetBytes(secret)); 78 var dataBuffer = Encoding.UTF8.GetBytes(strOrgData); 79 var hashBytes = hmacsha1.ComputeHash(dataBuffer); 80 return Convert.ToBase64String(hashBytes); 81 } 82 83 public static string SendRequest(string url, string completeUrl) 84 { 85 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 86 request.Method = "POST"; 87 request.ContentType = "application/x-www-form-urlencoded"; 88 request.ProtocolVersion = HttpVersion.Version10; 89 request.Host = url.Replace("https://", "").Replace("/", ""); 90 byte[] data = Encoding.UTF8.GetBytes(completeUrl); 91 request.ContentLength = data.Length; 92 Stream newStream = request.GetRequestStream(); 93 newStream.Write(data, 0, data.Length); 94 newStream.Close(); 95 HttpWebResponse response = null; 96 string content; 97 try 98 { 99 response = (HttpWebResponse)request.GetResponse(); 100 StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8); 101 content = reader.ReadToEnd(); 102 } 103 catch (WebException e) 104 { 105 response = (HttpWebResponse)e.Response; 106 using (Stream errData = response.GetResponseStream()) 107 { 108 using (StreamReader reader = new StreamReader(errData)) 109 { 110 content = reader.ReadToEnd(); 111 } 112 } 113 } 114 return content; 115 }
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Hmeshop.Entities { public class IDCardVerif { public IDCardVerifInfo Response { get; set; } } public class IDCardVerifInfo { /// <summary> /// 姓名 /// </summary> public string name { get; set; } /// <summary> /// 性别 /// </summary> public string Sex { get; set; } /// <summary> /// 民族 /// </summary> public string Nation { get; set; } /// <summary> /// 生日 /// </summary> public string Birth { get; set; } /// <summary> /// 地址 /// </summary> public string Address { get; set; } /// <summary> /// 身份证号 /// </summary> public string IdNum { get; set; } /// <summary> /// 发证机关 /// </summary> public string Authority { get; set; } /// <summary> /// 证件有效期 /// </summary> public string ValidDate { get; set; } /// <summary> /// 扩展信息 /// </summary> public string AdvancedInfo { get; set; } /// <summary> /// 唯一请求 ID,每次请求都会返回。定位问题时需要提供该次请求的 RequestId。 /// </summary> public string RequestId { get; set; } /// <summary> /// 错误信息,有则返回,没有则为空 /// </summary> public ErrorInfo Error { get; set; } } public class ErrorInfo { public string Code { get; set; } public string Message { get; set; } } }
开始的时候,使用了HTTP的POST这种请求方式进行调用,但后面发现这种请求方式有Bug,一旦用户上传的图片尺寸太大(跟图片大小没关系,主要是尺寸),请求腾讯的API就会返回下面这个错误(PS:因为我这边使用的是OCR身份证识别API,如果不涉及图片文件的话,可以使用我上面的调用方式):
根据图上的错误信息可知,需要用到TC3-HMAC-SHA256这个签名算法,So,没办法,我们只能用腾讯的SDK来调用了,SDK直接在VS的Nuget里下载就好了,在GitHub下载源码进行编译引用也行
下面贴腾讯官方SDK调用代码:
1 private void IDCardVerificationBySDK(HttpContext context) 2 { 3 string imgStr = context.Request["ImageBase64"]; 4 try 5 { 6 if (!string.IsNullOrEmpty(imgStr)) 7 { 8 string res = string.Empty; 9 10 Action<string> action = t => 11 { 12 res = GetOCRMsg(imgStr); 13 }; 14 IAsyncResult asyncResult = action.BeginInvoke("调用腾讯云身份证识别", null, null); 15 asyncResult.AsyncWaitHandle.WaitOne(); 16 if (res.Contains("message")) 17 { 18 context.Response.Write("{\"Status\":\"fail\",\"errorMsg\":\"" + res.Split(new string[] { "message:" }, StringSplitOptions.None)[1] + "\"}"); 19 } 20 else 21 { 22 IDCardOCRResponse resp = JsonConvert.DeserializeObject<IDCardOCRResponse>(res); 23 var result = new { Status = "success", data = resp }; 24 context.Response.Write(JsonConvert.SerializeObject(result)); 25 } 26 } 27 else 28 { 29 context.Response.Write("{\"Status\":\"fail\",\"errorMsg\":\"请选择上传的图片!\"}"); 30 } 31 } 32 catch(Exception ex) 33 { 34 Globals.Debuglog("调用接口出错:" + ex.StackTrace, "Tentent_IDCardVerif.txt"); 35 } 36 37 } 38 39 40 private string GetOCRMsg(string imgStr) 41 { 42 try 43 { 44 Credential cred = new Credential 45 { 46 SecretId = ConfigurationManager.AppSettings.Get("TcCloudSecretId"), 47 SecretKey = ConfigurationManager.AppSettings.Get("TcCloudSecretKey") 48 }; 49 50 ClientProfile clientProfile = new ClientProfile 51 { 52 SignMethod = ClientProfile.SIGN_TC3SHA256 53 }; 54 HttpProfile httpProfile = new HttpProfile(); 55 httpProfile.Endpoint = ("ocr.tencentcloudapi.com"); 56 httpProfile.ReqMethod = "POST"; 57 httpProfile.Timeout = 10; // 请求连接超时时间,单位为秒(默认60秒) 58 clientProfile.HttpProfile = httpProfile; 59 OcrClient client = new OcrClient(cred, "ap-guangzhou", clientProfile); 60 IDCardOCRRequest req = new IDCardOCRRequest(); 61 string strParams = "{\"ImageBase64\":\""+ imgStr + "\",\"CardSide\":\"FRONT\",\"ImageUrl\":\"\",\"Config\":\"\"}"; 62 Globals.Debuglog("strParams: " + strParams, "Tentent_IDCardVerif.txt"); 63 req = JsonConvert.DeserializeObject<IDCardOCRRequest>(strParams); 64 IDCardOCRResponse resp = client.IDCardOCR(req). 65 ConfigureAwait(false).GetAwaiter().GetResult(); 66 return AbstractModel.ToJsonString(resp); 67 } 68 catch (Exception e) 69 { 70 Globals.Debuglog("请求接口出错:" + e.StackTrace, "Tentent_IDCardVerif.txt"); 71 return e.Message.ToString(); 72 } 73 } 74
这里要注意的是,一定要使用异步请求的方式进行调用! 不然直接调用的话,执行到:
ConfigureAwait(false).GetAwaiter().GetResult();
这一步会没有任何响应,程序陷入假死状态,博主就是在这里踩了坑,尝试了多次才发现这个问题,真是坑爹啊- -!
好了,就先说到这里了,这是本人在博客园的处女blog,希望给各位有需要的人一点帮助哈~