C# 获取支付签名

C# 获取支付签名

签名规则

签名生成的通用步骤如下:

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

特别注意以下重要规则:

参数名ASCII码从小到大排序(字典序);

如果参数的值为空不参与签名;

◆ 参数名区分大小写;

◆ 验证调用返回签名时,传送的signature参数不参与签名,将生成的签名与该signature值作校验。

◆ 商户资金自主管理系统实时交易接口可能增加字段,验证签名时必须支持增加的扩展字段

第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行签名运算。

 

举例:

假设传送的参数如下:

merNo: 10001000000001

transDate:20180110

queryItem:A

queryValue:ABCD0001

 

第一步:对参数按照key=value的格式,并按照参数名ASCII字典序排序如下:

stringA="merNo=10001000000001&queryItem=A&queryValue=ABCD0001&transDate=20180110";

第二步:获取签名:

【特殊签名:使用商户私钥证书对第二步得到的数据进行签名,签名后对签名数据做RSA加密】

最终得到发送的数据。

====================================

一:调用

PayData payData = new PayData();
payData.SetValue("transCode", "202004");//交易码-按流水划付
payData.SetValue("verNo", "100");//版本号-定值

//sign字段不参加签名

payData.SetValue("sign", payData.MakeSignUpper(key, false));

//特殊签名

// string str = payData.ToUrl("signature");
//string sign = CaRsaEncrypt(str);

//参考http://www.qdyee.com/archives/495

=================================

PayData

 

 

using LitJson;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;

namespace adminWebApi
{
public class PayData
{
public PayData()
{

}

//采用排序的Dictionary的好处是方便对数据包进行签名,不用再签名之前再做一次排序
private SortedDictionary<string, object> m_values = new SortedDictionary<string, object>();

/**
* 设置某个字段的值
* @param key 字段名
* @param value 字段值
*/
public void SetValue(string key, object value)
{
m_values[key] = value;
}

/**
* 根据字段名获取某个字段的值
* @param key 字段名
* @return key对应的字段值
*/
public object GetValue(string key)
{
object o = null;
m_values.TryGetValue(key, out o);
return o;
}

/**
* 判断某个字段是否已设置
* @param key 字段名
* @return 若字段key已被设置,则返回true,否则返回false
*/
public bool IsSet(string key)
{
object o = null;
m_values.TryGetValue(key, out o);
if (null != o)
return true;
else
return false;
}

/**
* @Dictionary格式转化成url参数格式
* @ return url格式串, 该串不包含sign字段值
*/
public string ToUrl(string signKey = "sign")
{
string buff = "";

string[] arrKeys = m_values.Keys.ToArray();
Array.Sort(arrKeys, string.CompareOrdinal);
foreach (var key in arrKeys)
{
if (m_values[key] == null)
{

}
if (key != signKey && m_values[key].GetType() != typeof(String))
{
buff += key + "=" + m_values[key].ToJson() + "&";
}
else
if (key != signKey && m_values[key].ToString() != "")
{
buff += key + "=" + m_values[key] + "&";
}
}
buff = buff.Trim('&');
return buff;
}

public string ToGetUrl()
{
string buff = "";
foreach (KeyValuePair<string, object> pair in m_values)
{
if (pair.Value == null)
{
//LogHelper.WriteError(typeof(WxPayData), "WxPayData内部含有值为null的字段!");
}

if (pair.Value.ToString() != "")
{
buff += pair.Key + "=" + pair.Value + "&";
}
}
buff = buff.Trim('&');
return buff;
}

/**
* @Dictionary格式化成Json
* @return json串数据
*/
public string ToJson()
{
string jsonStr = JsonMapper.ToJson(m_values);
return jsonStr;
}

/// <summary>
/// json格式转换为Dictionary
/// </summary>
/// <param name="jsonStr"></param>
public void FromJson(string jsonStr)
{
LitJson.JsonData jsonData = LitJson.JsonMapper.ToObject(jsonStr);

foreach (var item in jsonData.Keys)
{
SetValue(item, jsonData[item]);
}
}

/// <summary>
/// Dictionary格式转换成Json,然后Base64加密
/// </summary>
/// <returns></returns>
public string Base64String(Encoding encodeType)
{
string jsonStr = JsonMapper.ToJson(m_values);
return Base64Encode(encodeType, jsonStr);
}

/**
* @values格式化成能在Web页面上显示的结果(因为web页面上不能直接输出xml格式的字符串)
*/
public string ToPrintStr()
{
string str = "";
foreach (KeyValuePair<string, object> pair in m_values)
{
if (pair.Value == null)
{
//LogHelper.WriteError(typeof(WxPayData), "WxPayData内部含有值为null的字段!");
}

str += string.Format("{0}={1}<br>", pair.Key, pair.Value.ToString());
}
//LogHelper.WriteDebug(typeof(WxPayData), "Print in Web Page : " + str);
return str;
}

/**
* @生成签名,详见签名生成算法
* @return 签名, sign字段不参加签名
*/
public string MakeSignUpper(string key, bool isAdd, string signKey = "sign")
{
//转url格式
string str = ToUrl(signKey);
//在string后加入API KEY
if (isAdd)
str += "&key=" + key;
else
str += key;

LogHelper.WriteDebug(this.GetType(), "签名源串:" + str);
//MD5加密
var md5 = MD5.Create();
var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
var sb = new StringBuilder();
foreach (byte b in bs)
{
sb.Append(b.ToString("x2"));
}
//所有字符转为大写
return sb.ToString().ToUpper();
}

/**
*
* 检测签名是否正确
* 正确返回true,错误抛异常
*/
public bool CheckSignUpper(string key, bool isAdd, string signKey = "sign")
{
//如果没有设置签名,则跳过检测
if (!IsSet(signKey))
{
//LogHelper.WriteError(typeof(WxPayData), "WxPayData签名存在但不合法!");
throw new WxPayException("WxPayData签名存在但不合法!");
}
//如果设置了签名但是签名为空,则抛异常
else if (GetValue(signKey) == null || GetValue(signKey).ToString() == "")
{
//LogHelper.WriteError(typeof(WxPayData), "WxPayData签名存在但不合法!");
throw new WxPayException("WxPayData签名存在但不合法!");
}

//获取接收到的签名
string return_sign = GetValue(signKey).ToString();

//在本地计算新的签名
string cal_sign = MakeSignUpper(key, isAdd, signKey);

LogHelper.WriteDebug(this.GetType(), "返回签名:" + return_sign + " 源串计算签名结果:" + cal_sign);

if (cal_sign == return_sign)
{
return true;
}

//LogHelper.WriteError(typeof(WxPayData), "WxPayData签名验证错误!");
throw new WxPayException("WxPayData签名验证错误!");
}

/**
* @获取Dictionary
*/
public SortedDictionary<string, object> GetValues()
{
return m_values;
}

/// <summary>
/// Base64加密
/// </summary>
/// <param name="encodeType">加密采用的编码方式</param>
/// <param name="source">待加密的明文</param>
/// <returns></returns>
public string Base64Encode(Encoding encodeType, string source)
{
string encode = string.Empty;
byte[] bytes = encodeType.GetBytes(source);
try
{
encode = Convert.ToBase64String(bytes);
}
catch
{
encode = source;
}
return encode;
}

/// <summary>
/// Base64解密
/// </summary>
/// <param name="encodeType">解密采用的编码方式,注意和加密时采用的方式一致</param>
/// <param name="result">待解密的密文</param>
/// <returns>解密后的字符串</returns>
public string Base64Decode(Encoding encodeType, string result)
{
string decode = string.Empty;
byte[] bytes = Convert.FromBase64String(result);
try
{
decode = encodeType.GetString(bytes);
}
catch
{
decode = result;
}
return decode;
}

public static string GenerateTimeStamp()
{
TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
return Convert.ToInt64(ts.TotalSeconds).ToString();
}
}

public class WxPayException : Exception
{
public WxPayException(string msg)
: base(msg)
{

}
}
}

 

 

 

 

 

 

 

本文由 魏代群个人博客 作者:weidaiqun 发表,其版权均为 魏代群个人博客 所有,文章内容系作者个人观点,不代表 魏代群个人博客 对观点赞同或支持。如需转载,请注明文章来源。
1

发表评论