2015-03-31 83 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