C#在Linux+Mono环境中使用微信支付证书

最近特殊的需求,要把微信平台一个功能页面部署到Linux(CentOS6.5)下,其中涉及到微信支付退款。

鉴于之前实践过mono+jexus+asp.net mvc的部署,于是问题重点在于解决对商户证书的调用问题。

 

查看微信支付官方文档关于证书的使用说明

  • ◆ apiclient_cert.p12是商户证书文件,除PHP外的开发均使用此证书文件。

  • ◆ 商户如果使用.NET环境开发,请确认Framework版本大于2.0,必须在操作系统上双击安装证书apiclient_cert.p12后才能被正常调用。

  • ◆ 商户证书调用或安装都需要使用到密码,该密码的值为微信商户号(mch_id)

  • ◆ PHP开发环境请使用商户证书文件apiclient_cert.pem和apiclient_key.pem ,rootca.pem是CA证书。

 

1.使用mono自带工具certmgr导入.p12证书

certmgr -add -c -m -p 密码 My ApiClient_cert.p12

2.编写测试程序

using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

public class TlsTest {
public static void Main(string[] args){HttpWebResponse webreponse; string strHtml = "NO";
try{ //系统必须已经导入cert指向的证书string url =
"https://api.mch.weixin.qq.com/secapi/pay/refund";
//My即对应”个人“存储区,固定不可改变X509Store store = new X509Store("My",
StoreLocation.LocalMachine);store.Open(OpenFlags.ReadOnly|OpenFlags.OpenExistingOnly);X509Certificate cer = store.Certificates.Find(
X509FindType.FindByThumbprint,
"546FCAA50DB599C5439AC8139C69393D5DB243D0", false)[0]; //遍历证书查看Hash;windows下可直接双击安装,查看属性            //Console.WriteLine(store.Certificates.Count);            //foreach(var c in store.Certificates){            // //Console.WriteLine("{0},{1},{2},{3},{4},{5}", c.GetCertHashString(), c.FriendlyName, c.GetFormat(), c.IssuerName, c.SubjectName, c.Thumbprint);            //    if (c.GetCertHashString() == "546FCAA50DB599C5439AC8139C69393D5DB243D0")            //    {            //        Console.WriteLine("found");            //        cer = c;            //        break;            //    }            //}HttpWebRequest webrequest =
(HttpWebRequest)HttpWebRequest.Create(url);webrequest.ClientCertificates.Add(cer);webrequest.Method = "post";webrequest.KeepAlive = true;webreponse = (HttpWebResponse)webrequest.GetResponse();Stream stream = webreponse.GetResponseStream();
string resp = string.Empty;
using (StreamReader reader = new StreamReader(stream)){resp = reader.ReadToEnd();}strHtml = resp;}
catch (Exception exp){strHtml = exp.ToString();}Console.WriteLine(strHtml);} }

3.运行测试程序

mono SSLtest.exe

结果运行报错


System.Net.WebException: Error: TrustFailure (The authentication or 
decryption has failed.) ---> System.IO.IOException:
The authentication or decryption has failed. --->
System.IO.IOException: The authentication or decryption has failed.
---> Mono.Security.Protocol.Tls.TlsException: Invalid certificate
received from server. Error code: 0xffffffff800b0109at Mono.Security.Protocol.Tls.RecordProtocol.EndReceiveRecor
(IAsyncResult asyncResult) <0x40713980 + 0x0013e>
in <filename unknown>:0 at Mono.Security.Protocol.Tls.SslClientStream.SafeEndReceiveRecord
(IAsyncResult ar, Boolean ignoreEmpty) <0x407138b0 + 0x00031> in
<filename unknown>:0 at Mono.Security.Protocol.Tls.SslClientStream.NegotiateAsyncWorker
(IAsyncResult result) <0x4070d2d0 + 0x0023a>
in <filename unknown>:0 --- End of inner exception stack trace ---at Mono.Security.Protocol.Tls.SslClientStream.EndNegotiateHandshake
(IAsyncResult result) <0x40726300 + 0x000f3>
in <filename unknown>:0 at Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback
(IAsyncResult asyncResult) <0x40726050 + 0x00086>
in <filename unknown>:0
--- End of inner exception stack trace ---at Mono.Security.Protocol.Tls.SslStreamBase.EndRead
(IAsyncResult asyncResult) <0x4070a990 + 0x00199>
in <filename unknown>:0 at Mono.Net.Security.Private.LegacySslStream.EndAuthenticateAsClient
(IAsyncResult asyncResult) <0x4070a8f0 + 0x00042>
in <filename unknown>:0 at Mono.Net.Security.Private.LegacySslStream.AuthenticateAsClient
(System.String targetHost,
System.Security.Cryptography.X509Certificates.
X509CertificateCollection clientCertificates,
SslProtocols enabledSslProtocols,
Boolean checkCertificateRevocation) <0x40704650 + 0x00055>
in <filename unknown>:0 at Mono.Net.Security.MonoTlsStream.CreateStream
(System.Byte[] buffer)
<0x40703e00 + 0x00145> in <filename unknown>:0 --- End of inner exception stack trace ---at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult)
<0x406fcf50 + 0x001ed> in <filename unknown>:0 at System.Net.HttpWebRequest.GetResponse () <0x406f5210 + 0x00053>
in <filename unknown>:0 at TlsTest.Main (System.String[] args) <0x406a7d80 + 0x002c6> in
<filename unknown>:0

 

4.发现错误原因是"Invalid certificate received from server",这个问题在Mono文档中已有说明:

That’s probably because you do not trust the site you are connecting to. Note that a default installation of Mono doesn’t trust anyone!

默认情况下,任何站点都不被Mono信任!

同时也给出了4个解决方案:

  • 使用cert-sync工具同步Mono和系统的证书存储区

  • 程序实现ICertificatePolicy自行决定信任规则

  • 使用certmgr.exe导入受信证书

  • 使用mozroots.exe自动导入常用的可信根证书

 

5.尝试解决方案2

ServicePointManager.ServerCertificateValidationCallback = 
new RemoteCertificateValidationCallback(CheckValidationResult);

private static bool CheckValidationResult(object sender,
X509Certificate c,
X509Chain chain, SslPolicyErrors errors) {
return true; }

报错问题虽然可以解决,但对所有情况均信任不是一个好的解决方法,根据X509Certificate c进行判断理应可行,没有再进一步探索

 

6.尝试解决方案4

使用mozroots自动下载安装常用的根证书

mozroots --import --sync

显示成功导入100+根证书,重新执行测试程序仍然报错。

这个结果一度使我认为此方法无效,但偶然在本地测试却通过了。

 

对比发现生效的下载路径是:

https://hg.mozilla.org/releases/mozilla-release/raw-file/default/
security/nss/lib/ckfw/builtins/certdata.txt

而无效的下载路径是:

http://mxr.mozilla.org/seamonkey/source/security/nss/lib/ckfw/builtins
/certdata.txt?raw=1

于是手动下载文件并指定mozroots安装指定的文件

wget https://hg.mozilla.org/releases/mozilla-release/raw-file/default
/security/nss/lib/ckfw/builtins/certdata.txt
mozroots --import --sync --file certdata.txt

这时,执行测试程序运行正常

<xml><return_code><![CDATA[FAIL]]></return_code>
<return_msg><![CDATA[post数据为空]]></return_msg>
</xml>

 

7.总结

使用mozroots是解决问题的简单方法,但由于mono版本问题会导致默认的下载文件并不有效。本地有效版本:mono 4.6.0.0,使用中已提示建议使用cert-sync [WARNING: mozroots is deprecated, please move to cert-sync instead.]

服务器版本:mono 4.4.1.0,默认下载文件无效,这不得不说是个坑。


原文链接:http://www.cnblogs.com/himax/p/how_to_use_wechat_cert_with_mono.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/328335.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql切换用户sql语句,MySQL用户管理及SQL语句详解

[(none)]>select user,host frommysql.user; #查询用户和主机--------------------------| user | host |--------------------------| root | 10.0.0.% || mysql.session | localhost || mysql.sys | localhost || root | localhost |--------------------------4 rows in …

其他

关于程序员的文章 2014年05月01日 16:58:25 a8511119 阅读数&#xff1a;300 中国有很多小朋友&#xff0c;他们18,9岁或21,2岁&#xff0c;通过自学也写了不少代码&#xff0c;他们有的代码写的很漂亮&#xff0c;一些技术细节相当出众&#xff0c;也很有钻研精神&#xff0…

Java经典面试题一

转载自 Java经典面试题一 题目一 面向对象的特征有哪些方面&#xff1f; 答&#xff1a;面向对象的特征主要有以下几个方面&#xff1a; 1.抽象&#xff1a; 抽象是将一类对象的共同特征总结出来构造类的过程&#xff0c;包括数据抽象和行为抽象两方面。抽象只关注对象有哪些…

微信小程序这么火,到底会对C#开发者带来怎样的改变

在9月22日凌晨&#xff0c;微信公众平台开始陆续对外发出小程序的内测邀请&#xff0c;小程序也立即成为被外界广为关注的微信“应用号"&#xff0c;9月23日的福州 2016腾讯全球合作伙伴大会上&#xff0c;腾讯COO、游戏和无线业务的掌舵人、腾讯首席运营官任宇任宇昕提到…

php js 验证码,js实现验证码的方法

验证码的生命周期在web应用中&#xff0c;验证码常用于登录注册。验证码本质就是一张图片。我们来看一下验证码的生命周期&#xff1a;客户端请求验证码服务端渲染验证码&#xff1a;渲染一张包含随机字符串的图片随机字符串写入session读取图片并返回响应客户端提交&#xff1…

区间数多属性决策matlab,区间数多属性决策的改进理想解法

Interval Multiple Attribute Decision Making Based on the Improved Technique for Order Preference by Similarity to Ideal Solution1、School of Economics and Management, Southwest Jiaotong University2、Deaprtment of Mathematics, North Sichuan Medical CollegeA…

.NET 标准介绍

本文介绍如何使用 .NET 标准&#xff0c;更容易地实现向 .NET Core 迁移。文中会讨论计划包含的 APIs&#xff0c;跨构架兼容性如何工作以及这对 .NET Core 意味着什么。 如果你对细节感兴趣&#xff0c;这篇文章正是为你准备的&#xff1b;如果你没有那么多时间或者对细节并不…

HTTP 返回码详解

转载自 HTTP 返回码详解200 服务器成功返回网页 404 请求的网页不存在 503 服务不可用1xx&#xff08;临时响应&#xff09; 表示临时响应并需要请求者继续执行操作的状态代码。 100&#xff08;继续&#xff09;请求者应当继续提出请求。 服务器返回此代码表示已收到请求…

银行营业网点管理系统——entity类(Branches)

package BranchesMgr.entity; /*** * author Administrator*网点信息表*/ public class Branches {private int id;private String name;private int cityAreatyid;private String cityName;public String getCityName() {return cityName;}public void setCityName(String cit…

自己的php工具,用PHP自己编写的站长工具箱

前沿&#xff1a; 看到站长之家的站长工具很强大&#xff0c;所以也想自己试着实现一些其中的功能&#xff0c;由于本人只具有初阶的php技术&#xff0c;所以便用php一些函数实现了部分功能。主要功能包括&#xff1a;正则表达式测试工具&#xff0c;MD5和SHA1加密工具&#xf…

轻量级的web框架[Nancy On .Net Core Docker]

.net core现在已经有了大的发展&#xff0c;虽然笔者现在已经从事python开发&#xff0c;但是一直在关注.net的发展&#xff0c;在逛博客园的时候&#xff0c;发现有大家都会提到Nancy这个框架&#xff0c;在简单的使用之后&#xff0c;发现竟然是如此的简单而优雅 public cla…

Git使用中的一些奇技淫巧

转载自 Git使用中的一些奇技淫巧Git作为当今最流行的分布式代码版本管理系统&#xff0c;它的出现改变了软件的开发流程&#xff0c;大大地提高了开发流畅度。 本人使用Git也有一段时间了&#xff0c;一直都只是使用一些最最基本的几个命令&#xff0c;对于不复杂的代码工程来…

oracle 更新参数,Oracle动态、静态参数参数修改规则

首先&#xff0c;查看要修改的oracle参数的属性(动态or静态)SQL> select name,value,isses_modifiable,issys_modifiable from V$PARAMETER where namemax_dump_file_size;注&#xff1a;isses_modifiable 为Y&#xff0c;session级别修改的参数&#xff0c;SQL>alter se…

银行营业网点管理系统——entity类(CityArea)

package BranchesMgr.entity; /*** 城区表* author Administrator**/ public class CityArea {private int id;private String name;public int getId() {return id;}public void setId(int id) {this.id id;}public String getName() {return name;}public void setName(Stri…

漫画:如何用Zookeeper实现分布式锁?

转载自 漫画&#xff1a;如何用Zookeeper实现分布式锁&#xff1f;什么是临时顺序节点&#xff1f;让我们来回顾一下Zookeeper节点的概念&#xff1a;Zookeeper的数据存储结构就像一棵树&#xff0c;这棵树由节点组成&#xff0c;这种节点叫做Znode。Znode分为四种类型&#…

使用CoreProfiler/NanoProfiler实现跨平台amp;应用的整合性能调试

NanoProfiler是一个开源.NET性能调试类库&#xff0c;CoreProfiler是其.NET Core版本的实现。在之前的一些文章中&#xff0c;我曾介绍过NanoProfiler的主要使用方式&#xff0c;以及如何为生产环境&#xff0c;基于ELK对应用性能进行调试和监控。不过&#xff0c;对于一般的用…

oracle授权序列,oracle 第二集序列

方案一&#xff1a;直接授权法1.用happyy2165登录&#xff0c;之后&#xff0c;授权grant select on HAPPYY2165.STUDENT to scott2.用scott登录&#xff0c;用如下代码去访问Student表select * from HAPPYY2165.student方式二&#xff1a;通过角色去控制1.自定义角色 role_tes…