zoukankan      html  css  js  c++  java
  • 微信小微商户证书和签名篇

    官网链接
    商户可以通过以下指引入驻成为小微商户:

    • 步骤一:服务商通过申请入驻接口提交你的小微商户入驻申请

    • 步骤二:服务商通过查询申请状态接口查询你的申请结果(建议提交申请后5分钟再进行查询)

    • 步骤三:小微商户本人签署协议(只能本人微信号扫码签约)

    • 提醒:你可能需要的开户银行对照表、省市区编码可前往对照表查看

    根据官网链接的指引,点开申请入驻页面,可以看到需要证书,需要加密,需要签名 所以先从证书相关开始

    1.注册并下载安装证书

    首先进入官网登录下,点击->账户中心->api安全 ,下载API证书,注意:下载之后如果有升级证书按钮直接点击升级,否则后续调用接口会失败 ;下载之后再服务器上安装,密码默认为商户号

    1. 安装完成后设置APIv3密钥和api秘钥,否则调用证书不能成功

    申明:本案例参考博客园前辈(我们的家乡)的文章传送门 ;Github地址 WxPayAPI.dll地址

    签名

    1、签名算法
    (签名校验工具)
    签名生成的通用步骤如下:

    第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。

    特别注意以下重要规则:

    ◆ 参数名ASCII码从小到大排序(字典序);
    ◆ 如果参数的值为空不参与签名;
    ◆ 参数名区分大小写;
    ◆ 验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
    ◆ 微信接口可能增加字段,验证签名时必须支持增加的扩展字段
    第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。

    ◆ key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置

    具体说明查看官网文档

    1. 下载WxPayAPIc#项目,找到WxPayData.cs类,修改CalcHMACSHA256Hash方法
      private  string CalcHMACSHA256Hash(string plaintext, string salt)
            {
               string result = "";
                var enc = Encoding.UTF8; //官网下载为 Encoding.Default,需要修改为UTF8;
                byte[]
                baText2BeHashed = enc.GetBytes(plaintext),
                baSalt = enc.GetBytes(salt);
                System.Security.Cryptography.HMACSHA256 hasher = new HMACSHA256(baSalt);
                byte[] baHashedText = hasher.ComputeHash(baText2BeHashed);
                result = string.Join("", baHashedText.ToList().Select(b => b.ToString("x2")).ToArray()).ToUpper();//这里需要转换为大写 
            }
    
    
    

    模型类

      public  class weixinConfig
        {
            //=======【基本信息设置】=====================================
            /* 微信公众号信息配置
            * APPID:绑定支付的APPID(必须配置)
            * MCHID:商户号(必须配置)
            * KEY:商户支付密钥,参考开户邮件设置(必须配置),请妥善保管,避免密钥泄露
            * APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置),请妥善保管,避免密钥泄露
            */
    
            public static string AppID
            {
                get;set;
            }
    
            public  static string MchID  {  get; set;}
             /// <summary>
            /// api秘钥  支付秘钥
            /// </summary>
            public static string Key { get; set; }
            public static string AppSecret
            {
                get;set;
            }
    
    
    
            //=======【证书路径设置】===================================== 
            /* 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要)
             * 1.证书文件不能放在web服务器虚拟目录,应放在有访问权限控制的目录中,防止被他人下载;
             * 2.建议将证书文件名改为复杂且不容易猜测的文件
             * 3.商户服务器要做好病毒和木马防护工作,不被非法侵入者窃取证书文件。
            */
    
            public static string SSlCertPath { get; set; } 
            public static string DerCertPath { get; set; }
    
            public static string SSlCertPassword
            {
                get; set;
            }
    
            /// <summary>
            /// apiv3秘钥 
            /// </summary>
            /// <value>
            /// The cert key.
            /// </value>
            /// 
            public static string CertKey { get; set; }
    
            /// <summary>
            /// 主要用来平台证书解密成密钥      
            /// </summary>
            /// <value>
            /// The encrypt certificate.
            /// </value>
            public static  encrypt_certificate encrypt_certificate { get; set; }
    
            /// <summary>
            /// 平台证书序列号
            /// </summary>
            /// <value>
            /// The serial no.
            /// </value>
            public static string serial_no { get; set; }
    
    
    
        }
        
          public class data_certificates//: result
        {
            public List<data_certificate> data { get; set; }
        }
    
        public class data_certificate
        {
            public string serial_no { get; set; }
            public string effective_time { get; set; }
            public string expire_time { get; set; }
            public encrypt_certificate encrypt_certificate { get; set; }
    
        }
    
        /// <summary>
        /// 证书相关
        /// </summary>
        public class encrypt_certificate
        {
            public string algorithm { get; set; }
            public string nonce { get; set; } 
            public string associated_data { get; set; } 
            public string ciphertext { get; set; }
        }
    
    

    获取证书序列号

       string url = "https://api.mch.weixin.qq.com/risk/getcertficates";
                    WxPayDataToXiaoWei inputObj = new WxPayDataToXiaoWei();
                    inputObj.SetValue("mch_id", weixinConfig.MchID);
                    inputObj.SetValue("nonce_str", Guid.NewGuid().ToString().Replace("-", ""));
                    inputObj.SetValue("sign_type", "HMAC-SHA256");
                    inputObj.SetValue("sign", inputObj.MakeSign(weixinConfig.Key));
                    var respones = WeixinXiaoweiService.Post(inputObj.ToXml(), url, false, true, 1000);
    
                    try
                    {
                        //获取证书序列号
                        inputObj = new WxPayDataToXiaoWei();
                        inputObj.FromXml(respones);
                        if (inputObj.GetValue("return_code").ToString() == "SUCCESS"
                            && inputObj.GetValue("result_code").ToString() == "SUCCESS")
                        {
                            var certificates = inputObj.GetValue("certificates").ToString();//获取证书信息 
                            var data = JsonConvert.DeserializeObject<dynamic>(certificates);
                            var obj = JsonConvert.DeserializeObject<List<dynamic>>(data.data.ToString());
                            weixinConfig.serial_no = obj[0].serial_no.ToString();//证书序列号
                            weixinConfig.encrypt_certificate = JsonConvert.DeserializeObject<encrypt_certificate>(obj[0].encrypt_certificate.ToString());
                        }
                        return ProtocolManager.GetPackage(PackageReturnCode.OK, "获取成功!");
                    }
                    catch (Exception ex)
                    {
                        LogHelper.Error("获取证书失败:" + ex.ToString());
                        return ProtocolManager.GetPackage(PackageReturnCode.Fail, "获取失败!");
                    }
    
    

    说明: sign签名方法是 inputObj.MakeSign(weixinConfig.Key),//注:key为商户平台设置的密钥key; WeixinXiaoweiService.Post(inputObj.ToXml(), url, false, true, 1000); 这个方法是下载的微信官方Demo中的HttpService类中,下面是修改的

      public static string Post(string body, string url, bool isUseCert,bool isxml, int timeout)
            {
               
                string result = "";//返回结果
                HttpWebRequest request = null;
                HttpWebResponse response = null;
                Stream reqStream = null;
    
                try
                {
                    //设置最大连接数
                    ServicePointManager.DefaultConnectionLimit = 200;
                    //设置https验证方式
                    if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                    {
                        ServicePointManager.ServerCertificateValidationCallback =
                                new RemoteCertificateValidationCallback(CheckValidationResult);
                    }
    
                    /***************************************************************
                    * 下面设置HttpWebRequest的相关属性
                    * ************************************************************/
                    request = (HttpWebRequest)WebRequest.Create(url);
                    request.UserAgent = USER_AGENT;
                    request.Method = "POST";
                    request.Timeout = timeout * 1000;
    
                    //设置代理服务器
                    //WebProxy proxy = new WebProxy();                          //定义一个网关对象
                    //proxy.Address = new Uri(WxPayConfig.PROXY_URL);              //网关服务器端口:端口
                    //request.Proxy = proxy;
    
                    //设置POST的数据类型和长度
                    request.ContentType = isxml? "text/xml": "application/json";
                    byte[] data = System.Text.Encoding.UTF8.GetBytes(body);
                    request.ContentLength = data.Length;
    
                    //是否使用证书
                    if (isUseCert)
                    {
    
    
                      //  X509Certificate2 cert = new X509Certificate2(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"WxXiaoWeiCertapiclient_cert.p12"), weixinConfig.SSlCertPassword);
    
                       X509Certificate2 cert = new X509Certificate2(weixinConfig.SSlCertPath,weixinConfig.SSlCertPassword);
    
    
                        request.ClientCertificates.Add(cert);
                        LogHelper .Debug("WxPayApi", "PostXml used cert");
                    }
    
                    //往服务器写入数据
                    reqStream = request.GetRequestStream();
                    reqStream.Write(data, 0, data.Length);
                    reqStream.Close();
    
                    //获取服务端返回
                    response = (HttpWebResponse)request.GetResponse();
    
                    //获取服务端返回数据
                    StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
                    result = sr.ReadToEnd().Trim();
                    sr.Close();
                }
                catch (System.Threading.ThreadAbortException e)
                {
                    LogHelper.Error("HttpService", "Thread - caught ThreadAbortException - resetting.");
                    LogHelper.Error("Exception message: {0}", e.Message);
                    System.Threading.Thread.ResetAbort();
                }
                catch (WebException e)
                {
                    LogHelper.Error("HttpService", e.ToString());
                    if (e.Status == WebExceptionStatus.ProtocolError)
                    {
                        LogHelper.Error("HttpService", "StatusCode : " + ((HttpWebResponse)e.Response).StatusCode);
                        LogHelper.Error("HttpService", "StatusDescription : " + ((HttpWebResponse)e.Response).StatusDescription);
                    }
                    throw new Exception(e.ToString());
                }
                catch (Exception e)
                {
                    LogHelper.Error("HttpService", e.ToString());
                    throw new Exception(e.ToString());
                }
                finally
                {
                    //关闭连接和流
                    if (response != null)
                    {
                        response.Close();
                    }
                    if (request != null)
                    {
                        request.Abort();
                    }
                }
                return result;
            }
    
  • 相关阅读:
    Solr 6.7学习笔记(02)-- 配置文件 managed-schema (schema.xml)
    Solr 6.7学习笔记(02)-- 配置文件 managed-schema (schema.xml)
    Solr 6.7学习笔记(03)-- 样例配置文件 solrconfig.xml
    《深入理解Java虚拟机》笔记04 -- 并发锁
    6.Python3标准库--数学运算
    7.Python3标准库--文件系统
    8.Python3标准库--数据持久存储与交换
    9.Python3标准库--数据压缩与归档
    10.python3标准库--加密
    11.python3标准库--使用进程、线程和协程提供并发性
  • 原文地址:https://www.cnblogs.com/HiLzd/p/10444757.html
Copyright © 2011-2022 走看看