Example: Use C#.NET to teach you how to develop WeChat public account (18) -- use WeChat payment to send red envelopes to fans

Everything mentioned above does not involve money. Once it is related to money, it is very sensitive, so the process of opening WeChat payment and the configuration process are relatively cumbersome. This article gives the main entry. Due to the length of the article, it is not too detailed. , but it is enough to help you solve the problem, and I hope to inspire you.

1. Operation demonstration results

2. WeChat payment configuration

1. First complete the WeChat authentication on the WeChat public account management platform ( WeChat public platform ); then open WeChat payment; link the WeChat payment account; the process of WeChat authentication will not be discussed, the steps of opening WeChat payment in the previous two pages, follow the prompts step by step Just operate.

 

2. Secondly, complete the relevant configuration on the WeChat payment management platform ( WeChat payment - China's leading third-party payment platform|WeChat payment provides a safe and fast payment method ), activate the corresponding functions, and set the white list of ip and domain names before it can be used smoothly WeChat payment.

3. Red envelope source code

Front-end code:

<%@ Page Language="C#" AutoEventWireup="true" EnableEventValidation="false" CodeFile="Test.aspx.cs" Inherits="Jjlm.Test" %>

<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
<head id="Head1" runat="server">
    <title>发送红包测试</title>
</head>

<body style="background:#fff;">
<center>
<div style="width:95%;">
 <form id="form1" runat="server">
    </br>
	<!---->openid:<asp:TextBox runat="server" id="tbxOpenid" Width="60%" Visible="true"></asp:TextBox></br></br>
	商户名称:<asp:TextBox runat="server" id="tbxShanghu" Width="60%"></asp:TextBox></br></br>
	红包描述:<asp:TextBox runat="server" id="tbxZhufu" Width="60%"></asp:TextBox></br></br>
	红包金额:<asp:TextBox runat="server" id="tbxNum" Width="60%"></asp:TextBox></br></br>
	发送事由:<asp:TextBox runat="server" id="tbxReason" Width="60%"></asp:TextBox></br></br>
	<div style="margin-top: 10px;text-align: center;">
		<asp:Button ID="btnSendCommission" Runat="server" OnClick="Send" width="15%" Text="发送红包"></asp:Button>
	</div>	

	<asp:Label runat="server" id="lbresult" Visible="true"/>

</form>
</div>
</center>

</body>
</html>

Backend code:

using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Data.SqlClient;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.IO;
using System.Xml;
using System.Text;
using System.Net;
using System.Drawing;
using System.Drawing.Imaging;
using QinMing.Config;
using QinMing.WeixinPayPayment;

namespace Jjlm
{
	public partial class Test : System.Web.UI.Page
	{
		protected void Page_Load(object sender, EventArgs e)
		{
			if (!IsPostBack)
			{

			}
		}

		protected void Send(object sender, EventArgs e)
		{
			Random r = new Random();
			string ran1 = r.Next(1000, 9999).ToString();
			string out_trade_no = QinMingConfig.Weixin_MchId + DateTime.Now.ToString("yyyyMMddHHmmss") + ran1;

			QinMingWeixinPayPayment.SendRedPackOne(tbxShanghu.Text, tbxZhufu.Text, tbxOpenid.Text, tbxNum.Text, tbxReason.Text, "", out_trade_no);
			lbresult.Text = "微信红包已发出,请注意查收";
		}
	}
}

4. Data sheet used

CREATE TABLE weixin_pay_payment_record
(
	open_id nvarchar(50),            --收款人openid
	payment_class nvarchar(30),      --支付类型,红包、转账到零钱等
	payment_num float,               --支付金额
	payment_time datetime,           --支付时间
	payment_reason nvarchar(200),    --支付缘由
	payment_trade_no nvarchar(50),   --支付订单号
	related_order_no nvarchar(50),   --相关订单号
	remark nvarchar(100)             --备注
)

Five, class source code

The following class implements two functions, one is to send red envelopes to designated WeChat users; the other is to transfer money to small change to designated WeChat users. What we demonstrated above is the function of sending red envelopes, and the next article demonstrates the function of transferring money to change.

QinMingWeixinPayPayment.cs, the class source code file is placed in the App_Code directory.

using System.Threading.Tasks;
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Xml.Linq;
using System.IO;
using System.Xml;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using QinMing.Config;
using QinMing.WeixinContainer;
using QinMing.Tools;

namespace QinMing.WeixinPayPayment
{
    /// <summary>
    /// 企业号微信支付接口
    /// </summary>
    public static class QinMingWeixinPayPayment
    {

        /// <summary>
        /// 外部调用的向某个openid发放微信红包的方法实现
        /// </summary>
		public static bool SendRedPackOne(string shanghu, string zhufu, string openid, string RedpackNum, string RedpackReason, string RedpackRemark, string out_trade_no)
        {
            string ShName = shanghu;  //商户名称
            string ZhuFuYu = zhufu;  //红包祝福语,  "客户能看到的红包说明"
            string HuoDong = "降价联盟活动";  //活动名称,已关注公众号用户看不到,未关注公众号用户可以在微信app的服务通知中看到
            string Remark = RedpackRemark;  //备注
			string tmpBillno = "";
            string certPath = QinMingConfig.certPath;  //证书在服务器的物理位置
            int time_out = 10000;
            string data = null;  //调用现金红包接口需要的数据
            string xmlResult = null;  //现金红包接口返回的xml

            try
            {
                //创建支付应答对象
                RequestHandler packageReqHandler = new RequestHandler(null);
                //初始化
                packageReqHandler.Init();
                string nonceStr = TenPayV3Util.GetNoncestr();  //时间戳
                                                               //设置package订单参数
                packageReqHandler.SetParameter("nonce_str", nonceStr);    //随机字符串,不长于32位
                if(out_trade_no == "")
				{
					tmpBillno = QinMingConfig.Weixin_MchId + DateTime.Now.ToString("yyyyMMdd") + TenPayV3Util.BuildDailyRandomStr(10);  //商户订单号(每个订单号必须唯一)组成:mch_id+yyyymmdd+10位一天内不能重复的数字。接口根据商户订单号支持重入,如出现超时可再调用。
				}
				else
				{
					tmpBillno = out_trade_no;
				}
				
				packageReqHandler.SetParameter("mch_billno", tmpBillno);
                packageReqHandler.SetParameter("mch_id", QinMingConfig.Weixin_MchId);  //微信支付分配的商户号
                packageReqHandler.SetParameter("wxappid", QinMingConfig.Weixin_AppId);//微信分配的公众账号ID(企业号corpid即为此appId)。接口传入的所有appid应该为公众号的appid(在mp.weixin.qq.com申请的),不能为APP的appid(在open.weixin.qq.com申请的)。 
                packageReqHandler.SetParameter("send_name", ShName);//商户名称  
                packageReqHandler.SetParameter("re_openid", openid);  //用户openid  接收红包的用户用户在wxappid下的openid
                                                                                    //int tmpAmount = Convert.ToInt32(dr["贡献uv"].ToString())*10;
                packageReqHandler.SetParameter("total_amount", RedpackNum);  //付款金额 单位分  tmpAmount.ToString()
                packageReqHandler.SetParameter("total_num", "1");  //红包发放总人数
                packageReqHandler.SetParameter("wishing", ZhuFuYu);  //红包祝福语
                packageReqHandler.SetParameter("client_ip", HttpContext.Current.Request.UserHostAddress);//Ip地址
                packageReqHandler.SetParameter("act_name", HuoDong);//活动名称,客户看不到
                packageReqHandler.SetParameter("remark", Remark);     //备注,客户看不到
                packageReqHandler.SetParameter("scene_id", "PRODUCT_5");  //红包发放总人数
                string sign = packageReqHandler.CreateMd5Sign("key", QinMingConfig.Weixin_MchIdKey);
                packageReqHandler.SetParameter("sign", sign);                        //签名
                data = packageReqHandler.ParseXML();
                xmlResult = QinMing.WeixinPayPayment.QinMingWeixinPayPayment.SendRedPack(data, QinMingConfig.Weixin_MchId, certPath, time_out);
                //Response.Write(xmlResult);
                var res = XDocument.Parse(xmlResult);
                string return_code = res.Element("xml").Element("return_code").Value;
                if ("SUCCESS".Equals(return_code))
                {
                    string result_code = res.Element("xml").Element("result_code").Value;
                    if ("SUCCESS".Equals(result_code))
                    {
                        //留存微信红包发送日志
						SendRedPackRecord(openid, "微信红包", RedpackNum, RedpackReason, tmpBillno, RedpackRemark);
                    }
					else
					{
						QinMingTools.WriteLog("微信支付(向指定openid发红包):", res.ToString());
					}
                }
                return true;
            }
            catch (Exception exception)
            {
                QinMingTools.WriteLog("微信支付(向指定openid发红包):", exception.ToString());
				return false;
            }
        }

        public static void SendRedPackRecord(string openid, string paymentclass, string redpack, string reason, string billno, string remark)
        {
            SqlConnection Conn = new SqlConnection(QinMingConfig.DatabaseConnStr);
            Conn.Open();
            SqlCommand Comm = new SqlCommand();
            Comm.Connection = Conn;
            Comm.CommandText = "insert into weixin_pay_payment_record (open_id, payment_class, payment_num, payment_time, payment_reason, payment_trade_no, remark) values "
                        + " ('" + openid + "','" + paymentclass + "'," + redpack + ",getdate(),'" + reason + "','" + billno + "','" + remark + "')";
            Comm.ExecuteScalar();
            if (Conn.State == ConnectionState.Open)
            {
                Conn.Close();
                Conn.Dispose();
            }
        }

        #region 内部调用企业向用户发红包
        /// <summary>
        /// 用于企业向微信用户个人发红包
        /// 目前支持向指定微信用户的openid个人发红包;不管用户是否关注公众号都能收到,未关注情况下在服务通知里收取红包
        /// </summary>
        /// <param name="certPassword">apiclient_cert.p12证书密码即商户号</param>
        /// <param name="data">微信支付需要post的xml数据</param>
        /// <param name="certPath">apiclient_cert.p12的证书物理位置(例如:E:\projects\文档\微信商户平台证书\商户平台API证书</param>
        /// <param name="timeOut"></param>
        /// <returns></returns>
        public static string SendRedPack(string data, string certPassword, string certPath, int timeOut)
        {
            var urlFormat = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";
            string cert = certPath;

            ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
            X509Certificate2 cer = new X509Certificate2(cert, certPassword, X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet);

            var formDataBytes = data == null ? new byte[0] : Encoding.UTF8.GetBytes(data);
            MemoryStream ms = new MemoryStream();
            ms.Write(formDataBytes, 0, formDataBytes.Length);
            ms.Seek(0, SeekOrigin.Begin);//设置指针读取位置

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlFormat);
            request.ClientCertificates.Add(cer);
            request.Method = "POST";
            request.Timeout = timeOut;

            request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36";

            #region 输入二进制流
            if (ms != null)
            {
                ms.Position = 0;
                //直接写入流
                Stream requestStream = request.GetRequestStream();
                byte[] buffer = new byte[1024];
                int bytesRead = 0;
                while ((bytesRead = ms.Read(buffer, 0, buffer.Length)) != 0)
                {
                    requestStream.Write(buffer, 0, bytesRead);
                }
                ms.Close();//关闭文件访问
            }
            #endregion

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            using (Stream responseStream = response.GetResponseStream())
            {
                using (StreamReader myStreamReader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8")))
                {
                    string retString = myStreamReader.ReadToEnd();
                    return retString;
                }
            }
        }
		
		/// <summary>
        /// 外部调用的向某个openid零钱转账的方法实现
		///TransferAccountRemark不能为空
        /// </summary>
		public static bool TransferAccountOne(string shanghu, string zhufu, string openid, string TransferAccountNum, string TransferAccountReason, string TransferAccountRemark, string out_trade_no)
        {
			string certPath = QinMingConfig.certPath;  //证书在服务器的物理位置
			//certPath = @"e:\web\weixin\apiclient_cert.p12";   //@"F:\apiclient_cert.p12";    Server.MapPath("~/") + ""
			int time_out = 10000;
			string data = null;  //调用现金红包接口需要的数据
			string xmlResult = null;  //现金红包接口返回的xml
			string tmpBillno = "";

			try
			{
				//创建支付应答对象
				RequestHandler packageReqHandler = new RequestHandler(null);
				//初始化
				packageReqHandler.Init();
				string nonceStr = TenPayV3Util.GetNoncestr();  //时间戳
				//设置package订单参数
				packageReqHandler.SetParameter("nonce_str", nonceStr);    //随机字符串,不长于32位
				if(out_trade_no == "")
				{
					tmpBillno = QinMingConfig.Weixin_MchId + DateTime.Now.ToString("yyyyMMdd") + TenPayV3Util.BuildDailyRandomStr(10);  //商户订单号(每个订单号必须唯一)组成:mch_id+yyyymmdd+10位一天内不能重复的数字。接口根据商户订单号支持重入,如出现超时可再调用。
				}
				else
				{
					tmpBillno = out_trade_no;
				}
				
				packageReqHandler.SetParameter("partner_trade_no", tmpBillno);
				packageReqHandler.SetParameter("mchid", QinMingConfig.Weixin_MchId);  //微信支付分配的商户号
				packageReqHandler.SetParameter("mch_appid", QinMingConfig.Weixin_AppId);//微信分配的公众账号ID(企业号corpid即为此appId)。接口传入的所有appid应该为公众号的appid(在mp.weixin.qq.com申请的),不能为APP的appid(在open.weixin.qq.com申请的)。 
				packageReqHandler.SetParameter("check_name", "NO_CHECK");//商户名称  
				packageReqHandler.SetParameter("openid", openid);  //用户openid  
				packageReqHandler.SetParameter("amount", TransferAccountNum);  //付款金额 单位分  
				packageReqHandler.SetParameter("desc", TransferAccountRemark);  //红包发放总人数
				packageReqHandler.SetParameter("spbill_create_ip", "192.168.0.1");  //红包祝福语
				string sign = packageReqHandler.CreateMd5Sign("key", QinMingConfig.Weixin_MchIdKey);
				packageReqHandler.SetParameter("sign", sign);                        //签名
				data = packageReqHandler.ParseXML();
				xmlResult = QinMing.WeixinPayPayment.QinMingWeixinPayPayment.TransferAccount(data, QinMingConfig.Weixin_MchId, certPath, time_out);
				//Response.Write(xmlResult);
				var res = XDocument.Parse(xmlResult);
				string return_code = res.Element("xml").Element("return_code").Value;
				if ("SUCCESS".Equals(return_code))
				{
					string result_code = res.Element("xml").Element("result_code").Value;
					if ("SUCCESS".Equals(result_code))
					{
						TransferAccountRecord(openid, "微信转账到零钱", TransferAccountNum, TransferAccountReason, tmpBillno, TransferAccountRemark);
					}
					else
					{
						QinMingTools.WriteLog("微信支付(向指定openid零钱转账):", res.ToString());
					}
				}
				return true;
			}
			catch (Exception exception)
			{
				QinMingTools.WriteLog("微信支付(向指定openid零钱转账):", exception.ToString());
				return false;
			}
		}
		
		public static void TransferAccountRecord(string openid, string paymentclass, string transferaccount, string reason, string billno, string remark)
        {
            SqlConnection Conn = new SqlConnection(QinMingConfig.DatabaseConnStr);
            Conn.Open();
            SqlCommand Comm = new SqlCommand();
            Comm.Connection = Conn;
            Comm.CommandText = "insert into weixin_pay_payment_record (open_id, payment_class, payment_num, payment_time, payment_reason, payment_trade_no, remark) values "
                        + " ('" + openid + "','" + paymentclass + "'," + transferaccount + ",getdate(),'" + reason + "','" + billno + "','" + remark + "')";
            Comm.ExecuteScalar();
            if (Conn.State == ConnectionState.Open)
            {
                Conn.Close();
                Conn.Dispose();
            }
        }

        /// <summary>
        /// 内部调用企业向微信用户个人转帐,直接到零钱
        /// 目前支持向指定微信用户的openid个人转帐
        /// </summary>
        public static string TransferAccount(string data, string certPassword, string certPath, int timeOut)
        {
            var urlFormat = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
            string cert = certPath;

            ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
            X509Certificate2 cer = new X509Certificate2(cert, certPassword, X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet);

            var formDataBytes = data == null ? new byte[0] : Encoding.UTF8.GetBytes(data);
            MemoryStream ms = new MemoryStream();
            ms.Write(formDataBytes, 0, formDataBytes.Length);
            ms.Seek(0, SeekOrigin.Begin);//设置指针读取位置

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlFormat);
            request.ClientCertificates.Add(cer);
            request.Method = "POST";
            request.Timeout = timeOut;

            request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36";

            #region 输入二进制流
            if (ms != null)
            {
                ms.Position = 0;
                //直接写入流
                Stream requestStream = request.GetRequestStream();
                byte[] buffer = new byte[1024];
                int bytesRead = 0;
                while ((bytesRead = ms.Read(buffer, 0, buffer.Length)) != 0)
                {
                    requestStream.Write(buffer, 0, bytesRead);
                }
                ms.Close();//关闭文件访问
            }
            #endregion

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            using (Stream responseStream = response.GetResponseStream())
            {
                using (StreamReader myStreamReader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8")))
                {
                    string retString = myStreamReader.ReadToEnd();
                    return retString;
                }
            }
        }
		
        private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            if (errors == SslPolicyErrors.None)
                return true;
            return false;
        }
        #endregion

    }

    /// <summary>
    /// MD5UtilHelper 的摘要说明。
    /// </summary>
    public class MD5UtilHelper
    {
        public MD5UtilHelper()
        {
            //
            // TODO: 在此处添加构造函数逻辑
            //
        }

        /// <summary>
        /// 获取大写的MD5签名结果
        /// </summary>
        /// <param name="encypStr"></param>
        /// <param name="charset"></param>
        /// <returns></returns>
        public static string GetMD5(string encypStr, string charset)
        {
            string retStr;
            MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider();

            //创建md5对象
            byte[] inputBye;
            byte[] outputBye;

            //使用GB2312编码方式把字符串转化为字节数组.
            try
            {
                inputBye = Encoding.GetEncoding(charset).GetBytes(encypStr);
            }
            catch (Exception ex)
            {
                inputBye = Encoding.GetEncoding("GB2312").GetBytes(encypStr);
            }
            outputBye = m5.ComputeHash(inputBye);

            retStr = System.BitConverter.ToString(outputBye);
            retStr = retStr.Replace("-", "").ToUpper();
            return retStr;
        }
    }

    public class RequestHandler
    {

        public RequestHandler(HttpContext httpContext)
        {
            Parameters = new Hashtable();

            this.HttpContext = httpContext ?? HttpContext.Current;

        }
        /// <summary>
        /// 密钥
        /// </summary>
        private string Key;

        protected HttpContext HttpContext;

        /// <summary>
        /// 请求的参数
        /// </summary>
        protected Hashtable Parameters;

        /// <summary>
        /// debug信息
        /// </summary>
        private string DebugInfo;

        /// <summary>
        /// 初始化函数
        /// </summary>
        public virtual void Init()
        {
        }
        /// <summary>
        /// 获取debug信息
        /// </summary>
        /// <returns></returns>
        public String GetDebugInfo()
        {
            return DebugInfo;
        }
        /// <summary>
        /// 获取密钥
        /// </summary>
        /// <returns></returns>
        public string GetKey()
        {
            return Key;
        }
        /// <summary>
        /// 设置密钥
        /// </summary>
        /// <param name="key"></param>
        public void SetKey(string key)
        {
            this.Key = key;
        }

        /// <summary>
        /// 设置参数值
        /// </summary>
        /// <param name="parameter"></param>
        /// <param name="parameterValue"></param>
        public void SetParameter(string parameter, string parameterValue)
        {
            if (parameter != null && parameter != "")
            {
                if (Parameters.Contains(parameter))
                {
                    Parameters.Remove(parameter);
                }

                Parameters.Add(parameter, parameterValue);
            }
        }


        /// <summary>
        /// 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名
        /// </summary>
        /// <param name="key">参数名</param>
        /// <param name="value">参数值</param>
        /// key和value通常用于填充最后一组参数
        /// <returns></returns>
        public virtual string CreateMd5Sign(string key, string value)
        {
            StringBuilder sb = new StringBuilder();

            ArrayList akeys = new ArrayList(Parameters.Keys);
            akeys.Sort();

            foreach (string k in akeys)
            {
                string v = (string)Parameters[k];
                if (null != v && "".CompareTo(v) != 0
                    && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0)
                {
                    sb.Append(k + "=" + v + "&");
                }
            }

            sb.Append(key + "=" + value);
            string sign = MD5UtilHelper.GetMD5(sb.ToString(), GetCharset()).ToUpper();

            return sign;
        }

        /// <summary>
        /// 输出XML
        /// </summary>
        /// <returns></returns>
        public string ParseXML()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<xml>");
            foreach (string k in Parameters.Keys)
            {
                string v = (string)Parameters[k];
                if (Regex.IsMatch(v, @"^[0-9.]$"))
                {

                    sb.Append("<" + k + ">" + v + "</" + k + ">");
                }
                else
                {
                    sb.Append("<" + k + "><![CDATA[" + v + "]]></" + k + ">");
                }

            }
            sb.Append("</xml>");
            return sb.ToString();
        }



        /// <summary>
        /// 设置debug信息
        /// </summary>
        /// <param name="debugInfo"></param>
        public void SetDebugInfo(String debugInfo)
        {
            this.DebugInfo = debugInfo;
        }

        public Hashtable GetAllParameters()
        {
            return this.Parameters;
        }

        protected virtual string GetCharset()
        {
            return this.HttpContext.Request.ContentEncoding.BodyName;
        }
    }


    public class TenPayV3Util
    {
        public static Random random = new Random();

        /// <summary>
        /// 随机生成Noncestr
        /// </summary>
        /// <returns></returns>
        public static string GetNoncestr()
        {
            return EncryptHelper.GetMD5(Guid.NewGuid().ToString(), "UTF-8");
        }

        /// <summary>
        /// 获取微信时间格式
        /// </summary>
        /// <returns></returns>
        public static string GetTimestamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }

        /// <summary>
        /// 对字符串进行URL编码
        /// </summary>
        /// <param name="instr"></param>
        /// <param name="charset"></param>
        /// <returns></returns>
        public static string UrlEncode(string instr, string charset)
        {
            //return instr;
            if (instr == null || instr.Trim() == "")
                return "";
            else
            {
                //string res;

                try
                {
                    return System.Web.HttpUtility.UrlEncode(instr, Encoding.GetEncoding(charset));
                }
                catch (Exception ex)
                {
                    return System.Web.HttpUtility.UrlEncode(instr, Encoding.GetEncoding("GB2312"));
                }

                //return res;
            }
        }

        /// <summary>
        /// 对字符串进行URL解码
        /// </summary>
        /// <param name="instr"></param>
        /// <param name="charset"></param>
        /// <returns></returns>
        public static string UrlDecode(string instr, string charset)
        {
            if (instr == null || instr.Trim() == "")
                return "";
            else
            {
                //string res;

                try
                {
                    return System.Web.HttpUtility.UrlDecode(instr, Encoding.GetEncoding(charset));
                }
                catch (Exception ex)
                {
                    return System.Web.HttpUtility.UrlDecode(instr, Encoding.GetEncoding("GB2312"));
                }
                //return res;

            }
        }


        /// <summary>
        /// 取时间戳生成随即数,替换交易单号中的后10位流水号
        /// </summary>
        /// <returns></returns>
        public static UInt32 UnixStamp()
        {
            TimeSpan ts = DateTime.Now - TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            return Convert.ToUInt32(ts.TotalSeconds);
        }

        /// <summary>
        /// 取随机数
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        public static string BuildRandomStr(int length)
        {
            int num;

            lock (random)
            {
                num = random.Next();
            }

            string str = num.ToString();

            if (str.Length > length)
            {
                str = str.Substring(0, length);
            }
            else if (str.Length < length)
            {
                int n = length - str.Length;
                while (n > 0)
                {
                    str = str.Insert(0, "0");
                    n--;
                }
            }

            return str;
        }

        /// <summary>
        /// 创建当天内不会重复的数字
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        public static string BuildDailyRandomStr(int length)
        {
            Random r = new Random();
            int i = r.Next(1000, 9999);
            var stringFormat = DateTime.Now.ToString("HHmmss" + i.ToString());//共10位

            return stringFormat;
        }


        /// <summary>
        /// 对退款通知消息进行解密
        /// </summary>
        /// <param name="reqInfo"></param>
        /// <param name="mchKey"></param>
        /// <returns></returns>
        public static string DecodeRefundReqInfo(string reqInfo, string mchKey)
        {
            //参考文档:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_16&index=11
            /*
               解密步骤如下: 
                (1)对加密串A做base64解码,得到加密串B
                (2)对商户key做md5,得到32位小写key* ( key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置 )

                (3)用key*对加密串B做AES-256-ECB解密(PKCS7Padding)
             */
            //var base64Encode = Encoding.UTF8.GetString(Convert.FromBase64String(reqInfo));//(1)
            var base64Encode = reqInfo;//(1) EncryptHelper.AESDecrypt 方法内部会进行一次base64解码,因此这里不再需要解码
            var md5Str = EncryptHelper.GetLowerMD5(mchKey, Encoding.UTF8);//(2)
            var result = EncryptHelper.AESDecrypt(base64Encode, md5Str);//(3)
            return result;
        }
    }


    /// <summary>
    /// 安全帮助类,提供SHA-1算法等
    /// </summary>
    public class EncryptHelper
    {
        #region SHA相关

        /// <summary>
        /// 采用SHA-1算法加密字符串(小写)
        /// </summary>
        /// <param name="encypStr">需要加密的字符串</param>
        /// <returns></returns>
        public static string GetSha1(string encypStr)
        {
            var sha1 = SHA1.Create();
            var sha1Arr = sha1.ComputeHash(Encoding.UTF8.GetBytes(encypStr));
            StringBuilder enText = new StringBuilder();
            foreach (var b in sha1Arr)
            {
                enText.AppendFormat("{0:x2}", b);
            }

            return enText.ToString();

            //byte[] strRes = Encoding.Default.GetBytes(encypStr);
            //HashAlgorithm iSHA = new SHA1CryptoServiceProvider();
            //strRes = iSHA.ComputeHash(strRes);
            //StringBuilder enText = new StringBuilder();
            //foreach (byte iByte in strRes)
            //{
            //    enText.AppendFormat("{0:x2}", iByte);
            //}
        }

        /// <summary>
        /// HMAC SHA256 加密
        /// </summary>
        /// <param name="message">加密消息原文。当为小程序SessionKey签名提供服务时,其中message为本次POST请求的数据包(通常为JSON)。特别地,对于GET请求,message等于长度为0的字符串。</param>
        /// <param name="secret">秘钥(如小程序的SessionKey)</param>
        /// <returns></returns>
        public static string GetHmacSha256(string message, string secret)
        {
            message = message ?? "";
            secret = secret ?? "";
            byte[] keyByte = Encoding.UTF8.GetBytes(secret);
            byte[] messageBytes = Encoding.UTF8.GetBytes(message);
            using (var hmacsha256 = new HMACSHA256(keyByte))
            {
                byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
                StringBuilder enText = new StringBuilder();
                foreach (var b in hashmessage)
                {
                    enText.AppendFormat("{0:x2}", b);
                }
                return enText.ToString();
            }
        }


        #endregion

        #region MD5

        /// <summary>
        /// 获取大写的MD5签名结果
        /// </summary>
        /// <param name="encypStr">需要加密的字符串</param>
        /// <param name="encoding">编码</param>
        /// <returns></returns>
        public static string GetMD5(string encypStr, Encoding encoding)
        {
            string retStr;

            MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider();

            //创建md5对象
            byte[] inputBye;
            byte[] outputBye;

            //使用指定编码方式把字符串转化为字节数组.
            try
            {
                inputBye = encoding.GetBytes(encypStr);
            }
            catch
            {
                inputBye = Encoding.GetEncoding("utf-8").GetBytes(encypStr);

            }
            outputBye = m5.ComputeHash(inputBye);

            retStr = BitConverter.ToString(outputBye);
            retStr = retStr.Replace("-", "").ToUpper();
            return retStr;
        }

        /// <summary>
        /// 获取大写的MD5签名结果
        /// </summary>
        /// <param name="encypStr">需要加密的字符串</param>
        /// <param name="charset">编码</param>
        /// <returns></returns>
        public static string GetMD5(string encypStr, string charset = "utf-8")
        {
            charset = charset ?? "utf-8";
            try
            {
                //使用指定编码
                return GetMD5(encypStr, Encoding.GetEncoding(charset));
            }
            catch (Exception ex)
            {
                //使用UTF-8编码
                return GetMD5("utf-8", Encoding.GetEncoding(charset));

                //#if NET35 || NET40 || NET45
                //                inputBye = Encoding.GetEncoding("GB2312").GetBytes(encypStr);
                //#else
                //                inputBye = Encoding.GetEncoding(936).GetBytes(encypStr);
                //#endif
            }
        }

        /// <summary>
        /// 获取小写的MD5签名结果
        /// </summary>
        /// <param name="encypStr">需要加密的字符串</param>
        /// <param name="encoding">编码</param>
        /// <returns></returns>
        public static string GetLowerMD5(string encypStr, Encoding encoding)
        {
            return GetMD5(encypStr, encoding).ToLower();
        }

        #endregion

        #region AES

        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="inputdata">输入的数据</param>
        /// <param name="iv">向量</param>
        /// <param name="strKey">加密密钥</param>
        /// <returns></returns>
        public static byte[] AESEncrypt(byte[] inputdata, byte[] iv, string strKey)
        {
            //分组加密算法   
            SymmetricAlgorithm des = Rijndael.Create();

            byte[] inputByteArray = inputdata;//得到需要加密的字节数组       
                                              //设置密钥及密钥向量
            des.Key = Encoding.UTF8.GetBytes(strKey.Substring(0, 32));
            des.IV = iv;
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(inputByteArray, 0, inputByteArray.Length);
                    cs.FlushFinalBlock();
                    byte[] cipherBytes = ms.ToArray();//得到加密后的字节数组   
                    //cs.Close();
                    //ms.Close();
                    return cipherBytes;
                }
            }
        }


        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="inputdata">输入的数据</param>
        /// <param name="iv">向量</param>
        /// <param name="strKey">key</param>
        /// <returns></returns>
        public static byte[] AESDecrypt(byte[] inputdata, byte[] iv, byte[] strKey)
        {
            SymmetricAlgorithm des = Rijndael.Create();

            des.Key = strKey;//Encoding.UTF8.GetBytes(strKey);//.Substring(0, 7)
            des.IV = iv;
            byte[] decryptBytes = new byte[inputdata.Length];
            using (MemoryStream ms = new MemoryStream(inputdata))
            {
                using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Read))
                {
                    cs.Read(decryptBytes, 0, decryptBytes.Length);
                    //cs.Close();
                    //ms.Close();
                }
            }
            return decryptBytes;
        }

        /// <summary>  
        /// AES解密(无向量)  
        /// </summary>  
        /// <param name="data">被加密的明文</param>  
        /// <param name="key">密钥</param>  
        /// <returns>明文</returns>  
        public static string AESDecrypt(String data, String key)
        {
            Byte[] encryptedBytes = Convert.FromBase64String(data);
            Byte[] bKey = new Byte[32];
            Array.Copy(Encoding.UTF8.GetBytes(key.PadRight(bKey.Length)), bKey, bKey.Length);

            MemoryStream mStream = new MemoryStream(encryptedBytes);
            //mStream.Write( encryptedBytes, 0, encryptedBytes.Length );  
            //mStream.Seek( 0, SeekOrigin.Begin );  


            //RijndaelManaged aes = new RijndaelManaged();
            SymmetricAlgorithm aes = Rijndael.Create();

            aes.Mode = CipherMode.ECB;
            aes.Padding = PaddingMode.PKCS7;
            aes.KeySize = 128;
            aes.Key = bKey;
            //aes.IV = _iV;  
            CryptoStream cryptoStream = new CryptoStream(mStream, aes.CreateDecryptor(), CryptoStreamMode.Read);
            try
            {
                byte[] tmp = new byte[encryptedBytes.Length + 32];
                int len = cryptoStream.Read(tmp, 0, encryptedBytes.Length + 32);
                byte[] ret = new byte[len];
                Array.Copy(tmp, 0, ret, 0, len);
                return Encoding.UTF8.GetString(ret);
            }
            finally
            {
                cryptoStream.Close();
                mStream.Close();
                aes.Clear();
            }
        }

        #endregion
    }

}

Guess you like

Origin blog.csdn.net/daobaqin/article/details/125073605