migrationwebhooksmd5sha2checkout

Migrate from MD5 to SHA in Verifone(2Checkout) webhook responses


Verifone will stop supporting the MD5 algorithm on the 15th of April, 2024 in their platform and forces users to use SHA instead. It is neccessary to responde on the IPN notifications with some hash created by their guide.

Here is a blocks of code on Java that creates response body with hash by MD5 algorithm:

import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;

    String responseBody(IpnRequest request, VerifoneApiKey secret) {
        var ipnPidValues = request.id();
        var ipnNameValues = request.get(IPN_PNAME);
        var ipnDateValue = request.get(IPN_DATE);

        List<String> toEncrypt = ImmutableList.of(
            ipnPidValues, ipnNameValues, ipnDateValue, ipnDateValue
        );

        var hash = hmacMd5(toEncrypt, secret.getValue());
        var responseBody = format("<EPAYMENT>%s|%s</EPAYMENT>", ipnDateValue, hash);
        return responseBody;
    }

    String hmacMd5(Collection<String> values, String key) {
        checkCanEncrypt(values);
        checkNotEmptyOrBlank(key);
        var toEncrypt = compose(values);
        var md5HashFunction = Hashing.hmacMd5(key.getBytes(UTF_8));
        return encrypt(toEncrypt, md5HashFunction);
    }

    String compose(Collection<String> values) {
        return values.stream()
                .map(s -> byteLength(s) + s)
                .collect(Collectors.joining());
    }

    int byteLength(String str) {
        return str.getBytes(UTF_8).length;
    }

This part works and Verifone marks the IPN as successfully delivered, but when Hashing.hmacMd5 is changed to Hashing.hmacSha256 or Hashing.hmacSha512, Verifone says that the notification was delivered with an error and tries to resend it.


Solution

  • Verifone has updated its documentation and control panel, so now it is possible to change expected response algorithm in the IPN settings.

    To migrate the code in question it is necessary to change the response string pattern:

    var responseBody = format("<EPAYMENT>%s|%s</EPAYMENT>", ipnDateValue, hash);

    to

    var responseBody = format("<sig algo=\"sha256\" date=\"%s\">%s</sig>", ipnDateValue, hash);

    and hashing algorithm Hashing.hmacMd5 to Hashing.hmacSha256.