@functions{ public static string Alipay(string method, string gateway, string notifyUrl, string returnUrl, string paysn, string subject, decimal PaySUM) { var AlipayAppId = razor.AlipayAppId(); var AlipayPrivateKey = razor.AlipayPrivateKey(); var order = new { out_trade_no = paysn, product_code = "FAST_INSTANT_TRADE_PAY", subject = subject, total_amount = PaySUM }; IDictionary<string, string> data = new SortedDictionary<string, string>(); data.Add("app_id", AlipayAppId.ToString()); data.Add("charset", "utf-8"); data.Add("format", "JSON"); data.Add("method", method); data.Add("notify_url", notifyUrl); data.Add("return_url", returnUrl); data.Add("sign_type", "RSA2"); data.Add("sign", ""); data.Add("timestamp", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); data.Add("version", "1.0"); data.Add("biz_content", Json.Encode(order)); //筛选 data.Remove("sign"); //拼接 var dataString = string.Join("&", data.Select(pattern => pattern.Key + "=" + pattern.Value)); //签名 var sign = razor.RsaSign(dataString, AlipayPrivateKey.ToString()); data.Add("sign",sign); //拼接 dataString = string.Join("&", data.Select(pattern => pattern.Key + "=" + HttpUtility.UrlEncode(pattern.Value))); var url = gateway + "?" + dataString; return url; } }
@functions{ public static string RsaSign(string data, string privatekey) { CspParameters CspParameters = new CspParameters(); RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(2048, CspParameters); byte[] bytes = Encoding.UTF8.GetBytes(data); privatekey = RSA.ToXmlString(true); RSA.FromXmlString(privatekey); byte[] sign = RSA.SignData(bytes, "SHA256"); return Convert.ToBase64String(sign); } }
调试错误,请回到请求来源地,重新发起请求。 错误代码 invalid-signature 错误原因: 验签出错,建议检查签名字符串或签名私钥与应用公钥是否匹配,网关生成的验签字符串为:app_id=2016091400508139&biz_content={"out_trade_no":"20180606012665123456","product_code":"FAST_INSTANT_TRADE_PAY","subject":"达人设计购物","total_amount":5.20}&charset=utf-8&format=JSON&method=alipay.trade.page.pay&notify_url=http://www.mastersws.com/Account/payAlipay&return_url=http://www.mastersws.com/Account/payAlipay/buy&sign_type=RSA2&timestamp=2018-06-12 16:35:44&version=1.0
分别使用demo和你自己的代码RsaSign计算,看结果是否一致
另外,我记得RSA签名有好几种参数的,你上面用了默认的参数,并不一定和服务器的一样
解决了吗?目前我也遇到该问题,还想问下你验签怎么演
怎么解决的,我也遇到了这个问题,头痛
public static string sign(string content, string privateKey, string input_charset)
{
byte[] Data = Encoding.GetEncoding(input_charset).GetBytes(content);
RSACryptoServiceProvider rsa = DecodePemPrivateKey(privateKey);
SHA256CryptoServiceProvider sh = new SHA256CryptoServiceProvider();
byte[] signData = rsa.SignData(Data, sh);
return Convert.ToBase64String(signData);
}
content:待签字符串
privateKey:私钥
input_charset:charset类型
待签字符串处理的没问题 签名类换下这个试试
如果是RSA SHA256CryptoServiceProvider换成SHA1就行了
//支付宝支付数据处理
@functions{
public static string Alipay(string method, string notifyUrl, string returnUrl, string paysn, string ProductCode, string subject, decimal total)
{
var AlipayAppId = razor.AlipayAppId();
var AlipayPrivateKey = razor.AlipayPrivateKey();
var gateway = "https://openapi.alipaydev.com/gateway.do";
var order = new { out_trade_no = paysn, product_code = ProductCode, subject = subject, total_amount = total };
SortedDictionary<string, string> data = new SortedDictionary<string, string>();
data.Add("app_id", AlipayAppId.ToString());
data.Add("charset", "utf-8");
data.Add("format", "JSON");
data.Add("method", method);
data.Add("notify_url", notifyUrl);
data.Add("return_url", returnUrl);
data.Add("sign", "");
data.Add("sign_type", "RSA2");
data.Add("timestamp", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
data.Add("version", "1.0");
data.Add("biz_content", Json.Encode(order));
//筛选
data.Remove("sign");
//拼接
var dataString = string.Join("&", data.Select(pattern => pattern.Key + "=" + pattern.Value));
//签名
var sign = AlipaySignature.AlipaySignature.RSASign(dataString, AlipayPrivateKey.ToString(), "RSA2", "utf-8");
data.Add("sign", sign);
//拼接
dataString = string.Join("&", data.Select(pattern => pattern.Key + "=" + HttpUtility.UrlEncode(pattern.Value)));
var url = gateway + "?" + dataString;
return url;
}
}
//签名规则用支付宝的
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.IO;
namespace AlipaySignature
{
public class AlipaySignature
{
//签名
public static string RSASign(string data, string privatekey, string signType, string charset)
{
RSACryptoServiceProvider rsaCsp = LoadCertificateString(privatekey, signType);
byte[] dataBytes = null;
if (string.IsNullOrEmpty(charset))
{
dataBytes = Encoding.UTF8.GetBytes(data);
}
else
{
dataBytes = Encoding.GetEncoding(charset).GetBytes(data);
}
if ("RSA2".Equals(signType))
{
byte[] signatureBytes = rsaCsp.SignData(dataBytes, "SHA256");
return Convert.ToBase64String(signatureBytes);
}
else
{
byte[] signatureBytes = rsaCsp.SignData(dataBytes, "SHA1");
return Convert.ToBase64String(signatureBytes);
}
}
//验签
public static bool RSACheck(string data, string publickey, string sign, string signType, string charset, bool keyFromFile)
{
try
{
if (string.IsNullOrEmpty(charset))
{
charset = "utf-8";
}
string sPublicKeyPEM;
if (keyFromFile)
{
sPublicKeyPEM = File.ReadAllText(publickey);
}
else
{
sPublicKeyPEM = "-----BEGIN PUBLIC KEY-----\r\n";
sPublicKeyPEM += publickey;
sPublicKeyPEM += "-----END PUBLIC KEY-----\r\n\r\n";
}
if ("RSA2".Equals(signType))
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.PersistKeyInCsp = false;
RSACryptoServiceProviderExtension.LoadPublicKeyPEM(rsa, sPublicKeyPEM);
bool bVerifyResultOriginal = rsa.VerifyData(Encoding.GetEncoding(charset).GetBytes(data), "SHA256", Convert.FromBase64String(sign));
return bVerifyResultOriginal;
}
else
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.PersistKeyInCsp = false;
RSACryptoServiceProviderExtension.LoadPublicKeyPEM(rsa, sPublicKeyPEM);
SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
bool bVerifyResultOriginal = rsa.VerifyData(Encoding.GetEncoding(charset).GetBytes(data), sha1, Convert.FromBase64String(sign));
return bVerifyResultOriginal;
}
}
catch
{
return false;
}
}
//签名算法规则
private static RSACryptoServiceProvider LoadCertificateString(string strKey, string signType)
{
byte[] data = null;
data = Convert.FromBase64String(strKey);
try
{
RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(data, signType);
return rsa;
}
catch
{
}
return null;
}
private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey, string signType)
{
byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
MemoryStream mem = new MemoryStream(privkey);
BinaryReader binr = new BinaryReader(mem);
byte bt = 0;
ushort twobytes = 0;
int elems = 0;
try
{
twobytes = binr.ReadUInt16();
if (twobytes == 0x8130)
binr.ReadByte();
else if (twobytes == 0x8230)
binr.ReadInt16();
else
return null;
twobytes = binr.ReadUInt16();
if (twobytes != 0x0102)
return null;
bt = binr.ReadByte();
if (bt != 0x00)
return null;
elems = GetIntegerSize(binr);
MODULUS = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
E = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
D = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
P = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
Q = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
DP = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
DQ = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
IQ = binr.ReadBytes(elems);
CspParameters CspParameters = new CspParameters();
CspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
int bitLen = 1024;
if ("RSA2".Equals(signType))
{
bitLen = 2048;
}
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(bitLen, CspParameters);
RSAParameters RSAparams = new RSAParameters();
RSAparams.Modulus = MODULUS;
RSAparams.Exponent = E;
RSAparams.D = D;
RSAparams.P = P;
RSAparams.Q = Q;
RSAparams.DP = DP;
RSAparams.DQ = DQ;
RSAparams.InverseQ = IQ;
RSA.ImportParameters(RSAparams);
return RSA;
}
catch
{
return null;
}
finally
{
binr.Close();
}
}
private static int GetIntegerSize(BinaryReader binr)
{
byte bt = 0;
byte lowbyte = 0x00;
byte highbyte = 0x00;
int count = 0;
bt = binr.ReadByte();
if (bt != 0x02)
return 0;
bt = binr.ReadByte();
if (bt == 0x81)
count = binr.ReadByte();
else if (bt == 0x82)
{
highbyte = binr.ReadByte();
lowbyte = binr.ReadByte();
byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
count = BitConverter.ToInt32(modint, 0);
}
else
{
count = bt;
}
while (binr.ReadByte() == 0x00)
{
count -= 1;
}
binr.BaseStream.Seek(-1, SeekOrigin.Current);
return count;
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.IO;
namespace AlipaySignature
{
public static class RSACryptoServiceProviderExtension
{
#region Methods
public static void LoadPublicKeyDER(RSACryptoServiceProvider provider, byte[] DERData)
{
byte[] RSAData = RSACryptoServiceProviderExtension.GetRSAFromDER(DERData);
byte[] publicKeyBlob = RSACryptoServiceProviderExtension.GetPublicKeyBlobFromRSA(RSAData);
provider.ImportCspBlob(publicKeyBlob);
}
public static void LoadPublicKeyPEM(RSACryptoServiceProvider provider, string sPEM)
{
byte[] DERData = RSACryptoServiceProviderExtension.GetDERFromPEM(sPEM);
RSACryptoServiceProviderExtension.LoadPublicKeyDER(provider, DERData);
}
internal static byte[] GetPublicKeyBlobFromRSA(byte[] RSAData)
{
byte[] data = null;
UInt32 dwCertPublicKeyBlobSize = 0;
if (RSACryptoServiceProviderExtension.CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING,
new IntPtr((int)CRYPT_OUTPUT_TYPES.RSA_CSP_PUBLICKEYBLOB), RSAData, (UInt32)RSAData.Length, CRYPT_DECODE_FLAGS.NONE,
data, ref dwCertPublicKeyBlobSize))
{
data = new byte[dwCertPublicKeyBlobSize];
if (!RSACryptoServiceProviderExtension.CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING,
new IntPtr((int)CRYPT_OUTPUT_TYPES.RSA_CSP_PUBLICKEYBLOB), RSAData, (UInt32)RSAData.Length, CRYPT_DECODE_FLAGS.NONE,
data, ref dwCertPublicKeyBlobSize))
throw new Win32Exception(Marshal.GetLastWin32Error());
}
else
throw new Win32Exception(Marshal.GetLastWin32Error());
return data;
}
internal static byte[] GetRSAFromDER(byte[] DERData)
{
byte[] data = null;
byte[] publicKey = null;
CERT_PUBLIC_KEY_INFO info;
UInt32 dwCertPublicKeyInfoSize = 0;
IntPtr pCertPublicKeyInfo = IntPtr.Zero;
if (RSACryptoServiceProviderExtension.CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING, new IntPtr((int)CRYPT_OUTPUT_TYPES.X509_PUBLIC_KEY_INFO),
DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, ref dwCertPublicKeyInfoSize))
{
data = new byte[dwCertPublicKeyInfoSize];
if (RSACryptoServiceProviderExtension.CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING, new IntPtr((int)CRYPT_OUTPUT_TYPES.X509_PUBLIC_KEY_INFO),
DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, ref dwCertPublicKeyInfoSize))
{
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
try
{
info = (CERT_PUBLIC_KEY_INFO)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(CERT_PUBLIC_KEY_INFO));
publicKey = new byte[info.PublicKey.cbData];
Marshal.Copy(info.PublicKey.pbData, publicKey, 0, publicKey.Length);
}
finally
{
handle.Free();
}
}
else
throw new Win32Exception(Marshal.GetLastWin32Error());
}
else
throw new Win32Exception(Marshal.GetLastWin32Error());
return publicKey;
}
internal static byte[] GetDERFromPEM(string sPEM)
{
UInt32 dwSkip, dwFlags;
UInt32 dwBinarySize = 0;
if (!RSACryptoServiceProviderExtension.CryptStringToBinary(sPEM, (UInt32)sPEM.Length, CRYPT_STRING_FLAGS.CRYPT_STRING_BASE64HEADER, null, ref dwBinarySize, out dwSkip, out dwFlags))
throw new Win32Exception(Marshal.GetLastWin32Error());
byte[] decodedData = new byte[dwBinarySize];
if (!RSACryptoServiceProviderExtension.CryptStringToBinary(sPEM, (UInt32)sPEM.Length, CRYPT_STRING_FLAGS.CRYPT_STRING_BASE64HEADER, decodedData, ref dwBinarySize, out dwSkip, out dwFlags))
throw new Win32Exception(Marshal.GetLastWin32Error());
return decodedData;
}
#endregion Methods
#region P/Invoke Constants
internal enum CRYPT_ACQUIRE_CONTEXT_FLAGS : uint
{
CRYPT_NEWKEYSET = 0x8,
CRYPT_DELETEKEYSET = 0x10,
CRYPT_MACHINE_KEYSET = 0x20,
CRYPT_SILENT = 0x40,
CRYPT_DEFAULT_CONTAINER_OPTIONAL = 0x80,
CRYPT_VERIFYCONTEXT = 0xF0000000
}
internal enum CRYPT_PROVIDER_TYPE : uint
{
PROV_RSA_FULL = 1
}
internal enum CRYPT_DECODE_FLAGS : uint
{
NONE = 0,
CRYPT_DECODE_ALLOC_FLAG = 0x8000
}
internal enum CRYPT_ENCODING_FLAGS : uint
{
PKCS_7_ASN_ENCODING = 0x00010000,
X509_ASN_ENCODING = 0x00000001,
}
internal enum CRYPT_OUTPUT_TYPES : int
{
X509_PUBLIC_KEY_INFO = 8,
RSA_CSP_PUBLICKEYBLOB = 19,
PKCS_RSA_PRIVATE_KEY = 43,
PKCS_PRIVATE_KEY_INFO = 44
}
internal enum CRYPT_STRING_FLAGS : uint
{
CRYPT_STRING_BASE64HEADER = 0,
CRYPT_STRING_BASE64 = 1,
CRYPT_STRING_BINARY = 2,
CRYPT_STRING_BASE64REQUESTHEADER = 3,
CRYPT_STRING_HEX = 4,
CRYPT_STRING_HEXASCII = 5,
CRYPT_STRING_BASE64_ANY = 6,
CRYPT_STRING_ANY = 7,
CRYPT_STRING_HEX_ANY = 8,
CRYPT_STRING_BASE64X509CRLHEADER = 9,
CRYPT_STRING_HEXADDR = 10,
CRYPT_STRING_HEXASCIIADDR = 11,
CRYPT_STRING_HEXRAW = 12,
CRYPT_STRING_NOCRLF = 0x40000000,
CRYPT_STRING_NOCR = 0x80000000
}
#endregion P/Invoke Constants
#region P/Invoke Structures
[StructLayout(LayoutKind.Sequential)]
internal struct CRYPT_OBJID_BLOB
{
internal UInt32 cbData;
internal IntPtr pbData;
}
[StructLayout(LayoutKind.Sequential)]
internal struct CRYPT_ALGORITHM_IDENTIFIER
{
internal IntPtr pszObjId;
internal CRYPT_OBJID_BLOB Parameters;
}
[StructLayout(LayoutKind.Sequential)]
struct CRYPT_BIT_BLOB
{
internal UInt32 cbData;
internal IntPtr pbData;
internal UInt32 cUnusedBits;
}
[StructLayout(LayoutKind.Sequential)]
struct CERT_PUBLIC_KEY_INFO
{
internal CRYPT_ALGORITHM_IDENTIFIER Algorithm;
internal CRYPT_BIT_BLOB PublicKey;
}
#endregion P/Invoke Structures
#region P/Invoke Functions
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CryptDestroyKey(IntPtr hKey);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CryptImportKey(IntPtr hProv, byte[] pbKeyData, UInt32 dwDataLen, IntPtr hPubKey, UInt32 dwFlags, ref IntPtr hKey);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CryptReleaseContext(IntPtr hProv, Int32 dwFlags);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CryptAcquireContext(ref IntPtr hProv, string pszContainer, string pszProvider, CRYPT_PROVIDER_TYPE dwProvType, CRYPT_ACQUIRE_CONTEXT_FLAGS dwFlags);
[DllImport("crypt32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CryptStringToBinary(string sPEM, UInt32 sPEMLength, CRYPT_STRING_FLAGS dwFlags, [Out] byte[] pbBinary, ref UInt32 pcbBinary, out UInt32 pdwSkip, out UInt32 pdwFlags);
[DllImport("crypt32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CryptDecodeObjectEx(CRYPT_ENCODING_FLAGS dwCertEncodingType, IntPtr lpszStructType, byte[] pbEncoded, UInt32 cbEncoded, CRYPT_DECODE_FLAGS dwFlags, IntPtr pDecodePara, ref byte[] pvStructInfo, ref UInt32 pcbStructInfo);
[DllImport("crypt32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CryptDecodeObject(CRYPT_ENCODING_FLAGS dwCertEncodingType, IntPtr lpszStructType, byte[] pbEncoded, UInt32 cbEncoded, CRYPT_DECODE_FLAGS flags, [In, Out] byte[] pvStructInfo, ref UInt32 cbStructInfo);
#endregion P/Invoke Functions
}
}
签名规则使用了支付宝的就可以了,见下面我的回答。代码比较繁琐,不知道有没有简洁的方法。其他的人回答我没时间去试,不知道可以不。
– 缘分0919 4年前