首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >错误:- {“代码”:“403”,“消息”:“HMAC验证失败”}

错误:- {“代码”:“403”,“消息”:“HMAC验证失败”}
EN

Stack Overflow用户
提问于 2015-03-31 11:04:18
回答 3查看 2.4K关注 0票数 5

这里我附加代码和一个由完整代码组成的链接,请看一看:-我的授权头接缝的长度与官方网站payeezy.I中提到的长度相同,我还使我的hmacString与这个链接(https://developer.payeezy.com/content/hmac-validation-failure)中提到的顺序相同。在做了这些之后,我仍然得到了同样的问题。

代码语言:javascript
复制
public static String excutePost(String urlParameters) throws IOException {
        URL url = new URL("https://api-cert.payeezy.com/v1/transactions");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        try {
            // Create connection
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", headerContentType);
            connection.setRequestProperty("apikey ", apikey);
            connection.setRequestProperty("token", MerchantToken);
            connection
                    .setRequestProperty("Authorization", authorizationHeader);
            connection.setRequestProperty("timestamp", ""+epoch);
            connection.setRequestProperty("nonce", ""+nonce);
            connection.setDoOutput(true);
            connection.setReadTimeout(30000);

            // Send request
            DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
            wr.writeBytes(urlParameters);
            wr.flush();
            wr.close();

            // Get Response
            InputStream is = connection.getInputStream();
            BufferedReader rd = new BufferedReader(new InputStreamReader(is));
            String line;
            StringBuffer response = new StringBuffer();
            while ((line = rd.readLine()) != null) {
                response.append(line);
                response.append('\r');
            }
            rd.close();
            return response.toString();

        } catch (Exception e) {

            e.printStackTrace();
            return null;

        } finally {

            if (connection != null) {
                connection.disconnect();
            }
        }
    }

下面是完整的java类代码:- http://piratepad.net/ep/pad/view/ro.WwZ9v6FX1a6/latest

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-04-09 04:46:05

我最终通过在api url hit.Here中发送直接字符串作为参数来解决此错误,我正在发布一些解决错误的代码:-

代码语言:javascript
复制
String str = "{\"amount\":\"1299\",\"merchant_ref\":\"Astonishing-Sale\",\"transaction_type\":\"authorize\",\"credit_card\":{\"card_number\":\"4788250000028291\",\"cvv\":\"123\",\"exp_date\": \"1020\",\"cardholder_name\": \"John Smith\",\"type\": \"visa\"},\"method\": \"credit_card\",\"currency_code\": \"USD\"}";

现在,这个字符串将用于生成我的授权密钥。整个过程定义在下面:-

代码语言:javascript
复制
getSecurityKeys(apikey, pzsecret,str);

private static Map<String, String> getSecurityKeys(String appId,
			String secureId, String payLoad) throws Exception {
		Map<String, String> returnMap = new HashMap<String, String>();
		try {
			returnMap.put(NONCE, Long.toString(nonce));
			returnMap.put(APIKEY, appId);
			returnMap.put(TIMESTAMP, Long.toString(System.currentTimeMillis()));
			returnMap.put(TOKEN, MerchantToken);
			returnMap.put(APISECRET, pzsecret);
			returnMap.put(PAYLOAD, payLoad);
			returnMap.put(AUTHORIZE, getMacValue(returnMap));
			authorizationHeader = returnMap.get(AUTHORIZE);
			return returnMap;

		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e.getMessage(), e);
		}
	}

	public static String getMacValue(Map<String, String> data) throws Exception {
		Mac mac = Mac.getInstance("HmacSHA256");
		String apiSecret = data.get(APISECRET);
		SecretKeySpec secret_key = new SecretKeySpec(apiSecret.getBytes(),
				"HmacSHA256");
		mac.init(secret_key);
		StringBuilder buff = new StringBuilder();
		buff.append(data.get(APIKEY)).append(data.get(NONCE))
				.append(data.get(TIMESTAMP));
		if (data.get(TOKEN) != null)
			buff.append(data.get(TOKEN));
		if (data.get(PAYLOAD) != null)
			buff.append(data.get(PAYLOAD));
		byte[] macHash = mac.doFinal(buff.toString().getBytes("UTF-8"));
		String authorizeString = Base64.encodeBase64String(toHex(macHash));
		return authorizeString;
	}

现在,您可以将直接字符串(即str)作为参数传递给java中的post api。

希望它能帮助其他人在不使用任何依赖项的情况下集成付费支付网关。编码快乐!

票数 3
EN

Stack Overflow用户

发布于 2015-03-31 11:14:02

您必须为每个timestamp请求为生成一个新的timestampnonce,也就是说,每个新的请求都必须有其唯一的timestampnonce

在java中,timestamp可以设置为System.currentTimeMillis()nonce可以使用UUID (UUID.randomUUID().toString())设置。

最后,确保您的Authorization被正确计算(我看到他们使用HMAC-SHA1使用API密钥)。

我希望这能帮到你。

编辑:正如所怀疑的,是您的HMAC-SHA1授权值不正确。在运行您的代码时(在我自己编写了几个代码之后),我会得到以下响应。

代码语言:javascript
复制
Connection = keep-alive
Content-Length = 51
Content-Type = application/json
{"code":"403", "message":"HMAC validation Failure"}

确保您正确地计算了您的HMAC-SHA1值(正如我前面所说)。

请参阅下面(更新的)代码,您可以自己编译和运行这些代码。您将需要Java 8,因为它现在附带了Base 64编码器/解码器。

代码语言:javascript
复制
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.net.URI;
import java.net.URL;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.TimeZone;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

//import org.apache.commons.codec.binary.Base64;

public class MainJava {
    private static final String    myEncoding            = "UTF-8";
    private static final String    myMessageDigest        = "SHA-1";
    private static final String    myKeySpec            = "HmacSHA1";
    private static String        NEWLINE                = "\n";
    private static String        authorizationHeader;
    private static String        contentSha1;
    // private static String keyId = "230297";
    // private static String hmacKey = "tcwR9r1OR85V9bcV5tc7a9d1XkWigjqY";
    private static String        ApiSecretkey        = "0779eb593286b278aaf8cfcf83c8e33bc757d53a8a642b53d24d63bda844da5b";
    private static String        MerchantToken        = "fdoa-a480ce8951daa73262734cf102641994c1e55e7cdf4c02b6";
    private static String        reportingToken        = "e56a0223d0415067";
    private static String        apikey                = "XSjbv8PLDINJ28qXLEYAhcrz8rxKXQ4Y";
    private static long            nonce;
    public static String        headerContentType    = "application/json";
    private static long            epoch;

    public static void main(String[] args) throws Exception {
        String json_string_dataTwo = "{\"type\":\"visa\",\"cardholder_name\":\"John Smith\",\"card_number\":\"4788250000028291\",\"exp_date\":1020,\"cvv\":\"123\"}";
        // String json_string =
        // "{\"gateway_id\":\"AI2010-01\",\"password\":\"w226638qtot48xu503zumwt2iy46g26q\",\"transaction_type\":\"00\",\"amount\":10,\"cardholder_name\":\"test\",\"cc_number\":\"4111111111111111\",\"cc_expiry\":\"1219\"}";
        String json_string_data = "{\"merchant_ref\":\"Astonishing-Sale\",\"transaction_type\":\"authorize\",\"method\":\"credit_card\",\"amount\":1299,\"currency_code\":\"USD\",\"credit_card\":"
                + json_string_dataTwo + "}";
        // "{\r\n  \"merchant_ref\": \"Astonishing-Sale\",\r\n  \"transaction_type\": \"authorize\",\r\n  \"method\": \"credit_card\",\r\n  \"amount\": \"1299\",\r\n  \"currency_code\": \"USD\",\r\n  \"credit_card\": {\r\n    \"type\": \"visa\",\r\n    \"cardholder_name\": \"John Smith\",\r\n    \"card_number\": \"4788250000028291\",\r\n    \"exp_date\": \"1020\",\r\n    \"cvv\": \"123\"\r\n  }\r\n}";

        epoch = System.currentTimeMillis();// / 1000;
        // nonce = UUID.randomUUID().toString();
        nonce = Math.abs(SecureRandom.getInstance("SHA1PRNG").nextLong());
        contentSha1 = contentSha1(json_string_data);
        authorizationHeader = authHeader(epoch, contentSha1);
        System.out.println(excutePost(json_string_data));
    }

    private static String authHeader(long hashTime, String contentSha1) {
        String authorizationHeader = null;
        try {
            String hmacString = "POST" + NEWLINE + "application/json" + NEWLINE + contentSha1 + NEWLINE + hashTime + NEWLINE + apikey + NEWLINE
                    + new URI("https://api-cert.payeezy.com/v1/transactions");

            return sha1(hmacString, ApiSecretkey);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static String contentSha1(String content) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        byte[] sha1hash = new byte[40];
        md.update(content.getBytes("UTF-8"), 0, content.length());
        sha1hash = md.digest();
        return convertToHex(sha1hash);
    }

    private static String convertToHex(byte[] data) {
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < data.length; i++) {
            int halfbyte = data[i] >>> 4 & 0xF;
            int two_halfs = 0;
            do {
                if ((0 <= halfbyte) && (halfbyte <= 9))
                    buf.append((char) (48 + halfbyte));
                else
                    buf.append((char) (97 + (halfbyte - 10)));
                halfbyte = data[i] & 0xF;
            } while (two_halfs++ < 1);
        }
        return buf.toString();
    }

//     private static String sha1(String s, String keyString) {
//     Base64 base64 = new Base64();
//     try {
//     SecretKeySpec key = new SecretKeySpec(keyString.getBytes("UTF-8"),
//     "HmacSHA1");
//     Mac mac = Mac.getInstance("HmacSHA1");
//     mac.init(key);
//     byte[] bytes = mac.doFinal(s.getBytes("UTF-8"));
//    
//     return new String(base64.encode(bytes));
//     } catch (Exception e) {
//     throw new RuntimeException(e);
//     }
//     }
    private static String sha1(String s, String keyString) {
        byte[] bytes = null;
        try {
            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(keyString.getBytes(), "HmacSHA256");
            sha256_HMAC.init(secret_key);
            bytes = sha256_HMAC.doFinal(s.getBytes("UTF-8"));
            //return new String(Base64.encodeBase64String(bytes));
        } catch (Exception e) {
            System.out.println("Error");
        }
        return  Base64.getEncoder().encodeToString(bytes);
    }

    private static String hashTime() {
        String time = getUTCFormattedDate("yyyy-MM-dd'T'HH:mm:ss'Z'");

        return time;
    }

    private static String getUTCFormattedDate(String format) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        return dateFormat.format(new Date());
    }

    public static String excutePost(String urlParameters) throws IOException {
    System.out.println(urlParameters);
    System.out.println(headerContentType);
    System.out.println(MerchantToken);
    System.out.println(authorizationHeader);
    System.out.println(epoch);
    System.out.println(nonce);
        URL url = new URL("https://api-cert.payeezy.com/v1/transactions");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        try {
            // Create connection
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", headerContentType);
            connection.setRequestProperty("apikey ", apikey);
            connection.setRequestProperty("token", MerchantToken);
            connection.setRequestProperty("Authorization", authorizationHeader);
            connection.setRequestProperty("timestamp", "" + epoch);
            connection.setRequestProperty("nonce", "" + nonce);
            connection.setDoOutput(true);
            connection.setReadTimeout(30000);

            // Send request
            DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
            wr.writeBytes(urlParameters);
            wr.flush();
            wr.close();

            // Get Response
            InputStream is = null;
            int statusCode = connection.getResponseCode();

        try {
            is = connection.getInputStream();
        } catch (IOException e) {
            if (statusCode >= 400) {
                is = connection.getErrorStream();
            }
        }
        BufferedReader rd = new BufferedReader(new InputStreamReader(is));
            String line;
            StringBuffer response = new StringBuffer();
            while ((line = rd.readLine()) != null) {
                response.append(line);
                response.append('\r');
            }
            rd.close();
            return response.toString();

        } catch (Exception e) {

            e.printStackTrace();
            return null;

        } finally {

            if (connection != null) {
                connection.disconnect();
            }
        }
    }

}
票数 1
EN

Stack Overflow用户

发布于 2015-03-31 13:35:48

我唯一的问题是字符编码,在这里我假设UTF-8。我怀疑错误在别处。

代码语言:javascript
复制
        // Send request
        byte[] data = urlParameters.getBytes(StandardCharsets.UTF_8);
        BufferedOutputStream wr = new BufferedOutputStream(connection.getOutputStream());
        wr.writeBytes(data);
        wr.close();

        // Get Response
        InputStream is = connection.getInputStream();
        BufferedReader rd = new BufferedReader(new InputStreamReader(is,
                StandardCharsets.UTF_8));

\r,CR,不作为行分隔符(除了旧的MacOS)。

代码语言:javascript
复制
           response.append("\r\n"); // Or '\n'
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29367152

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档