前面讲的所有都没有涉及到钱,一旦关联到钱都是非常敏感的,所以开通微信支付的过程和配置过程相对比较繁琐,本篇给出主要入口,因篇幅原因一篇文章讲不太细,但已足以帮你解决问题,希望给大家启发。
一、操作演示结果
二、微信支付配置
1、首先在微信公众号管理平台(微信公众平台)完成微信认证;然后开通微信支付;关联微信支付账号;微信认证的过程就不讲了,上两张开通微信支付的步骤,按提示一步步操作即可。
2、其次在微信支付管理平台(微信支付 - 中国领先的第三方支付平台 | 微信支付提供安全快捷的支付方式)完成相关配置,开通相应的功能,设置ip、域名等白名单,才可以顺利使用微信支付。
三、发红包源码
前端代码:
<%@ 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>
后端代码:
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 = "微信红包已发出,请注意查收";
}
}
}
四、所用数据表
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) --备注
)
五、类源码
下面这个类实现了两个功能,一是给指定微信用户发红包;二是给指定微信用户转账到零钱。我们上面演示的是发红包功能,下一篇文章演示转账到零钱功能。
QinMingWeixinPayPayment.cs,类源码文件放到App_Code目录中。
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
}
}