2015-03-31 85 views
4

这里我附上了代码和一个包含完整代码的链接,看看它: - 我的授权头接缝与官方网站payeezy中提到的长度相同。我也使得我的hmacString与此链接中提到的顺序相同(https://developer.payeezy.com/content/hmac-validation-failure)。做这一切后,我仍然得到同样的问题错误: - {“code”:“403”,“message”:“HMAC validation Failure”}

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

回答

3

我终于在API网址hit.Here直接发送String作为参数我张贴我的一些代码解决了这个错误,解决了我的错误: -

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\"}";

现在这个String将被用于生成我的授权密钥。 整个过程被定义如下: -

getSecurityKeys(apikey, pzsecret,str); 
 

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

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

 
\t public static String getMacValue(Map<String, String> data) throws Exception { 
 
\t \t Mac mac = Mac.getInstance("HmacSHA256"); 
 
\t \t String apiSecret = data.get(APISECRET); 
 
\t \t SecretKeySpec secret_key = new SecretKeySpec(apiSecret.getBytes(), 
 
\t \t \t \t "HmacSHA256"); 
 
\t \t mac.init(secret_key); 
 
\t \t StringBuilder buff = new StringBuilder(); 
 
\t \t buff.append(data.get(APIKEY)).append(data.get(NONCE)) 
 
\t \t \t \t .append(data.get(TIMESTAMP)); 
 
\t \t if (data.get(TOKEN) != null) 
 
\t \t \t buff.append(data.get(TOKEN)); 
 
\t \t if (data.get(PAYLOAD) != null) 
 
\t \t \t buff.append(data.get(PAYLOAD)); 
 
\t \t byte[] macHash = mac.doFinal(buff.toString().getBytes("UTF-8")); 
 
\t \t String authorizeString = Base64.encodeBase64String(toHex(macHash)); 
 
\t \t return authorizeString; 
 
\t }
现在终于可以通过直接的字符串(即STR)在击中后的Java API参数。

希望它可以帮助其他人集成payeezy支付网关而不使用任何依赖关系。 快乐编码!

1

必须生成一个新的timestampnonce要求,即每一个新的请求必须有其独特的timestampnonce

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

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

我希望这会有所帮助。


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

Connection = keep-alive 
Content-Length = 51 
Content-Type = application/json 
{"code":"403", "message":"HMAC validation Failure"} 

请确保您正确计算您的HMAC-SHA1值(如上所述)。

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

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(); 
      } 
     } 
    } 

} 
+0

嘿,谢谢你的回复,是的,我知道这一点,我必须生成我的时间戳和随机数,当我相应地打我的认证头还得到唯一生成的API ..在这里,我给你发送我的主要Java上课...请看看它,并告诉我,我在做什么错...(http://piratepad.net/ep/pad/view/ro.WwZ9v6FX1a6/latest) – sid 2015-03-31 13:09:27

+0

看到我更新的职位。祝你好运! – 2015-03-31 14:25:37

+0

嘿,谢谢你的努力,我会试试它,让你知道它是怎么回事:) – sid 2015-03-31 14:51:55

0

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

 // 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)。

  response.append("\r\n"); // Or '\n' 
+0

嘿,Eggen感谢您的回复...但我仍然得到相同的错误: - java.lang.IllegalArgumentException:邮件标题值中的非法字符:AMru2osZZnotc25nRr7/dAOwkV/S3J1T7Yn7zs2XpFc = – sid 2015-03-31 13:57:25

+0

此外,当我尝试调试代码我发现像这样: - java.lang.IllegalStateException:已连接 – sid 2015-03-31 13:58:51

+0

**尝试省略尾部的'='填充字符。** – 2015-03-31 14:10:07