I am integrating PayPal payments into my website using the PayPal REST API using the .NET SDK (https://www.nuget.org/packages/PayPal). My website is running as an App Service in Microsoft Azure. I have a testing slot configured to use PayPal Sandbox, and a production slot which uses the Live credentials (configuration settings are in the App Settings, and are slot-specific).
Everything works fine in Sandbox, and I am able to authenticate and get an access token using the live configuration, but when I try to process anything I get a PayPal.IdentityException
(I tried Payments as well as Billing Plans and Agreements). If I look at the IdentityException
Response
(or Details
), I get this:
{"error":"invalid_token","error_description":"The token passed in was not found in the system"}
Digging further, it seems that the ApiContext
that is created has the AccessToken set, but the Config property is null
. If I look at the API request (from PayPalResource.LastRequestDetails.Value
) I see that even though it's using the live configuration, it's sending the request to api.sandbox.paypal.com, not the live API. This seems to be a problem with my ApiContext
, which I establish as follows:
public static APIContext Authenticate()
{
string clientId = ConfigurationManager.AppSettings["PayPalClientId"];
string clientSecret = ConfigurationManager.AppSettings["PayPalSecret"];
string mode = ConfigurationManager.AppSettings["PayPalMode"];
var config = new Dictionary<string, string>();
config.Add("mode", mode);
config.Add("clientId", clientId);
config.Add("clientSecret", clientSecret);
accessToken = new OAuthTokenCredential(config).GetAccessToken();
return new APIContext(accessToken); // <--- problem here
}
Apart from manually constructing the Config
dictionary rather than using the ConfigManager
to create it automatically from a custom config section, this follows the .NET SDK documentation very closely. What am I doing wrong?
The problem here is that all that is passed to the APIContext
constructor is the accessToken
. Without having the settings in the custom config section of Web.config
or App.config
, APIContext
defaults to using the sandbox API.
The solution is to explicitly set the Config property using an Object Initializer:
return new APIContext(accessToken) { Config = config }; // <---- fixed