I'm following this interactive login example from Paypal's site.
public ActionResult PaypalResponse(string scope, string code)
{
Dictionary<string, string> configurationMap = new Dictionary<string, string>();
configurationMap.Add("mode", "sandbox");
APIContext apiContext = new APIContext();
apiContext.Config = configurationMap;
CreateFromAuthorizationCodeParameters param = new CreateFromAuthorizationCodeParameters();
param.setClientId(clientId);
param.setClientSecret(clientSecret);
param.SetCode(code);
// Exception here:
Tokeninfo info = Tokeninfo.CreateFromAuthorizationCode(apiContext, param);
return null;
}
The method CreateFromAuthorizationCode results in this (incorrect) call. Note how client ID and client secret are missing
POST https://api.sandbox.paypal.com/v1/identity/openidconnect/tokenservice HTTP/1.1
Content-Type: application/x-www-form-urlencoded
User-Agent: PayPalSDK/ ;lang=DOTNET;v=4.0.30319.18051;bit=64;os=Microsoft Windows 8 Enterprise 6.2.9200.0;
Host: api.sandbox.paypal.com
Content-Length: 211
Expect: 100-continue
Connection: Keep-Alive
grant_type=authorization_code&code=d2mSEzm9xvE_l9Ibho0g6FNBVrC7wHZchJWqJfY...redacted...
The Fiddler output is
HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Cache-Control: no-store
Pragma: no-cache
Content-Type: application/json
Vary: Accept-Encoding
Content-Length: 76
DC: origin1-api.sandbox.paypal.com
Date: Mon, 14 Oct 2013 01:30:05 GMT
Connection: close
Set-Cookie: DC=origin1-api.sandbox.paypal.com; secure
{"error_description":"client id or secret is null","error":"invalid_client"}
I had the exact same problem, and solved it changing call method
string postcontents = string.Format("client_id={0}&client_secret={1}&grant_type=authorization_code&redirect_uri={2}&code={3}"
, System.Web.HttpUtility.UrlEncode(clientId)
, System.Web.HttpUtility.UrlEncode(secret)
, System.Web.HttpUtility.UrlEncode(url)
, System.Web.HttpUtility.UrlEncode(code));
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://api.sandbox.paypal.com/v1/identity/openidconnect/tokenservice");
request.Credentials = new NetworkCredential(clientId, secret);
request.Method = "POST";
byte[] postcontentsArray = System.Text.Encoding.UTF8.GetBytes(postcontents);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postcontentsArray.Length;
//OAuth.
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(postcontentsArray, 0, postcontentsArray.Length);
requestStream.Close();
WebResponse response = request.GetResponse();
using (Stream responseStream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(responseStream))
{
string responseFromServer = reader.ReadToEnd();
reader.Close();
responseStream.Close();
response.Close();
// return SerializeToken(responseFromServer);
dynamic dynObj = JsonConvert.DeserializeObject(responseFromServer);
string token = dynObj["access_token"];
//token = ser.Deserialize<ImportContacts._Default.GoogleOAuthToken>(responseFromServer);
}
}
Hope it helps
I had some issues with PayPal too, albeit not with this sample. I used nodejs. This library works fine, you might want to compare notes with the one you are using and see if you find any difference. (The endpoints are certainly different). See here specifically.
updated based on @pollirrata answer, and this is how it worked for me. Hope it will help someone.
//code is what you get from LoginWithPayPal login page in return (query string)
public .... GetRefreshAccessToken(string code)
{
var oAuthClientId = "clientid from paypal developer site";
var oAuthClientSecret = "client secret from paypal developer site";
var oAuthUrl = "https://api.sandbox.paypal.com/v1/identity/openidconnect/tokenservice";
var authHeader = string.Format("Basic {0}",
Convert.ToBase64String(
Encoding.UTF8.GetBytes(Uri.EscapeDataString(oAuthClientId) + ":" +
Uri.EscapeDataString((oAuthClientSecret)))
));
//passing code here
var postBody = string.Format("grant_type=authorization_code&code={0}", code);
var authRequest = (HttpWebRequest)WebRequest.Create(oAuthUrl);
authRequest.Headers.Add("Authorization", authHeader);
authRequest.Method = "POST";
byte[] postcontentsArray = Encoding.UTF8.GetBytes(postBody);
authRequest.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
authRequest.ContentLength = postcontentsArray.Length;
try
{
using (Stream stream = authRequest.GetRequestStream())
{
stream.Write(postcontentsArray, 0, postcontentsArray.Length);
stream.Close();
WebResponse response = authRequest.GetResponse();
using (Stream responseStream = response.GetResponseStream())
if (responseStream != null)
{
using (var reader = new StreamReader(responseStream))
{
string responseFromServer = reader.ReadToEnd();
reader.Close();
responseStream.Close();
response.Close();
//this will return you access token which you can use to get user information
var responseResult =
JsonConvert.DeserializeObject(responseFromServer);
}
}
}
}
catch (Exception e)
{
//log error
}
}
After this you can call GET method with new token for user information, uri: https://api.sandbox.paypal.com/v1/identity/openidconnect/userinfo/?schema=openid
Refer to: https://developer.paypal.com/webapps/developer/docs/integration/direct/identity/log-in-with-paypal/
Im having the same issue here, and Im trying your method. However I'm getting a a 400 Bad Request after being returned to my site, at the
WebResponse response = authRequest.GetResponse();
I've verified my clientId and secret is correct, and that an authCode is being returned successfully to the method. Did you possibly also run into this issue?
Thanks
--- UPDATE ---
cleaned solution and browser cache and it does seem to work ok now
Sailen's answer above worked for me. However, because Paypal changed their encryption to TLS in June 2016, the solution as it was written will return the following error
The request was aborted: Could not create SSL/TLS secure channel.
Based on answers provided in another thread, the SecurityProtocol
needs to be set to Tls12 before
creating the WebRequest
. Hope this helps someone.
Here's a snippet.
var postBody = $"grant_type=authorization_code&code={code}";
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
var authRequest = (HttpWebRequest)WebRequest.Create(oAuthUrl);