25

E-Trade は最近 API をリリースし、ある程度役立つが完全ではない技術文書を提供しました。

これがどのように機能するかを示す、C# で完全に機能する例を誰かが持っていますか?

OAuth を使用して認証を正しく行うことができましたが、アカウントまたは市場データから情報を取得しようとすると、サーバーに障害が発生します。

4

5 に答える 5

9

DevDefined OAuth Library を使用して接続できましたが、ソースを適切に機能させるには、ソースを微調整する必要がありました。私が使用した src をダウンロードして .dll をビルドできるように、リポジトリをフォークしました。

レポ: GitHub

例のクラス:

 public abstract class BaseOAuthRepository
{

    private static string REQUEST_URL = "https://etws.etrade.com/oauth/request_token";
    private static string AUTHORIZE_URL = "https://us.etrade.com/e/t/etws/authorize";
    private static string ACCESS_URL = "https://etws.etrade.com/oauth/access_token";

    private readonly TokenBase _tokenBase;
    private readonly string _consumerSecret;

    protected BaseOAuthRepository(TokenBase tokenBase, 
                                  string consumerSecret)
    {
        _tokenBase = tokenBase;
        _consumerSecret = consumerSecret;
    }

    public TokenBase MyTokenBase
    {
        get { return _tokenBase; }
    }

    public string MyConsumerSecret
    {
        get { return _consumerSecret; }
    }


    public OAuthSession CreateSession()
    {
        var consumerContext = new OAuthConsumerContext
        {
            ConsumerKey = MyTokenBase.ConsumerKey,
            ConsumerSecret = MyConsumerSecret,
            SignatureMethod = SignatureMethod.HmacSha1,
            UseHeaderForOAuthParameters = true,
            CallBack = "oob"
        };

        var session = new OAuthSession(consumerContext, REQUEST_URL, AUTHORIZE_URL, ACCESS_URL);    
        return session;
    }

    public IToken GetAccessToken(OAuthSession session)
    {
        IToken requestToken = session.GetRequestToken();
        string authorizationLink = session.GetUserAuthorizationUrlForToken(MyTokenBase.ConsumerKey, requestToken);
        Process.Start(authorizationLink);
        Console.Write("Please enter pin from browser: ");
        string pin = Console.ReadLine();
        IToken accessToken = session.ExchangeRequestTokenForAccessToken(requestToken, pin.ToUpper());

        return accessToken;
    }

    public string GetResponse(OAuthSession session, string url)
    {
        IToken accessToken = MyTokenBase;

        var response = session.Request(accessToken).Get().ForUrl(url).ToString();
        return response;
    }

    public XDocument GetWebResponseAsXml(HttpWebResponse response)
    {
        XmlReader xmlReader = XmlReader.Create(response.GetResponseStream());
        XDocument xdoc = XDocument.Load(xmlReader);
        xmlReader.Close();
        return xdoc;
    }

    public string GetWebResponseAsString(HttpWebResponse response)
    {
        Encoding enc = System.Text.Encoding.GetEncoding(1252);
        StreamReader loResponseStream = new
        StreamReader(response.GetResponseStream(), enc);
        return loResponseStream.ReadToEnd();
    }
}
于 2011-07-29T15:12:48.583 に答える
7

ETrade API に接続するために使用したコードを次に示します (テスト済みで動作します)。

1 つの注意点: ユーザー トークンの独自のストレージを実装する必要があります。私が作成したコードは非常にドメイン固有であるため、ここには含めません。

最初にDotNetOpenAuth、プロジェクトに追加して作成しましたETradeConsumer(DotNetOpenAuth の WebConsumer から派生します)。

EtradeConsumer.cs

public static class ETradeConsumer
{
    public static string AccessUrl 
    { 
        get 
        { 
            return "https://etws.etrade.com/oauth/access_token"; 
        } 
    }

    public static string RequestUrl 
    { 
        get 
        { 
            return "https://etws.etrade.com/oauth/request_token"; 
        } 
    }

public static string UserAuthorizedUrl 
    {  
        get 
        { 
            return "https://us.etrade.com/e/t/etws/authorize"; 
        } 
    }
private static readonly ServiceProviderDescription ServiceProviderDescription = new ServiceProviderDescription()
{
    AccessTokenEndpoint = new MessageReceivingEndpoint(AccessUrl, HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
    ProtocolVersion = ProtocolVersion.V10a,
    RequestTokenEndpoint = new MessageReceivingEndpoint(RequestUrl, HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
    TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
    UserAuthorizationEndpoint = new MessageReceivingEndpoint(new Uri(UserAuthorizedUrl), HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest)
};

public static DesktopConsumer CreateConsumer(IConsumerTokenManager tokenManager)
{
    return new DesktopConsumer(ServiceProviderDescription, tokenManager);
}

public static Uri PrepareRequestAuthorization(DesktopConsumer consumer, out string requestToken)
{
    if (consumer == null)
    {
        throw new ArgumentNullException("consumer");
    }

        Uri authorizationUrl = consumer.RequestUserAuthorization(null, null, out requestToken);

    authorizationUrl = new Uri(string.Format("{0}?key={1}&token={2}", ServiceProviderDescription.UserAuthorizationEndpoint.Location.AbsoluteUri, consumer.TokenManager.ConsumerKey, requestToken));
    return authorizationUrl;
}

public static AuthorizedTokenResponse CompleteAuthorization(DesktopConsumer consumer, string requestToken, string userCode)
    {
    var customServiceDescription = new ServiceProviderDescription
    {
            RequestTokenEndpoint = ServiceProviderDescription.RequestTokenEndpoint,
        UserAuthorizationEndpoint =
                new MessageReceivingEndpoint(
                string.Format("{0}?key={1}&token={2}",  ServiceProviderDescription.UserAuthorizationEndpoint.Location.AbsoluteUri,
                              consumer.TokenManager.ConsumerKey, requestToken),
                HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.GetRequest),
        AccessTokenEndpoint = new MessageReceivingEndpoint(
        ServiceProviderDescription.AccessTokenEndpoint.Location.AbsoluteUri + "?oauth_verifier" + userCode + string.Empty,
                HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.GetRequest),
        TamperProtectionElements = ServiceProviderDescription.TamperProtectionElements,
        ProtocolVersion = ProtocolVersion.V10a
    };

    var customConsumer = new DesktopConsumer(customServiceDescription, consumer.TokenManager);
    var response = customConsumer.ProcessUserAuthorization(requestToken, userCode);
    return response;
    }

}

次に、Etrade トークンを管理するクラスを作成する必要があります。例として、次のクラスを作成しました。InMemoryCollection を介してトークンを管理しますが、ユーザーが毎回認証/承認する必要がないように、実際には別の場所 (データベース、Cookie、または何か) に保持する必要があります。ConsumerKeyおよびトークンは、ConsumerSecretEtrade を通じてサインアップするものです。

public class ETradeTokenManager : IConsumerTokenManager 
{
    private Dictionary<string, string> tokensAndSecrets = new Dictionary<string, string>();
public string ConsumerKey { get { return "YourConsumerKey"; } }
public string ConsumerSecret { get { return "YourConsumerSecret";  } }
    
public string GetTokenSecret(string token)
{
    return tokensAndSecrets[token];
}

public void StoreNewRequestToken(UnauthorizedTokenRequest request, ITokenSecretContainingMessage response)
{
    tokensAndSecrets[response.Token] = response.TokenSecret;
}

public void ExpireRequestTokenAndStoreNewAccessToken(string consumerKey, string requestToken, string accessToken, string accessTokenSecret)
{
    tokensAndSecrets.Remove(requestToken);
    tokensAndSecrets[accessToken] = accessTokenSecret;
}

public TokenType GetTokenType(string token)
{
    throw new NotImplementedException();
}
}

最後に、以下を入力します (私は ASP.NET MVC 3 を使用しました。フレームワークは異なる場合があります)。

public ActionResult EtradeAuthorize(string returnUrl)
   {
        var consumer = ETradeConsumer.CreateConsumer(TokenManager);
    string requestToken;
    Uri popupWindow = ETradeConsumer.PrepareRequestAuthorization(consumer, out requestToken);
    var etradeViewModel = new ETradeAuthorizeViewModel(popupWindow, requestToken);
    return View(etradeViewModel);
    }

    [HttpPost]
    public ActionResult CompleteAuthorization(FormCollection formCollection)
    {
    string accessToken = "";
    var consumer = ETradeConsumer.CreateConsumer(TokenManager);
    var authorizationReponse = ETradeConsumer.CompleteAuthorization(consumer, formCollection["requestToken"], formCollection["userCode"]);
    if (authorizationReponse != null)
    {
        accessToken = authorizationReponse.AccessToken;
    }
    var etradeViewModel = new ETradeCompleteAuthorizeViewModel(formCollection["requestToken"], formCollection["userCode"], accessToken);
    return View(etradeViewModel);
    }

を取得した場合は、Etrade400 Bad Requestを取り出します。callbackUrl何らかの理由で、コールバック URL が使用されるたびに不正なリクエストがスローされます。彼らはoob(帯域外)を好みます。を使用するには、メソッド内の Callback URL にoob設定します。nullConsumer.Channel.Send()

他にも問題があります。この問題:通話の一部が適切に処理されていないことDue to a logon delay or other issue, your authentication could not be completed at this time. Please try again.が原因です。authorize具体的には、Etrade では、認証 URL が次のようになっている必要があります。

https://us.etrade.com/e/t/etws/authorize?key={yourConsumerKey}&token={requestToken}

OAuth 仕様では、リクエスト トークンは である必要がrequest_token={requestToken}あり、 ではない必要がありtoken={requestToken}ます。

で Etrade API を正しく認証できませんでしたWebConsumerが、 に切り替えてDesktop Consumer自分でリクエストを操作すると、正しく機能しました。

于 2011-10-26T14:35:05.280 に答える
3

「ログオンの遅延またはその他の問題により、現時点で認証を完了できませんでした。もう一度お試しください。」というメッセージが表示された場合、

次に、承認URLに間違ったキーを入れたと思います。

この形式の適切なキーを置き換えて、ドキュメントに従う必要があります

https://us.etrade.com/e/etws/authorize?key= &token=

于 2011-08-04T09:06:56.667 に答える
1

jejernigの回答からのサンプルクラス+GitHubのコードを使用するために、次を使用しました。

TokenBase token = new TokenBase { ConsumerKey = "oauth_consumer_key from ETRADE" }; // OAuthRepository only seems to use the consumer key
OAuthRepository rep = new OAuthRepository(token, "consumer_secret from ETRADE");
OAuthSession session = rep.CreateSession();
IToken accessToken = rep.GetAccessToken(session);

を削除しましたabstractBaseOAuthRepository、のパラメータが逆になっているため、GitHubコードを修正する必要がありました IOAuthSession.GetUserAuthorizationUrlForToken()(インターフェイスのパラメータに一致するように残りのコードを変更しました)。

恐ろしいDue to a logon delay or other issue, your authentication could not be completed at this time. Please try again.メッセージが表示されますが、これは実際のログオンの問題が原因である可能性があり、解決する必要があります。

于 2012-04-15T14:18:04.690 に答える
-2

Cookie をクリアして、もう一度お試しください。なぜこれが起こるのかわかりません。ただし、このエラーが発生すると、Cookie をクリアしない限り、同じエラーが発生します。ログインに成功し、REST サービスの一部を呼び出すことができます。

于 2011-02-27T16:34:48.520 に答える