最近特殊的需求,要把微信平台一个功能页面部署到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)[];
//遍历证书查看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: 0xffffffff800b0109
at Mono.Security.Protocol.Tls.RecordProtocol.EndReceiveRecord (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,默认下载文件无效,这不得不说是个坑。

C#在Linux+Mono环境中使用微信支付证书的更多相关文章

  1. 在Web应用中接入微信支付的流程之极简清晰版

    在Web应用中接入微信支付的流程之极简清晰版 背景: 在Web应用中接入微信支付,我以为只是调用几个API稍作调试即可. 没想到微信的API和官方文档里隐坑无数,致我抱着怀疑人生的心情悲愤踩遍了丫们布 ...

  2. 在Web应用中接入微信支付的流程之极简清晰版 (转)

    在Web应用中接入微信支付的流程之极简清晰版 背景: 在Web应用中接入微信支付,我以为只是调用几个API稍作调试即可. 没想到微信的API和官方文档里隐坑无数,致我抱着怀疑人生的心情悲愤踩遍了丫们布 ...

  3. ThinkPHP中实现微信支付(jsapi支付)流程

    https://blog.csdn.net/sinat_35861727/article/details/72783988 之前写过一篇文章讲了 PHP实现微信支付(jsapi支付)流程 ,详见文章: ...

  4. Spring Boot中的微信支付(小程序)

    前言 微信支付是企业级项目中经常使用到的功能,作为后端开发人员,完整地掌握该技术是十分有必要的. logo 一.申请流程和步骤 图1-1 注册微信支付账号 获取微信小程序APPID 获取微信商家的商户 ...

  5. Ecstore中的微信支付怎么样配置

    要在Ecstore中开启微信支付,需要先在后台/应用中心中安装“移动商城”和“微信商城管理”这两个App移动商城App是ecstore的手机wap版,可在手机浏览器中实现商城的B2c购物功能.“微信商 ...

  6. 微信小程序中实现微信支付

    最近在做微信小程序,今天刚好做到小程序里的微信支付这块,踩过不少坑,特此写个博客记录下,希望能帮到其它人吧. 我总结了一下,小程序中的微信支付和之前其它的公众号里的微信支付有两个区别,第一就是小程序必 ...

  7. Java中的微信支付(2):API V3 微信平台证书的获取与刷新

    1. 前言 在Java中的微信支付(1):API V3版本签名详解一文中胖哥讲解了微信支付V3版本API的签名,当我方(你自己的服务器)请求微信支付服务器时需要根据我方的API证书对参数进行加签,微信 ...

  8. .Net程序在linux mono环境和WindowsServer上执行测试对比

    最近研究了一下mono,想把windows上写的.Net程序移植到linux上跑.网上有资料说Linux上mono执行.Net程序效率比Windows高,本着实证的态度,只有实际验证过才有说服力. 写 ...

  9. Neutron VxLAN + Linux Bridge 环境中的网络 MTU

    1. 基础知识 1.1 MTU   一个网络接口的 MTU 是它一次所能传输的最大数据块的大小.任何超过MTU的数据块都会在传输前分成小的传输单元.MTU 有两个测量层次:网络层和链路层.比如,网络层 ...

随机推荐

  1. bzoj4237 稻草人

    我是萌萌的传送门 题意不难理解吧-- 一开始看到这道题的时候lrd告诉我这题要分治,还给我讲了讲分治要怎么写,好像是CDQ+树状数组来着--(好吧我已经忘了--)然而我第一眼看完题之后的思路是数据结构 ...

  2. Java对象的深拷贝和浅拷贝、集合的交集并集

    http://blog.csdn.net/lian_1988/article/details/45970927 http://www.cnblogs.com/yxnchinahlj/archive/2 ...

  3. ffmpeg-20161003[04,05.06]-bin.7z

    ESC 退出 0 进度条开关 1 屏幕原始大小 2 屏幕1/2大小 3 屏幕1/3大小 4 屏幕1/4大小 5 屏幕横向放大 20 像素 6 屏幕横向缩小 20 像素 S 下一帧 [ -2秒 ] +2 ...

  4. SQL Server删除重复行的6个方法

    SQL Server删除重复行是我们最常见的操作之一,下面就为您介绍六种适合不同情况的SQL Server删除重复行的方法,供您参考. 1.如果有ID字段,就是具有唯一性的字段 delect   ta ...

  5. Clang与libc++abi库安装

    系统ubuntu64位 Clang4.0 参考: 1 https://github.com/yangyangwithgnu/use_vim_as_ide#0.1 其中 第7章 工具链集成 2. htt ...

  6. Ext.js细节:在MVC中处理Widget Column,GetCmp和ComponentQuery, Id和ItemId

    针对EXT.JS版本的演进,要不断的学习新的最佳实践方法. 比如,在定义组件时,尽管用itemid,而不是id. 在搜索组件时,尽量用ComponentQuery,而不是getCmp. 在MVC中处理 ...

  7. Dump类型说明

    通过使用windbg提供DbgHelp库中的MiniDumpWriteDump函数在程序崩溃时写dump文件记录程序当时状态,为后续分析问题提供现场. 该函数提供了DumpType参数,让程序员根据具 ...

  8. 前端试题本(HTML+CSS篇)

    CS1. 下面关于IE.FF下面CSS的解释区别描述正确的有?(不定项)CS2请选出结构正确的选项CS3.下面哪些是HTML5 新增的表单元素?CS4在使用table表现数据时,有时候表现出来的会比自 ...

  9. maven权威指南学习笔记(二)——安装、运行、获取帮助

    这部分在网上很容易找到详细教程,这里就略写了. 基础:系统有配置好的jdk,通过 命令行 java -version,有类似下面的提示,表示java环境以配好 下载maven:官网 http://ma ...

  10. 两个select 左右添加,上下移动

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...