.NET调用腾讯云API实例
程序员文章站
2022-06-20 23:11:19
最近项目有用到腾讯云的身份识别接口,话不多说,直接上代码: 开始的时候,使用了HTTP的POST这种请求方式进行调用,但后面发现这种请求方式有Bug,一旦用户上传的图片尺寸太大(跟图片大小没关系,主要是尺寸),请求腾讯的API就会返回下面这个错误(PS:因为我这边使用的是OCR身份证识别API,如果 ......
最近项目有用到腾讯云的身份识别接口,话不多说,直接上代码:
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}®ion=ap-guangzhou&secretid={2}&signaturemethod=hmacsha1×tamp={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}®ion=ap-guangzhou&secretid={2}&signature={3}&signaturemethod=hmacsha1×tamp={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();
这一步会没有任何响应,程序陷入假死状态,博主就是在这里踩了坑,尝试了多次才发现这个问题,真是坑爹啊- -!
上一篇: 莲子桂圆红枣汤怎么做呢