Skip to main content

IPN code samples

IPN code samples

Last updated: 13-Oct-2021
Rate this article:

PHP


<?php
/* Instant Payment Notification */
$pass        = "AABBCCDDEEFF";    /* pass to compute HASH */
$result        = "";                 /* string for compute HASH for received data */
$return        = "";                 /* string to compute HASH for return result */
$signature    = $_POST["HASH"];    /* HASH received */
$body        = "";
/* read info received */
ob_start();
while(list($key, $val) = each($_POST)){
    $$key=$val;
    /* get values */
echo '<pre>';
//*********FUNCTIONS FOR HMAC*********
function ArrayExpand($array){
$retval = "";
foreach($array as $i => $value){
if(is_array($value)){
$retval .= ArrayExpand($value);
}
else{
$size = strlen($value);
$retval .= $size.$value;
}
}
return $retval;
}
$body = ob_get_contents();
ob_end_flush();
$date_return = date("YmdHis");
$return = strlen($_POST["IPN_PID"][0]).$_POST["IPN_PID"][0].strlen($_POST["IPN_PNAME"][0]).$_POST["IPN_PNAME"][0];
$return .= strlen($_POST["IPN_DATE"]).$_POST["IPN_DATE"].strlen($date_return).$date_return;
function ArrayExpand($array){
    $retval = "";
    for($i = 0; $i < sizeof($array); $i++){
        $size        = strlen(StripSlashes($array[$i]));  /*StripSlashes function to be used only for PHP versions <= PHP 5.3.0, only if the magic_quotes_gpc function is enabled */
        $retval    .= $size.StripSlashes($array[$i]);  /*StripSlashes function to be used only for PHP versions <= PHP 5.3.0, only if the magic_quotes_gpc function is enabled */
    }
    return $retval;
}
function hmac ($key, $data){
   $b = 64; // byte length for md5
   if (strlen($key) > $b) {
       $key = pack("H*",md5($key));
   }
   $key  = str_pad($key, $b, chr(0x00));
   $ipad = str_pad('', $b, chr(0x36));
   $opad = str_pad('', $b, chr(0x5c));
   $k_ipad = $key ^ $ipad ;
   $k_opad = $key ^ $opad;
   return md5($k_opad  . pack("H*",md5($k_ipad . $data)));
}
$hash =  hmac($pass, $result); /* HASH for data received */
$body .= $result."\r\n\r\nHash: ".$hash."\r\n\r\nSignature: ".$signature."\r\n\r\nReturnSTR: ".$return;
if($hash == $signature){
    echo "Verified OK!";
    /* ePayment response */
    $result_hash =  hmac($pass, $return);
    echo "<EPAYMENT>".$date_return."|".$result_hash."</EPAYMENT>";
    /* Begin automated procedures (START YOUR CODE)*/

}else{
    /* warning email */
    mail("your_address@example.com","BAD IPN Signature", $body,"");
}
?>

Java


import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;

@RestController
@RequestMapping("/ipn")
public class IpnController {
    private String secretKey = "yoursecretkey";
    private String algorithm = "HmacMD5";

    @RequestMapping(method = RequestMethod.POST)
    public String handleRequest(HttpServletRequest request) {

        Map<String, String[]> parameters = request.getParameterMap();

        String receivedRequestSignature = request.getParameter("HASH");

        String calculatedRequestSignature = calculateRequestSignature(parameters);

        String responseDate = getResponseDate();

        String responseSignature = calculateResponseSignature(request, parameters, responseDate);

        if(calculatedRequestSignature.equals(receivedRequestSignature)) {
            String response = "Verified OK! <EPAYMENT>" + responseDate + "|" + responseSignature + "</EPAYMENT>";
            handleIpn(parameters);
            return response;
        } else {
            // LOG OR EMAIL THIS OCCURRENCE
            return "Bad request!";
        }
    }

    private String calculateResponseSignature(HttpServletRequest request, Map<String, String[]> parameters, String responseDate) {
        String responseStringToSign = parameters.get("IPN_PID")[0].length() + parameters.get("IPN_PID")[0] +
                    parameters.get("IPN_PNAME")[0].length() + parameters.get("IPN_PNAME")[0] +
                    request.getParameter("IPN_DATE").length() + request.getParameter("IPN_DATE") +
                    responseDate.length() + responseDate;
        return hmac(responseStringToSign);
    }

    private String getResponseDate() {
        String pattern = "yyyyMMddHHmmss";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        return simpleDateFormat.format(new Date());
    }

    private String calculateRequestSignature(Map<String, String[]> parameters) {
        String requestStringToVerify = "";
        for (Map.Entry<String, String[]> entry : parameters.entrySet()) {
            if (entry.getKey().equals("HASH")) continue;
            // convert parameter values array to ArrayList to be able to use streams
            ArrayList<String> valueList = new ArrayList<String>(Arrays.asList(entry.getValue()));
            // append to request string each length and value
            requestStringToVerify = valueList
                    .stream()
                    .reduce(requestStringToVerify,
                            (partialResult, value)
                                    -> partialResult + (value == null ? 0 : value.getBytes().length + value));
        }
        return hmac(requestStringToVerify);
    }

    private void handleIpn(Map<String, String[]> parameters) {
        // INSERT YOUR HANDLING CODE HERE
    }

    private String hmac(String stringForHash) {
        SecretKeySpec key = new SecretKeySpec((secretKey).getBytes(), algorithm);
        try {
            Mac mac = Mac.getInstance(algorithm);
            mac.init(key);
            byte[] bytes = mac.doFinal(stringForHash.getBytes());
            return toHexString(bytes);
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            e.printStackTrace();
            return null;
        }
    }

    private String toHexString(byte[] bytes) {
        Formatter form = new Formatter();
        String result;

        for (byte b : bytes) {
            form.format("%02x", b);
        }
        result = form.toString();
        form.close();
        return result;
    }
}

Perl


#!/usr/bin/perl
# Simple IPN implementation for 2Checkout
# PERL version
use strict;
use CGI;
use Digest::HMAC_MD5 qw(hmac_md5_hex);
# modify your settings here
my $mykey='testkey';
# / end modifications area
my $q = new CGI;
my @name = $q->param;
print "Content-type: text/html\n\n";
my $in_md5='';
my $first_product = '';
my $first_pid = '';
# Main loop
foreach my $par (@name) {
  next if ($par=~/HASH/i);
      if ($q->param($par) ne '') { #parameter not empty
        my @mylist = $q->param($par);
          if (scalar(@mylist)) { #multi valued
            foreach my $el (@mylist) {
              $in_md5.=length($el).$el;
          if ($par eq "IPN_PNAME[]") { $first_product = $mylist[0]; }
          if ($par eq "IPN_PID[]") { $first_pid = $mylist[0]; }
            }
          } else { #single valued
            $in_md5.=length($q->param($par)).$q->param($par);
          }
      } else { #empty parameter
        $in_md5.='0';
      }
}

my $md5 = $q->param('HASH');
my $md5Verify = hmac_md5_hex($in_md5, $mykey);
my $response='';
if ($md5=~/^$md5Verify$/i) { # ok
    # The notification is genuine / verified
    # Write your own code here to insert the data into a database or email it in a specified format
    # The code below will confirm the request
  $response = length($first_pid).$first_pid.length($first_product).$first_product.length($q->param("IPN_DATE")).$q->param("IPN_DATE");
  my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time);
  my $now = (1900+$year).sprintf("%02d", $mon+1).sprintf("%02d", $mday).sprintf("%02d", $hour).sprintf("%02d", $min).sprintf("%02d", $sec);
  $response.=length($now).$now;
  my $md5response = hmac_md5_hex($response, $mykey);
  print '<EPAYMENT>'.$now.'|'.$md5response.'</EPAYMENT>';
} else { # not ok
  print '<EPAYMENT>Error. Cannot verify signature.</EPAYMENT>';
}


ASP


<!-- The two files mentioned below are included in this script. Use the code to create standalone files.-->
<!--#include file="md5.asp"-->
<!--#include file="functions.inc.asp"-->
<%
dim pass ' pass to compute HASH 
pass = "IPN_SECRET_KEY"
dim baseStringForHash 'string to compute HASH from received data
dim baseStringForReturnHash 'string to compute HASH from baseStringForReturnHash result
dim signature 'HASH received 
baseStringForHash = ""
for a = 1 to Request.Form.Count
    if Request.Form.Key(a) <> "HASH" then
        for b = 1 to Request.Form.Item(a).Count
            baseStringForHash = baseStringForHash & Len( StripSlashes(Request.Form.Item(a).Item(b)) ) & StripSlashes(Request.Form.Item(a).Item(b) ' StripSlashes function to be used only for PHP versions <= PHP 5.3.0, only if the magic_quotes_gpc function is enabled  
    end if
next
date_return = year(date) & month(date) & day(date) & hour(time) & minute(time) & second(time)
signature = Request.Form("HASH")
hash = hmac(pass, baseStringForHash)
' DEBUG:
'response.Write(baseStringForHash)
'response.Write("Hash:"&hash)
'response.Write("Signature:"&signature)

if hash = signature then 
    response.Write("Verified OK!")
    baseStringForReturnHash = ""
    baseStringForReturnHash = baseStringForReturnHash & Len( Request.Form("IPN_PID[]").Item(1) ) & Request.Form("IPN_PID[]").Item(1)
    baseStringForReturnHash = baseStringForReturnHash & Len( Request.Form("IPN_PNAME[]").Item(1) ) & Request.Form("IPN_PNAME[]").Item(1)
    baseStringForReturnHash = baseStringForReturnHash & Len( Request.Form("IPN_DATE") ) & Request.Form("IPN_DATE")
    baseStringForReturnHash = baseStringForReturnHash & len(date_return) & date_return
    response.Write(VbCrLf)
    response.Write("BASE STRING FOR HASH: " & baseStringForReturnHash)
    response.Write(VbCrLf)
    
    ' Received response
    response.Write( "<EPAYMENT>" & date_return & "|" & hmac(pass, baseStringForReturnHash) & "</EPAYMENT>" )
    
    ' Begin automated procedures (START YOUR CODE)
    
    
else
    ' It is a problem (START YOUR CODE)
    response.Write("!!! BAD !!!")
    response.Write( VbCrLf & VbCrLf )
    
    response.Write("Base string:")
    response.Write( VbCrLf )
    response.Write(baseStringForHash)
    response.Write( VbCrLf & VbCrLf )
    
    response.Write(signature & " != " & hash)
    response.Write( VbCrLf & VbCrLf )
end if
%>
<!-- file="md5.asp"-->
<%
Private Const BITS_TO_A_BYTE=8
Private Const BYTES_TO_A_WORD=4
Private Const BITS_TO_A_WORD=32
Private m_lOnBits(30)
Private m_l2Power(30)
m_lOnBits(0)=CLng(1)
m_lOnBits(1)=CLng(3)
m_lOnBits(2)=CLng(7)
m_lOnBits(3)=CLng(15)
m_lOnBits(4)=CLng(31)
m_lOnBits(5)=CLng(63)
m_lOnBits(6)=CLng(127)
m_lOnBits(7)=CLng(255)
m_lOnBits(8)=CLng(511)
m_lOnBits(9)=CLng(1023)
m_lOnBits(10)=CLng(2047)
m_lOnBits(11)=CLng(4095)
m_lOnBits(12)=CLng(8191)
m_lOnBits(13)=CLng(16383)
m_lOnBits(14)=CLng(32767)
m_lOnBits(15)=CLng(65535)
m_lOnBits(16)=CLng(131071)
m_lOnBits(17)=CLng(262143)
m_lOnBits(18)=CLng(524287)
m_lOnBits(19)=CLng(1048575)
m_lOnBits(20)=CLng(2097151)
m_lOnBits(21)=CLng(4194303)
m_lOnBits(22)=CLng(8388607)
m_lOnBits(23)=CLng(16777215)
m_lOnBits(24)=CLng(33554431)
m_lOnBits(25)=CLng(67108863)
m_lOnBits(26)=CLng(134217727)
m_lOnBits(27)=CLng(268435455)
m_lOnBits(28)=CLng(536870911)
m_lOnBits(29)=CLng(1073741823)
m_lOnBits(30)=CLng(2147483647)
m_l2Power(0)=CLng(1)
m_l2Power(1)=CLng(2)
m_l2Power(2)=CLng(4)
m_l2Power(3)=CLng(8)
m_l2Power(4)=CLng(16)
m_l2Power(5)=CLng(32)
m_l2Power(6)=CLng(64)
m_l2Power(7)=CLng(128)
m_l2Power(8)=CLng(256)
m_l2Power(9)=CLng(512)
m_l2Power(10)=CLng(1024)
m_l2Power(11)=CLng(2048)
m_l2Power(12)=CLng(4096)
m_l2Power(13)=CLng(8192)
m_l2Power(14)=CLng(16384)
m_l2Power(15)=CLng(32768)
m_l2Power(16)=CLng(65536)
m_l2Power(17)=CLng(131072)
m_l2Power(18)=CLng(262144)
m_l2Power(19)=CLng(524288)
m_l2Power(20)=CLng(1048576)
m_l2Power(21)=CLng(2097152)
m_l2Power(22)=CLng(4194304)
m_l2Power(23)=CLng(8388608)
m_l2Power(24)=CLng(16777216)
m_l2Power(25)=CLng(33554432)
m_l2Power(26)=CLng(67108864)
m_l2Power(27)=CLng(134217728)
m_l2Power(28)=CLng(268435456)
m_l2Power(29)=CLng(536870912)
m_l2Power(30)=CLng(1073741824)
Private Function LShift(lValue,iShiftBits)
  If iShiftBits=0 Then
    LShift=lValue
    Exit Function
  ElseIf iShiftBits=31 Then
    If lValue And 1 Then
      LShift=&H80000000
    Else
      LShift=0
    End If
    Exit Function
  ElseIf iShiftBits<0 Or iShiftBits>31 Then
    Err.Raise 6
  End If
  If (lValue And m_l2Power(31-iShiftBits)) Then
    LShift=((lValue And m_lOnBits(31-(iShiftBits+1)))*m_l2Power(iShiftBits)) Or &H80000000
  Else
    LShift=((lValue And m_lOnBits(31-iShiftBits))*m_l2Power(iShiftBits))
  End If
End Function
Private Function RShift(lValue,iShiftBits)
  If iShiftBits=0 Then
    RShift=lValue
    Exit Function
  ElseIf iShiftBits=31 Then
    If lValue And &H80000000 Then
      RShift=1
    Else
      RShift=0
    End If
    Exit Function
  ElseIf iShiftBits<0 Or iShiftBits>31 Then
    Err.Raise 6
  End If
  
  RShift=(lValue And &H7FFFFFFE)\m_l2Power(iShiftBits)
  If (lValue And &H80000000) Then
    RShift=(RShift Or (&H40000000\m_l2Power(iShiftBits-1)))
  End If
End Function
Private Function RotateLeft(lValue,iShiftBits)
  RotateLeft=LShift(lValue,iShiftBits) Or RShift(lValue,(32-iShiftBits))
End Function
Private Function AddUnsigned(lX,lY)
  Dim lX4
  Dim lY4
  Dim lX8
  Dim lY8
  Dim lResult
  lX8=lX And &H80000000
  lY8=lY And &H80000000
  lX4=lX And &H40000000
  lY4=lY And &H40000000
  lResult=(lX And &H3FFFFFFF)+(lY And &H3FFFFFFF)
  If lX4 And lY4 Then
    lResult=lResult Xor &H80000000 Xor lX8 Xor lY8
  ElseIf lX4 Or lY4 Then
    If lResult And &H40000000 Then
      lResult=lResult Xor &HC0000000 Xor lX8 Xor lY8
    Else
      lResult=lResult Xor &H40000000 Xor lX8 Xor lY8
    End If
  Else
    lResult=lResult Xor lX8 Xor lY8
  End If
  AddUnsigned=lResult
End Function
Private Function F(x,y,z)
  F=(x And y) Or ((Not x) And z)
End Function
Private Function G(x,y,z)
  G=(x And z) Or (y And (Not z))
End Function
Private Function H(x,y,z)
  H=(x Xor y Xor z)
End Function
Private Function I(x,y,z)
  I=(y Xor (x Or (Not z)))
End Function
Private Sub FF(a,b,c,d,x,s,ac)
  a=AddUnsigned(a,AddUnsigned(AddUnsigned(F(b,c,d),x),ac))
  a=RotateLeft(a,s)
  a=AddUnsigned(a,b)
End Sub
Private Sub GG(a,b,c,d,x,s,ac)
  a=AddUnsigned(a,AddUnsigned(AddUnsigned(G(b,c,d),x),ac))
  a=RotateLeft(a,s)
  a=AddUnsigned(a,b)
End Sub
Private Sub HH(a,b,c,d,x,s,ac)
  a=AddUnsigned(a,AddUnsigned(AddUnsigned(H(b,c,d),x),ac))
  a=RotateLeft(a,s)
  a=AddUnsigned(a,b)
End Sub
Private Sub II(a,b,c,d,x,s,ac)
  a=AddUnsigned(a,AddUnsigned(AddUnsigned(I(b,c,d),x),ac))
  a=RotateLeft(a,s)
  a=AddUnsigned(a,b)
End Sub
Private Function ConvertToWordArray(sMessage)
  Dim lMessageLength
  Dim lNumberOfWords
  Dim lWordArray()
  Dim lBytePosition
  Dim lByteCount
  Dim lWordCount
  Dim lByteValue    ' need these variables to handle byte value and input argument type
  Dim lMessageType
  Const MODULUS_BITS=512
  Const CONGRUENT_BITS=448
  
  lMessageType=Vartype(sMessage)
  Select Case lMessageType    ' strings or Variant Byte Arrays: nothing else!
    Case 8    : lMessageLength=Len(sMessage)
    Case 8209 : lMessageLength=LenB(sMessage)
    Case Else Err.Raise -1,"MD5","Unknown Type passed to MD5 function"
  End Select
  
  lNumberOfWords=(((lMessageLength+((MODULUS_BITS-CONGRUENT_BITS)\BITS_TO_A_BYTE))\(MODULUS_BITS\BITS_TO_A_BYTE))+1)*(MODULUS_BITS\BITS_TO_A_WORD)
  ReDim lWordArray(lNumberOfWords-1)
  
  lBytePosition=0
  lByteCount=0
  Do Until lByteCount >=lMessageLength
    lWordCount=lByteCount\BYTES_TO_A_WORD
    lBytePosition=(lByteCount Mod BYTES_TO_A_WORD)*BITS_TO_A_BYTE
    Select Case lMessageType    ' get the next byte value
      Case 8    : lByteValue = Asc (Mid (sMessage,lByteCount+1,1))
      Case 8209 : lByteValue = AscB(MidB(sMessage,lByteCount+1,1))
    End Select
    lWordArray(lWordCount)=lWordArray(lWordCount) Or LShift(lByteValue,lBytePosition)
    lByteCount=lByteCount+1
  Loop
  lWordCount=lByteCount\BYTES_TO_A_WORD
  lBytePosition=(lByteCount Mod BYTES_TO_A_WORD)*BITS_TO_A_BYTE
  lWordArray(lWordCount)=lWordArray(lWordCount) Or LShift(&H80,lBytePosition)
  lWordArray(lNumberOfWords-2)=LShift(lMessageLength,3)
  lWordArray(lNumberOfWords-1)=RShift(lMessageLength,29)
  
  ConvertToWordArray=lWordArray
End Function
Private Function WordToHex(lValue)
  Dim lByte
  Dim lCount
  
  For lCount=0 To 3
    lByte=RShift(lValue,lCount*BITS_TO_A_BYTE) And m_lOnBits(BITS_TO_A_BYTE-1)
    WordToHex=WordToHex & Right("0" & Hex(lByte),2)
  Next
End Function
Public Function MD5(sMessage)
  Dim x
  Dim k
  Dim AA
  Dim BB
  Dim CC
  Dim DD
  Dim a
  Dim b
  Dim c
  Dim d
  
  Const S11=7
  Const S12=12
  Const S13=17
  Const S14=22
  Const S21=5
  Const S22=9
  Const S23=14
  Const S24=20
  Const S31=4
  Const S32=11
  Const S33=16
  Const S34=23
  Const S41=6
  Const S42=10
  Const S43=15
  Const S44=21
  x=ConvertToWordArray(sMessage)
  
  a=&H67452301
  b=&HEFCDAB89
  c=&H98BADCFE
  d=&H10325476
  For k=0 To UBound(x) Step 16
    AA=a
    BB=b
    CC=c
    DD=d
    FF a,b,c,d,x(k+0),S11,&HD76AA478
    FF d,a,b,c,x(k+1),S12,&HE8C7B756
    FF c,d,a,b,x(k+2),S13,&H242070DB
    FF b,c,d,a,x(k+3),S14,&HC1BDCEEE
    FF a,b,c,d,x(k+4),S11,&HF57C0FAF
    FF d,a,b,c,x(k+5),S12,&H4787C62A
    FF c,d,a,b,x(k+6),S13,&HA8304613
    FF b,c,d,a,x(k+7),S14,&HFD469501
    FF a,b,c,d,x(k+8),S11,&H698098D8
    FF d,a,b,c,x(k+9),S12,&H8B44F7AF
    FF c,d,a,b,x(k+10),S13,&HFFFF5BB1
    FF b,c,d,a,x(k+11),S14,&H895CD7BE
    FF a,b,c,d,x(k+12),S11,&H6B901122
    FF d,a,b,c,x(k+13),S12,&HFD987193
    FF c,d,a,b,x(k+14),S13,&HA679438E
    FF b,c,d,a,x(k+15),S14,&H49B40821
    GG a,b,c,d,x(k+1),S21,&HF61E2562
    GG d,a,b,c,x(k+6),S22,&HC040B340
    GG c,d,a,b,x(k+11),S23,&H265E5A51
    GG b,c,d,a,x(k+0),S24,&HE9B6C7AA
    GG a,b,c,d,x(k+5),S21,&HD62F105D
    GG d,a,b,c,x(k+10),S22,&H2441453
    GG c,d,a,b,x(k+15),S23,&HD8A1E681
    GG b,c,d,a,x(k+4),S24,&HE7D3FBC8
    GG a,b,c,d,x(k+9),S21,&H21E1CDE6
    GG d,a,b,c,x(k+14),S22,&HC33707D6
    GG c,d,a,b,x(k+3),S23,&HF4D50D87
    GG b,c,d,a,x(k+8),S24,&H455A14ED
    GG a,b,c,d,x(k+13),S21,&HA9E3E905
    GG d,a,b,c,x(k+2),S22,&HFCEFA3F8
    GG c,d,a,b,x(k+7),S23,&H676F02D9
    GG b,c,d,a,x(k+12),S24,&H8D2A4C8A
        
    HH a,b,c,d,x(k+5),S31,&HFFFA3942
    HH d,a,b,c,x(k+8),S32,&H8771F681
    HH c,d,a,b,x(k+11),S33,&H6D9D6122
    HH b,c,d,a,x(k+14),S34,&HFDE5380C
    HH a,b,c,d,x(k+1),S31,&HA4BEEA44
    HH d,a,b,c,x(k+4),S32,&H4BDECFA9
    HH c,d,a,b,x(k+7),S33,&HF6BB4B60
    HH b,c,d,a,x(k+10),S34,&HBEBFBC70
    HH a,b,c,d,x(k+13),S31,&H289B7EC6
    HH d,a,b,c,x(k+0),S32,&HEAA127FA
    HH c,d,a,b,x(k+3),S33,&HD4EF3085
    HH b,c,d,a,x(k+6),S34,&H4881D05
    HH a,b,c,d,x(k+9),S31,&HD9D4D039
    HH d,a,b,c,x(k+12),S32,&HE6DB99E5
    HH c,d,a,b,x(k+15),S33,&H1FA27CF8
    HH b,c,d,a,x(k+2),S34,&HC4AC5665
    II a,b,c,d,x(k+0),S41,&HF4292244
    II d,a,b,c,x(k+7),S42,&H432AFF97
    II c,d,a,b,x(k+14),S43,&HAB9423A7
    II b,c,d,a,x(k+5),S44,&HFC93A039
    II a,b,c,d,x(k+12),S41,&H655B59C3
    II d,a,b,c,x(k+3),S42,&H8F0CCC92
    II c,d,a,b,x(k+10),S43,&HFFEFF47D
    II b,c,d,a,x(k+1),S44,&H85845DD1
    II a,b,c,d,x(k+8),S41,&H6FA87E4F
    II d,a,b,c,x(k+15),S42,&HFE2CE6E0
    II c,d,a,b,x(k+6),S43,&HA3014314
    II b,c,d,a,x(k+13),S44,&H4E0811A1
    II a,b,c,d,x(k+4),S41,&HF7537E82
    II d,a,b,c,x(k+11),S42,&HBD3AF235
    II c,d,a,b,x(k+2),S43,&H2AD7D2BB
    II b,c,d,a,x(k+9),S44,&HEB86D391
    a=AddUnsigned(a,AA)
    b=AddUnsigned(b,BB)
    c=AddUnsigned(c,CC)
    d=AddUnsigned(d,DD)
  Next
  
  MD5=LCase(WordToHex(a) & WordToHex(b) & WordToHex(c) & WordToHex(d))
End Function
%>

<!-- file="functions.inc.asp"-->
<%
function ArrayExpand (Vector)
    dim i
    for i = 0 to Vector.Count
        size = Len(StripSlashes(Vector(i)))  ' StripSlashes function to be used only for PHP versions <= PHP 5.3.0, only if the magic_quotes_gpc function is enabled
        result = result&size&SripSlashes(Vector(i))
    next
end function
function StripSlashes (string)   ' StripSlashes function to be used only for PHP versions <= PHP 5.3.0, only if the magic_quotes_gpc function is enabled
    if Len(string) <> 0 then 
        string = Replace(string, "\\", "\")
        string = Replace(string, "\'", "'")
    end if
    StripSlashes = string   ' StripSlashes function to be used only for PHP versions <= PHP 5.3.0, only if the magic_quotes_gpc function is enabled
end function
function hmac(key, data)
    b = 64
    if len(key) > b then
        key = pack(md5(key))
    end if 
    char1 = chr(0)
    char2 = chr(54)
    char3 = chr(92)
    key = str_pad(key, b, char1)
    ipad = str_pad("", b, char2)
    opad = str_pad("", b, char3)
    k_opad = myXor(key, opad)
    k_ipad  =  myXor (key, ipad)
    hmac = md5(k_opad&pack(md5(k_ipad&data)))
end function
Function pack(S)
  Dim i, MultiByte
  For i=1 To Len(S)
    MultiByte = MultiByte &  Chr(HexToDec(Mid(S,i,2)))
    i = i+1
  Next
  pack = MultiByte
End Function
function str_pad(originalString, no, str)
    dim i
    length  = len(originalString)
    diff = no - length
    if diff > 0 then
        for i=1 to diff
            originalString = originalString & str
        next
    end if
    str_pad = originalString
end function
Function HexToDec(hexVal)
    HexToDec = Clng("&H" & hexVal)
End Function
function myXor (str1, str2)
    dim returnVal, i, j
    for i = 1 to len(str1)
        returnVal = returnVal & chr(asc(Mid(str1,i,1)) xor asc(Mid(str2,i,1)))
    next
    myXor = returnVal
end function
function myAnd (str1, str2)
    dim returnVal, i, j
    for i = 1 to len(str1)
        returnVal = returnVal & chr(asc(Mid(str1,i,1)) and asc(Mid(str2,i,1)))
    next
    myAnd = returnVal
end function

%>

C# 

using System;    
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;

namespace VerifoneIPNSample
{
    public class IpnSignatureHandler
    {
        public string calculateSignature(
            IEnumerable<KeyValuePair<string, string>> requestPayloadValues,
            string secretKey,
            string currentDate
            )
        {
            int size = 0;
            string hash = string.Empty;
            UTF8Encoding encoding = new UTF8Encoding();
            System.Text.StringBuilder PlainDataTohash = new System.Text.StringBuilder();
            var res = requestPayloadValues.GetEnumerator();

            while (res.MoveNext())
            {
                switch (res.Current.Key)
                {
                    case "IPN_PID[]":
                        size = res.Current.Value.Length; 
                                        
                        PlainDataTohash.Append(size); 
                        PlainDataTohash.Append(res.Current.Value); 
                        break; 
                    case "IPN_PNAME[]":
                        size = res.Current.Value.Length; 
                                        
                        PlainDataTohash.Append(size); 
                        PlainDataTohash.Append(res.Current.Value); 
                        break; 
                    case "IPN_DATE":
                        size = res.Current.Value.Length; 
                                        
                        PlainDataTohash.Append(size); 
                        PlainDataTohash.Append(res.Current.Value); 
                        break; 
                }
            }
            size = currentDate.Length;
            PlainDataTohash.Append(size);
            PlainDataTohash.Append(currentDate);
            
            Console.WriteLine(PlainDataTohash);

            string pass = secretKey;
            byte[] passBytes = encoding.GetBytes(pass);
            
            HMACMD5 hmacmd5 = new HMACMD5(passBytes);
            string HashData = PlainDataTohash.ToString();
            
            byte[] baseStringForHashBytes = encoding.GetBytes(HashData);
            byte[] hashBytes = hmacmd5.ComputeHash(baseStringForHashBytes);
            
            hash = ByteToString(hashBytes);

            return hash;
        }

        private static string ByteToString(byte[] buff)
        {
            string sbinary = "";
            for (int i = 0; i < buff.Length; i++)
            {
                sbinary += buff[i].ToString("x2"); // hex format
            }
            return (sbinary);
        }

        public string generateTag(
            IEnumerable<KeyValuePair<string, string>> requestPayloadValues,
            string secretKey
            )
        {
            var now = DateTime.Now.ToString("yyyyMMddHHmmss");
            var responseHash = calculateSignature(requestPayloadValues, secretKey, now);
            var response = now + "|" + responseHash;

            return "<EPAYMENT>" + response + "</EPAYMENT>";
        }
    }
}

C# - IPN Signature Handler Test Example  

using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace VerifoneIPNSample.Tests
{
    [TestClass()]
    public class IpnSignatureHandlerTests
    {
        [TestMethod()]
        public void TestCalculateSignature() {
            List<KeyValuePair<string, string>> requestPayloadValues = new List<KeyValuePair<string, string>>()
            {
                new KeyValuePair<string, string>("IPN_PID[]", "1"),
                new KeyValuePair<string, string>("IPN_PNAME[]", "Software program"),
                new KeyValuePair<string, string>("IPN_DATE", "20050303123434"),
            };

            string testedDate = "20050303123434";
            string secretKey = "test";
            
            IpnSignatureHandler ipnHandler = new IpnSignatureHandler();

            var responseHash = ipnHandler.calculateSignature(requestPayloadValues, secretKey, testedDate);
            
            Console.WriteLine(responseHash);

            Assert.AreEqual(responseHash, "3d7a5eb5557b70a80e5141c4fee0ed0d");
        }
    }
}
Rate this article:
Logo of Verifone