首页 新闻 会员 周边

工行在线支付接口问题

0
[已解决问题] 解决于 2013-09-02 21:02

做工行查询接口的时候在本地没有问题,发布到服务器上之后一直报错系统找不到指定的文件,而服务器上证书文件是存在的,是怎么回事,有做过的吗求帮助?代码如下:

我排查过在执行 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";
            }
        }
View Code
   /// <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;
            }
        }
View Code
    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;
        }
View Code
放羊娃的主页 放羊娃 | 菜鸟二级 | 园豆:318
提问于:2013-09-02 10:36
< >
分享
最佳答案
0

cert_path 不对,或者没有访问 cert_path 的权限。

奖励园豆:5
Launcher | 高人七级 |园豆:45045 | 2013-09-02 10:45

返回1.0:在服务器上程序执行的时候cert_path 取到的值如下:D:\web\OnlineTraining\ICBCcert\zzjy001.pfx 在这个路径下面可以找到这个证书。权限应该分配什么权限呢?

放羊娃 | 园豆:318 (菜鸟二级) | 2013-09-02 10:57

@放羊娃: 读权限。

Launcher | 园豆:45045 (高人七级) | 2013-09-02 11:06

@Launcher: 

我已经分配了完全控制的权限了

放羊娃 | 园豆:318 (菜鸟二级) | 2013-09-02 11:23

@放羊娃: 你的网站是以 Network service 运行的吗?

你可以通过在 ICBCert 新建一个文件或修改一个文件,来验证你的设置是否成功。

Launcher | 园豆:45045 (高人七级) | 2013-09-02 11:24

@Launcher: 奇怪的是,我在我本地测试的没有问题,vs上跑起来后查询订单时并没有抛这个异常。

放羊娃 | 园豆:318 (菜鸟二级) | 2013-09-02 11:26

@放羊娃: 完全控制的权限授给Users试试

dudu | 园豆:30994 (高人七级) | 2013-09-02 11:26

@放羊娃: 一点都不奇怪,你是在VS的环境下运行的,你把VS装到服务器上,你会发现你在服务器上用VS运行也不会有问题;如果你在本地的时候把网站部署到你的本地IIS运行,你就会发现问题。

Launcher | 园豆:45045 (高人七级) | 2013-09-02 11:28

@Launcher: USER 给了完全控制权限后还是同样的问题,在 ICBCert 文件夹下面建过文件了具有读写权限。

放羊娃 | 园豆:318 (菜鸟二级) | 2013-09-02 11:41

@放羊娃: 你的 cert_path 可能有问题,建议你建立一个简单的 aspx 页面,此页面输出 cert_path 的值,并调用 X509Certificate2 cert = new X509Certificate2(cert_path, cert_password)); 方法。

Launcher | 园豆:45045 (高人七级) | 2013-09-02 11:47

@Launcher: 新建一个页面调用这个方法的时候报错,错误信息如下

是证书的问题吗?

放羊娃 | 园豆:318 (菜鸟二级) | 2013-09-02 12:13

@放羊娃: try catch 住,然后把 cert_path 输出到页面。

Launcher | 园豆:45045 (高人七级) | 2013-09-02 13:15

@Launcher: 

 try
            {
                X509Certificate2 cert = new X509Certificate2(cert_path, "12345678");
            }
            catch
            {
                Response.Write(cert_path);
            }

输出D:\web\OnlineTraining\ICBCcert\zzjy001.pfx 

放羊娃 | 园豆:318 (菜鸟二级) | 2013-09-02 13:58
 try
            {
                X509Certificate2 cert = new X509Certificate2(cert_path, "12345678");
            }
            catch
            {
            }
            Response.Write(cert_path);

这样也输出了证书文件地址D:\web\OnlineTraining\ICBCcert\zzjy001.pfx ,路径应该没什么问题啊

@Launcher: 

放羊娃 | 园豆:318 (菜鸟二级) | 2013-09-02 14:03

@放羊娃: 也就是说路径是对的,而且文件的确存在,是吧。那么你把 X509Certificate2 换成

FileStream fs = new FileStream(cert_path,FileMode.Open, FileAccess.Read); 试试。

Launcher | 园豆:45045 (高人七级) | 2013-09-02 14:03

@Launcher: 

 try
            {
                FileStream fs = new FileStream(cert_path, FileMode.Open, FileAccess.Read); 
            }
            catch
            {
            }
            Response.Write(cert_path);

正常输出了证书所在路径

放羊娃 | 园豆:318 (菜鸟二级) | 2013-09-02 14:14

@放羊娃: 我测试了下,打开证书的话,没有问题,也不用特别的给予权限。如果是权限问题,错误描述会和访问有关。而你的提示是找不到文件,那么错误只能是 D:\web\OnlineTraining\ICBCcert 目录下没有名称为 zzjy001.pfx 的文件,也就是说路径肯定是对的,因为如果路径不存在的话会告诉你目录找不到,而不是文件找不到。你把证书换个目录试试。

Launcher | 园豆:45045 (高人七级) | 2013-09-02 14:44

@Launcher: 问题解决了,把原来的X509Certificate2 cert = new X509Certificate2(cert_path, "12345678");加了一个参数改为:X509Certificate2 cert=  new X509Certificate2(cert_path, cert_password, X509KeyStorageFlags.MachineKeySet)测试通过。坑了我整整两天了,.net的报错真的是不知所云,不过终于解决了,谢谢大哥帮忙,小弟终于要下班回家了。

放羊娃 | 园豆:318 (菜鸟二级) | 2013-09-02 21:02

@放羊娃: 的确是很隐晦的错误,在此方法中 X509KeyStorageFlags 的默认值是 DefaultKeySet ,加载时,会要求保存与 PFX 文件关联的密钥,但是又没指定密钥存储。我猜想在 Windows 7 和 Windows 8 上对 DefaultKeySet 的解释可能不相同。

Launcher | 园豆:45045 (高人七级) | 2013-09-03 09:23
其他回答(5)
0
dudu | 园豆:30994 (高人七级) | 2013-09-02 10:58

这个只有支付接口例子,我的支付接口已经做完了没有问题,在做查询接口的时候遇到了如上问题,windows server2012 的服务器,奇怪的是我在本地电脑上运行的时候并没有抛异常,会不会是权限的问题呢,可是我已经给了完全控制的权限

支持(0) 反对(0) 放羊娃 | 园豆:318 (菜鸟二级) | 2013-09-02 11:21
0

        不错..  留个记号,以后可能用的到 ~

悟动人生 | 园豆:202 (菜鸟二级) | 2013-10-29 17:50
0

佳付通专业卡类消耗通道,API接口对接,回收各类充值卡,通讯卡,游戏卡,人工寄售,接口对接
高比例,抗投诉,秒结算,长期稳定!
QQ:1090603892
网址:www.lcardy.com 联系电话:0898-65637899

佳付通 | 园豆:210 (菜鸟二级) | 2014-05-19 15:36
0

请问下博主,cert_path的值是什么

波霸38 | 园豆:205 (菜鸟二级) | 2016-10-24 08:44
0

    博主,能回复说下你是怎么组件注册成功的么?

artz.r.linh | 园豆:202 (菜鸟二级) | 2018-01-23 09:41
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册