matthiasnoback / microsoft-translator

PHP library for making calls to the Microsoft Translator V3 API
MIT License
39 stars 26 forks source link

key or keys -- on clientSecret #19

Closed kklepper closed 5 years ago

kklepper commented 6 years ago

Hello,

Thanks a lot for providing your translation solution. Unfortunately, it does not work.

API call was not successful, 400: Bad Request

I suppose this is due to the fact that I did not provide the right credentials. Maybe Microsoft has changed its policy.

On the Microsoft page http://docs.microsofttranslator.com/speech-translate.html as well as on the administrative page, they talk both of "the subscription key" as well as "Keys", which is what they provide.

Go to the Keys option and copy your subscription key to access the service.

Use the subscription key to authenticate.

I do have a key1 and a key2, displayed under the option "Keys", but no "subscription key". So which one to use? Or is there another mechanism to get the "subscription key"?

Regards Karl

matthiasnoback commented 6 years ago

Honestly, I have no idea ;) I don't use or actively maintain this library anymore.

arraintxo commented 6 years ago

I will take a look as soon as i have a slot. Thanks for the report.

kklepper commented 6 years ago

See https://cognitive.uservoice.com/knowledgebase/articles/1128340-microsoft-translator-moves-to-the-azure-portal (with C# code)

In particular:

For Microsoft Translator API users previously subscribed in DataMarket, to continue using the Microsoft Translator API from the Azure portal, you will need to replace the app authentication using your Microsoft DataMarket Client ID and Client Secret with your new Azure key. The single Azure key is used to request an Azure token for the Microsoft Translator service.

Refer to the documentation for getting an Azure token. Learn more on why Azure generates two keys.

See https://stackoverflow.com/questions/13215130/using-the-azure-microsoft-translator-api-with-php-and-curl -- answer no. 5 looks good, gives bad result:

curlResponse :<html><body><h1>Argument Exception</h1><p>Method: Translate()</p><p>Parameter: </p><p>Message: The API type of the received token in not Text. Please use a subscription to Translator Text API.</p><code></code><p>message id=0916.V2_Rest.Translate.2DFAEE71</p></body></html>:

Unfortunately I cannot interpret this.

See also https://stackoverflow.com/questions/44246451/microsoft-translator-api-error-message-the-received-token-is-of-incorrect-token with console code

curl --header 'Ocp-Apim-Subscription-Key: ******************' --data "" 'https://api.cognitive.microsoft.com/sts/v1.0/issueToken'

works fine

but using the token results in error

curl -X GET --header 'Accept: application/xml' --header 'Authorization: Bearer **veryLONGtoken**' 'https://api.microsofttranslator.com/v2/http.svc/Translate?&text=this%20is%20my%20name&from=en&to=af'
<html><body><h1>Argument Exception</h1><p>Method: Translate()</p><p>Parameter: </p><p>Message: The API type of the received token in not Text. Please use a subscription to Translator Text API.</p><code></code><p>message id=0916.V2_Rest.Translate.2DFC9500</p></body></html>

The sample supposedly did work for the original poster, though...

php code for token:

https://social.msdn.microsoft.com/Forums/azure/en-US/ac1b3467-4cf2-414b-a769-e80b2a94063e/transitioning-microsoft-translator-api-from-data-market-to-azure-portal?forum=DataMarket

kklepper commented 6 years ago

It should be possible to work without access token, though.

http://docs.microsofttranslator.com/speech-translate.html

Use the subscription key to authenticate. Microsoft Translator Speech API supports two modes of authentication:

Using an access token. In your application, obtain an access token from the token service. Use your Microsoft Translator Speech API subscription key to obtain an acess token from the Cognitive Services authentication service. The acces token is valid for 10 minutes. Obtain a new acces token every 10 minutes, and keep using the same access token for repeated requests within these 10 minutes.

Using a subscription key directly. In your application, pass your subscription key as a value in Ocp-Apim-Subscription-Key header.
arraintxo commented 6 years ago

Hi @kklepper, which Provider are you using? For the new Azure subscriber key the AzureTokenProvider should be used. The AccessTokenProvider is deprecated and should not be used anymore.

kklepper commented 6 years ago

Hi @arraintxo I don't know what you mean. I am new to Azure, so I guess I use a AzureTokenProvider.

I found this: https://social.msdn.microsoft.com/Forums/azure/en-US/abea40b7-856d-4654-a229-326d1a3578a0/subscription-key-and-authorization-token-for-microsoft-translator-text-api?forum=MediaServices

Looks like i used subscription key from "Translator speech API", not from "Translator Text Api" ...

and this is true; I just try to find out how to subscribe to the right type of service. Looks like I cannot find it.

kklepper commented 6 years ago

This is what I got, and it is obviously wrong. Where is the real translation service?

grafik

kklepper commented 6 years ago

I found it: you have to click "more" to get a list among which the translator-text-API is listed.

arraintxo commented 6 years ago

On Azure Portal you should be subscribed to "Translator Text API". Just click "New" and look for "Translator Text API" on the search bar. Once you've got the Translator Text API keys (you're right, there are two available there), the Key1 should work.

About my previous comment on providers, I mean on the PHP side. I haven't seen any of you're code, so I can't say if you are doing it right or not. If you are using the first sample you should be doing it right, if you are using the "Azure DataMarket token usage [deprecated]" you are doing it wrong.

Hope this helps...

arraintxo commented 6 years ago

Great! I'm glad you found it, Microsoft's UX is not really helping too much on Azure Portal.

Does it work now?

kklepper commented 6 years ago

Using the Shell method, I get a different error now:

Argument Exception

Method: Translate()

Parameter:

Message: The received token is of incorrect token type.

message id=0639.V2_Rest.Translate.2E630CA7

Okay, I'll find out.

kklepper commented 6 years ago

Got it: https://stackoverflow.com/questions/40788259/error-the-received-token-is-of-incorrect-token-type-what-should-the-token-lo led me to http://docs.microsofttranslator.com/oauth-token.html which I used with shell/curl. result:

Dit is my naam

For the record:

get the token:

curl --data "" 'https://api.cognitive.microsoft.com/sts/v1.0/issueToken?Subscription-Key='

curl -X GET --header 'Accept: application/xml' --header 'Authorization: Bearer <705-byte-token>' 'https://api.microsofttranslator.com/v2/http.svc/Translate?&text=this%20is%20my%20name&from=en&to=af'

Now I'll translate this to PHP

kklepper commented 6 years ago

First a more elegant shell version without the need to copy the lengthy access token:

$ accessToken=$(curl --data "" 'https://api.cognitive.microsoft.com/sts/v1.0/issueToken?Subscription-Key=<your_key_here>')
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   705  100   705    0     0   2866      0 --:--:-- --:--:-- --:--:--  2877
$ curl -X GET --header 'Accept: application/xml' --header "Authorization: Bearer $accessToken" 'https://api.microsofttranslator.com/v2/http.svc/Trans
late?&text=this%20is%20my%20name&from=en&to=af'
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">Dit is my naam</string>

Now a PHP translation based on paul couck's code:

<?php

translation_test();

// ====================================================================
/**
 * translation_test()
 *
 * @access  public
 * @param   string
 * @return  string
 */
function translation_test() {
    $text = 'this is my name';
    $from = 'en';
    $to = 'af';
    $result = simple_ms_text_translation($text, $from, $to);
echo("<hr><pre> L: ".__LINE__."  :$result:  :: M: ".__METHOD__ . " F: ".__FILE__." ".date('H:i:s').' (  ) '."</pre>"   );              
} # translation_test

// ====================================================================
/**
 * simple_ms_text_translation($text, $from, $to)
 *
 * @access  public
 * @param   string
 * @return  string
 */
function simple_ms_text_translation($text, $from, $to) {
    $accessToken = simple_ms_translation_get_token();
    $text = urlencode($text);
    $translateUrl = "https://api.microsofttranslator.com/v2/http.svc/Translate?text=$text&from=$from&to=$to";
    $curlResponse = simple_ms_translation_get_result($translateUrl, $accessToken);
    $translatedStr = simplexml_load_string($curlResponse);
    return $translatedStr; 
} # simple_ms_text_translation

// ====================================================================
/**
 * simple_ms_translation_get_token()
 *
 * @access  public
 * @param   string
 * @return  string
 */
function simple_ms_translation_get_token() {
    # see https://social.msdn.microsoft.com/Forums/azure/en-US/ac1b3467-4cf2-414b-a769-e80b2a94063e/transitioning-microsoft-translator-api-from-data-market-to-azure-portal?forum=DataMarket
    $azure_key = "<your key1 or key2 here>";  // !!! TODO: secret key here !!!

    //1. initialize cURL 
    $ch = curl_init();

    //2. set options

    //Set to POST request
    curl_setopt($ch, CURLOPT_POST,1);

    // URL to send the request to
    curl_setopt($ch, CURLOPT_URL, "https://api.cognitive.microsoft.com/sts/v1.0/issueToken?Subscription-Key=$azure_key");

    //return instead of outputting directly
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

    //donot include header in the output.
    curl_setopt($ch, CURLOPT_HEADER, 0);

    // WEIRD!!!: pass subscription key or just 0 by the HTTP "POST" Operation.
    curl_setopt($ch, CURLOPT_POSTFIELDS,0);

    //CURLOPT_SSL_VERIFYPEER- Set to false to stop verifying certificate
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

    //3. Execute the request, fetch the response & check for errors
    $accessToken = curl_exec($ch);

    if ($accessToken === FALSE) {
        echo "cURL Error" . curl_error($ch);
    }
    curl_close($ch);
    return $accessToken; 
} # simple_ms_translation_get_token

// ====================================================================
/**
 * simple_ms_translation_get_result($translateUrl)
 *
 * @access  public
 * @param   string
 * @return  string
 */
function simple_ms_translation_get_result($translateUrl, $accessToken) {
    $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $translateUrl);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                'Authorization: Bearer ' . $accessToken,
            )
        );
    $curlResponse = curl_exec($ch);
    curl_close($ch);
    return $curlResponse; 
} # simple_ms_translation_get_result

?>

@arraintxo @matthiasnoback Thank you all very much.