Грешка при удостоверяване на X-FACEBOOK-PLATFORM

Опитвам се да се свържа с Facebook chat api чрез SMACK, като използвам кода по-долу, но винаги получавам X-FACEBOOK-PLATFORM failed: not-authorized. Имам валиден токен с xmpp разрешение, но мисля, че пропускам нещо... работи с user/pass, но не и с 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( "-%[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;
    }
}
}

person Imanagent Sococare    schedule 26.09.2013    source източник


Отговори (1)


Боже мой, аз също се боря с това завинаги. Току-що го разбрах! След като го разбрах, изглеждаше толкова лесно, но объркващото е, че проблемът, който изглежда идва от XMPP, всъщност е проблем с Facebook. Мисля, че вашият проблем (моят проблем беше), че Facebook изисква от вас да поискате разрешения за влизане в приложението, които нямат нищо общо с протокола XMPP. Ако погледнете спецификациите на API за чат, там се казва, че трябва да поискате разширено разрешение xmpp_login за вашето приложение, ако използвате X-FACEBOOK-PLATFORM. Трябва да направите това чрез обекта на сесията във Facebook SDK, който сте използвали, за да получите вашия session_token.

Ето кода, който използвах:

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

Веднага след като го направих, работи като чар. Последното предупреждение е, че трябва да се уверите, че изскачащият диалогов прозорец с молба към потребителя да даде на вашето приложение това разширено разрешение се появява и получава необходимото разрешение ПРЕДИ да продължите и да опитате xmpp.login. В противен случай ще имате същия проблем, тъй като приложението ви ще иска разрешение, но всъщност няма да получава разрешение.

Надявам се, че това работи за вас.

person JSv4    schedule 30.10.2013