0

我正在尝试使用下面的代码连接到Facebook chat apiSMACK但我总是收到X-FACEBOOK-PLATFORM failed: not-authorized. 我有一个具有 xmpp 权限的有效令牌,但我认为我遗漏了一些东西......它正在使用用户/密码,但不适用于 accessToken。

谢谢你们的帮助,这件事让我发疯了。

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( "-%d@chat.facebook.com", 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;
    }
}
}
4

1 回答 1

1

我的上帝,我也一直在为此苦苦挣扎。我刚刚想通了!一旦我得到它,它似乎很容易,但令人困惑的是,似乎来自 XMPP 的问题实际上是 Facebook 的问题。我认为您的问题(我的问题是)Facebook 要求您请求与 XMPP 协议无关的应用程序特定登录权限。如果您查看聊天 API 规范,它说如果您使用 X-FACEBOOK-PLATFORM,则需要为您的应用程序请求 xmpp_login 扩展权限。您必须通过用于获取 session_token 的 Facebook SDK 中的会话对象来执行此操作。

这是我使用的代码:

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

一旦我这样做,它就像一个魅力。最后需要注意的是,您需要确保弹出对话框要求用户授予您的应用程序此扩展权限,并在您继续尝试 xmpp.login 之前获得所需的权限。否则,您将遇到与您的应用程序请求许可但实际上并未获得许可相同的问题。

我希望这对你有用。

于 2013-10-30T16:08:00.313 回答