做工行查询接口的时候在本地没有问题,发布到服务器上之后一直报错系统找不到指定的文件,而服务器上证书文件是存在的,是怎么回事,有做过的吗求帮助?代码如下:
我排查过在执行 httpRequest.ClientCertificates.Add(new X509Certificate2(cert_path, cert_password));这一句代码的时候抛异常了,“系统找不到指定的文件“,但是证书文件我已经上产到服务器上了。
/// <summary> /// 查询订单 /// </summary> /// <param name="strOrderNum">订单号</param> /// <param name="strTranDate">交易日期</param> /// <param name="strShopCode">商家代码</param> /// <param name="strShopAccount">商城账号</param> /// <param name="errInfo"></param> /// <returns></returns> public static string CheckOrder(string strOrderNum, string strTranDate, string strShopCode, string strShopAccount, out string errInfo) { try { errInfo = string.Empty; StringBuilder sb = new StringBuilder(); sb.Append("<?xml version=\"1.0\" encoding=\"GBK\" standalone=\"no\" ?><ICBCAPI><in><orderNum>"); sb.Append(strOrderNum); sb.Append("</orderNum><tranDate>"); sb.Append(strTranDate); sb.Append("</tranDate><ShopCode>"); sb.Append(strShopCode); sb.Append("</ShopCode><ShopAccount>"); sb.Append(strShopAccount); sb.Append("</ShopAccount></in></ICBCAPI>"); string post_data = post_params + sb.ToString(); string retruenstring = PostDataBySSL(post_data, api_url, cert_path, strKey, out errInfo); //var result = SpringFactory.BusinessFactory.GetBusinessAnonymousUser(); //result.AddLogs("返回3:" + (retruenstring.Length > 400 ? retruenstring.Substring(0, 400) : retruenstring)); if (retruenstring.Length <= 5) { return retruenstring; } return HttpUtility.UrlDecode(retruenstring); } catch (Exception ex) { var result = SpringFactory.BusinessFactory.GetBusinessAnonymousUser(); result.AddLogs("返回1:" + "查询缴费接口失败" + ex.Message); errInfo = "查询缴费接口失败"; return "99"; } }
/// <summary> /// 发送SSL加密请求 /// </summary> /// <param name="post_data"></param> /// <param name="url"></param> /// <param name="cert_path"></param> /// <param name="cert_password"></param> /// <param name="errInfo"></param> /// <returns></returns> public static string PostDataBySSL(string post_data, string url, string cert_path, string cert_password, out string errInfo) { errInfo = string.Empty; try { ASCIIEncoding encoding = new ASCIIEncoding(); byte[] data = encoding.GetBytes(post_data); if (cert_path != string.Empty) { //验证证书,默认有效 ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate); } //获取结果 WebRequest webRequest = WebRequest.Create(url); //配置请求参数 HttpWebRequest httpRequest = webRequest as HttpWebRequest; if (cert_path.ToLower().EndsWith(".cer")) { httpRequest.ClientCertificates.Add(X509Certificate.CreateFromCertFile(cert_path)); } else { var s = new X509Certificate2(cert_path, cert_password); httpRequest.ClientCertificates.Add(s); //httpRequest.ClientCertificates.Add(new X509Certificate2(cert_path, cert_password)); //X509Store store = new X509Store("My", StoreLocation.LocalMachine); //store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); //System.Security.Cryptography.X509Certificates.X509Certificate2 cert = // store.Certificates.Find(X509FindType.FindBySubjectName, "zzjy001.e.3002", false)[0]; } //获取或设置一个值,该值指示是否与 Internet 资源建立持久性连接。 httpRequest.KeepAlive = true; //获取或设置 User-agentHTTP 标头的值。 httpRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)"; httpRequest.ContentType = "application/x-www-form-urlencoded"; httpRequest.Method = "POST"; // 发送 POST 的 BODY数据 要发送到 Internet 资源的数据的字节数 httpRequest.ContentLength = data.Length; Stream requestStream = httpRequest.GetRequestStream(); //获取用于写入请求数据的 Stream 对象 requestStream.Write(data, 0, data.Length); //发送带有 HttpWebRequest 的数据 requestStream.Close(); Stream responseStream = null; //从 Internet 资源返回数据流 // 获取HTTPs的响应 responseStream = httpRequest.GetResponse().GetResponseStream(); string stringResponse = string.Empty; if (responseStream != null) { using (StreamReader responseReader = new StreamReader(responseStream, Encoding.GetEncoding("GBK"))) { stringResponse = responseReader.ReadToEnd(); } responseStream.Close(); } return stringResponse; } catch (Exception e) { errInfo = e.Message; var result = SpringFactory.BusinessFactory.GetBusinessAnonymousUser(); result.AddLogs("返回2:" + e.Message); return string.Empty; } }
public static bool ValidateServerCertificate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors) { return true; }
cert_path 不对,或者没有访问 cert_path 的权限。
返回1.0:在服务器上程序执行的时候cert_path 取到的值如下:D:\web\OnlineTraining\ICBCcert\zzjy001.pfx 在这个路径下面可以找到这个证书。权限应该分配什么权限呢?
@放羊娃: 读权限。
@Launcher:
我已经分配了完全控制的权限了
@放羊娃: 你的网站是以 Network service 运行的吗?
你可以通过在 ICBCert 新建一个文件或修改一个文件,来验证你的设置是否成功。
@Launcher: 奇怪的是,我在我本地测试的没有问题,vs上跑起来后查询订单时并没有抛这个异常。
@放羊娃: 完全控制的权限授给Users试试
@放羊娃: 一点都不奇怪,你是在VS的环境下运行的,你把VS装到服务器上,你会发现你在服务器上用VS运行也不会有问题;如果你在本地的时候把网站部署到你的本地IIS运行,你就会发现问题。
@Launcher: USER 给了完全控制权限后还是同样的问题,在 ICBCert 文件夹下面建过文件了具有读写权限。
@放羊娃: 你的 cert_path 可能有问题,建议你建立一个简单的 aspx 页面,此页面输出 cert_path 的值,并调用 X509Certificate2 cert = new X509Certificate2(cert_path, cert_password)); 方法。
@Launcher: 新建一个页面调用这个方法的时候报错,错误信息如下
是证书的问题吗?
@放羊娃: try catch 住,然后把 cert_path 输出到页面。
@Launcher:
try { X509Certificate2 cert = new X509Certificate2(cert_path, "12345678"); } catch { Response.Write(cert_path); }
输出D:\web\OnlineTraining\ICBCcert\zzjy001.pfx
try { X509Certificate2 cert = new X509Certificate2(cert_path, "12345678"); } catch { } Response.Write(cert_path);
这样也输出了证书文件地址D:\web\OnlineTraining\ICBCcert\zzjy001.pfx ,路径应该没什么问题啊
@Launcher:
@放羊娃: 也就是说路径是对的,而且文件的确存在,是吧。那么你把 X509Certificate2 换成
FileStream fs = new FileStream(cert_path,FileMode.Open, FileAccess.Read); 试试。
@Launcher:
try { FileStream fs = new FileStream(cert_path, FileMode.Open, FileAccess.Read); } catch { } Response.Write(cert_path);
正常输出了证书所在路径
@放羊娃: 我测试了下,打开证书的话,没有问题,也不用特别的给予权限。如果是权限问题,错误描述会和访问有关。而你的提示是找不到文件,那么错误只能是 D:\web\OnlineTraining\ICBCcert 目录下没有名称为 zzjy001.pfx 的文件,也就是说路径肯定是对的,因为如果路径不存在的话会告诉你目录找不到,而不是文件找不到。你把证书换个目录试试。
@Launcher: 问题解决了,把原来的X509Certificate2 cert = new X509Certificate2(cert_path, "12345678");加了一个参数改为:X509Certificate2 cert= new X509Certificate2(cert_path, cert_password, X509KeyStorageFlags.MachineKeySet)测试通过。坑了我整整两天了,.net的报错真的是不知所云,不过终于解决了,谢谢大哥帮忙,小弟终于要下班回家了。
@放羊娃: 的确是很隐晦的错误,在此方法中 X509KeyStorageFlags 的默认值是 DefaultKeySet ,加载时,会要求保存与 PFX 文件关联的密钥,但是又没指定密钥存储。我猜想在 Windows 7 和 Windows 8 上对 DefaultKeySet 的解释可能不相同。
这个只有支付接口例子,我的支付接口已经做完了没有问题,在做查询接口的时候遇到了如上问题,windows server2012 的服务器,奇怪的是我在本地电脑上运行的时候并没有抛异常,会不会是权限的问题呢,可是我已经给了完全控制的权限
不错.. 留个记号,以后可能用的到 ~
佳付通专业卡类消耗通道,API接口对接,回收各类充值卡,通讯卡,游戏卡,人工寄售,接口对接
高比例,抗投诉,秒结算,长期稳定!
QQ:1090603892
网址:www.lcardy.com 联系电话:0898-65637899
请问下博主,cert_path的值是什么
博主,能回复说下你是怎么组件注册成功的么?