2013-09-26 82 views
0

我正在嘗試使用以下代碼連接到Facebook chat api通過SMACK但我總是會收到X-FACEBOOK-PLATFORM failed: not-authorized。我有一個有xmpp權限的有效標記,但我想我錯過了一些東西......它正在處理用戶/密碼,但與accessToken無關。X-FACEBOOK-PLATFORM認證錯誤

感謝您的幫助,這件事讓我瘋狂。

public class FacebookChatSample { 

public static void main( ) 
{ 

    String accessToken = //internet example "AAACjg0Eh1N8BAFuhUFZAN0EteV6pjZAsZAI46i8oV3iVmyLdaKiwaBcM5DPFjbEZAq9LZAZAA0qXsvaXkKB7SqnhubzlUAK7tmr3UYLaeQgaXSJ6EZCKn2G"; 
    String consumerKey = //internet example "179784128779487"; 

    long targetFacebookId = 550121201669650L; 

    String toID = "1002221765"; 

    String message = "HELLOOOOO FROM MY JAVA PROGRAM!!"; 

    XMPPConnection connection = createXMPPConnection(); 
    try 
    { 
     connection.connect(); 
     connection.login(consumerKey, accessToken); 

     String to = String.format("-%[email protected]", Long.valueOf(targetFacebookId)); 
     Chat chat = connection.getChatManager().createChat(to, null); 
     chat.sendMessage(message); 
    } 
    catch(XMPPException e) 
    { 
     e.printStackTrace(); 
    } 
    finally 
    { 
     connection.disconnect(); 
    } 
} 

private static synchronized XMPPConnection createXMPPConnection() 
{ 
    SASLAuthentication.registerSASLMechanism(
      SASLXFacebookPlatformMechanism.NAME, 
      SASLXFacebookPlatformMechanism.class); 
    SASLAuthentication.supportSASLMechanism(
      SASLXFacebookPlatformMechanism.NAME, 0); 

    ConnectionConfiguration configuration = new ConnectionConfiguration(
      "chat.facebook.com", 5222); 
    configuration.setSASLAuthenticationEnabled(true); 

    return new XMPPConnection(configuration); 
} 

public static class SASLXFacebookPlatformMechanism extends SASLMechanism 
{ 
    public static final String NAME = "X-FACEBOOK-PLATFORM"; 

    public SASLXFacebookPlatformMechanism(
      SASLAuthentication saslAuthentication) 
    { 
     super(saslAuthentication); 
    } 

    private String apiKey = ""; 

    private String accessToken = ""; 

    @Override 
    protected void authenticate() throws IOException, XMPPException 
    { 
     AuthMechanism stanza = new AuthMechanism(getName(), null); 
     getSASLAuthentication().send(stanza); 
    } 

    @SuppressWarnings("hiding") 
    @Override 
    public void authenticate(String apiKey, String host, String accessToken) 
      throws IOException, XMPPException 
    { 
     if(apiKey == null || accessToken == null) 
     { 
      throw new IllegalStateException("Invalid parameters!"); 
     } 

     this.apiKey = apiKey; 
     this.accessToken = accessToken; 
     this.hostname = host; 

     String[] mechanisms = { "DIGEST-MD5" }; 
     Map<String, String> props = new HashMap<String, String>(); 
     this.sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, 
       props, this); 
     authenticate(); 
    } 

    @Override 
    public void authenticate(String username, String host, 
      CallbackHandler cbh) throws IOException, XMPPException 
    { 
     String[] mechanisms = { "DIGEST-MD5" }; 
     Map<String, String> props = new HashMap<String, String>(); 
     this.sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, 
       props, cbh); 
     authenticate(); 
    } 

    @Override 
    protected String getName() 
    { 
     return NAME; 
    } 

    @Override 
    public void challengeReceived(String challenge) throws IOException 
    { 
     byte response[] = null; 
     if(challenge != null) 
     { 
      String decodedResponse = new String(
        org.jivesoftware.smack.util.Base64.decode(challenge)); 
      Map<String, String> parameters = getQueryMap(decodedResponse); 

      String version = "1.0"; 
      String nonce = parameters.get("nonce"); 
      String method = parameters.get("method"); 

      Long callId = Long.valueOf(System.currentTimeMillis()); 

      String composedResponse = String 
        .format(
          "method=%s&nonce=%s&access_token=%s&api_key=%s&call_id=%s&v=%s", 
          URLEncoder.encode(method, "UTF-8"), 
          URLEncoder.encode(nonce, "UTF-8"), 
          URLEncoder.encode(this.accessToken, "UTF-8"), 
          URLEncoder.encode(this.apiKey, "UTF-8"), 
          callId, URLEncoder.encode(version, "UTF-8")); 
      response = composedResponse.getBytes(); 
     } 

     String authenticationText = ""; 

     if(response != null) 
     { 
      authenticationText = org.jivesoftware.smack.util.Base64 
        .encodeBytes(
          response, 
          org.jivesoftware.smack.util.Base64.DONT_BREAK_LINES); 
     } 

     Response stanza = new Response(authenticationText); 

     getSASLAuthentication().send(stanza); 
    } 

    private Map<String, String> getQueryMap(String query) 
    { 
     String[] params = query.split("&"); 
     Map<String, String> map = new HashMap<String, String>(); 
     for(String param : params) 
     { 
      String name = param.split("=")[0]; 
      String value = param.split("=")[1]; 
      map.put(name, value); 
     } 
     return map; 
    } 
} 
} 

回答

1

我的上帝,我一直在爲此而苦苦掙扎。我只是想通了!一旦我得到它,看起來很容易,但令人困惑的是,似乎來自XMPP的問題實際上是Facebook的問題。我認爲你的問題(我的問題是)Facebook要求你請求與XMPP協議無關的特定於應用程序的登錄權限。如果您查看Chat API規範,則說明如果您使用的是X-FACEBOOK-PLATFORM,則需要爲您的應用程序請求xmpp_login擴展權限。您必須通過您用來獲取session_token的Facebook SDK中的會話對象來執行此操作。

這裏是我使用的代碼:

session.requestNewReadPermissions(new NewPermissionsRequest(getActivity(), Arrays.asList("xmpp_login"))); 

當我這樣做,它的工作就像一個魅力。最後需要注意的是,您需要確保彈出式對話框要求用戶授予您的應用程序此擴展權限,並且在您繼續前進並嘗試xmpp.login之前獲得所需的權限。否則你會遇到同樣的問題,因爲你的應用程序會請求權限權限,但實際上並不是獲得權限。

我希望這對你有用。