I'm trying to get use Sage Pay's Form Integration with my website. I thought it'd be fairly straightforward but it's not proving to be so far. I'm working in .NET so I downloaded the .NET Integration Kit from their support page hoping that I'd be able to see how it works and replicate it.
Unfortunately, the example kits are far too complex for what they are. They should be extremely simple projects which allow the workings to be clearly understood, not complete, nicely encapsulated solutions. It's very complicated when there are methods in one code file that call methods from a couple of others which use values stored in the Web.Config file... For the purposes of education it'd be much easier if the code was typed out long-hand in one file, with settings values explicitly declared. Of course it wouldn't be pretty and hopefully no decent developer would replicate such a clumsy approach, but it would make it easier to see what's going on!
Anyway, rant over. My problem is that when I submit my data to Sage Pay I get the error
"5068: The encryption method is not supported by this protocol version"
To do my encryption I added the SagePay.IntegrationKit.DotNet.DLL file to my project and then called the SagePay.IntegrationKit.Cryptography.EncryptAndEncode
method, which produces an encrypted string that looks the same as the one produced in the working example from the website. Unfortunately, when I submit the string to Sage Pay's server I get the error mentioned.
I've just got this working with this code to do the encryption:
public string SagePayEncryptAndEncode(string inputText, string key)
{
using (var AES = new RijndaelManaged())
{
// Set the mode, padding and block size for the key
AES.Padding = PaddingMode.PKCS7;
AES.Mode = CipherMode.CBC;
AES.KeySize = 128;
AES.BlockSize = 128;
// Convert key and input text into byte arrays
Byte[] keyAndIvBytes = UTF8Encoding.UTF8.GetBytes(key);
Byte[] inputBytes = UTF8Encoding.UTF8.GetBytes(inputText);
// Create streams and encryptor object
using (var memoryStream = new MemoryStream())
using (var cryptoStream = new CryptoStream(memoryStream, AES.CreateEncryptor(keyAndIvBytes, keyAndIvBytes), CryptoStreamMode.Write))
{
// Perform encryption
cryptoStream.Write(inputBytes, 0, inputBytes.Length);
cryptoStream.FlushFinalBlock();
// Get encrypted stream into byte array
var outBytes = memoryStream.ToArray();
// Manually close streams
memoryStream.Close();
cryptoStream.Close();
AES.Clear();
//return Convert.ToBase64String(outBytes);
return BitConverter.ToString(outBytes).Replace("-", String.Empty);
}
}
}
You then need to store the resulting value in the hidden 'Crypt' field and prepend '@'.
<input name='Crypt' type='hidden' value='@<InsertResultHere>' />
One thing to note, it appears to only work using Hex encoding, and not Base64 encoding as the documentation implies.