I am trying to make a request to Paypal endpoint via SDK in my .NET Core application. The request works on local server just fine. But when I pulished the application on 1and1 hosting server, I get this error.
A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
The reason I found out is that 1and1 doesn't allow direct calls so I need to use proxy. Some people have asked the same question already. But there is no real answer for me.
Here are two of them:
I also did contact 1and1 for support (2x times). They sent me the same link (in german) which I have already found and tried. No success.
Here are some senairos, that I have tried:
1. Add proxy server to web.config
file
My config file looks something like this
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath=".\MyApp.exe" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
</system.webServer>
</location>
<system.net>
<defaultProxy>
<proxy proxyaddress="http://1and1proxy:123"
bypassonlocal="true"/>
</defaultProxy>
</system.net>
</configuration>
2. Add AspNetCore.Proxy
to startup.cs
file
public void ConfigureServices(IServiceCollection services) {
...
services.AddProxies();
...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
...
app.RunProxy(proxy => proxy.UseHttp("http://1and1proxy:123"));
...
}
3. Make another simple request to another server (using webproxy
but also failed)
public async Task < IActionResult > callingGet() {
var proxiedHttpClientHandler = new HttpClientHandler() {
UseProxy = true
};
proxiedHttpClientHandler.Proxy = new WebProxy("http://1and1proxy:123");
HttpClient client = new HttpClient(proxiedHttpClientHandler);
using
var client = new HttpClient();
var result = await client.GetAsync("https://reqres.in/api/users/2");
return View(new Model {
Message = result.ToString()
});
}
Did I miss something here or do I have to switch to another provider? PS: this is my first time publishing a website
It turns out that the third did work (but I still don't know why the first and second one do not).
So I created an issue on GitHub page to ask if there is any option for me to create a proxy while calling request to PayPal service. I've got no response from any SDK's developers but a member, who had the same request. He had to create on his own this option, because there is no official way to set proxy using PayPal .Net SDK yet. So I am going to repost his answer here.
I think it could help someone. Thanks to WSSC-Jonathan
again.
using System;
using System.Threading.Tasks;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using PayPalCheckoutSdk.Core;
namespace MongMi.Application.Paypal
{
public class ProxiedPayPalHttpClient : PayPalHttp.HttpClient
{
private WebProxy _proxy;
private PayPalEnvironment _environment;
private PayPalHttp.IInjector _gzipInjector;
private PayPalHttp.IInjector _authInjector;
public ProxiedPayPalHttpClient(PayPalEnvironment environment, WebProxy proxy)
: base(environment)
{
_environment = environment;
_proxy = proxy;
OverrideClient();
SetupInjectors();
}
public ProxiedPayPalHttpClient(PayPalEnvironment environment, string url, string username = "", string password = "")
: base(environment)
{
_environment = environment;
_proxy = SetupProxy(url, username, password);
OverrideClient();
SetupInjectors();
}
public WebProxy SetupProxy(string url, string username, string password)
{
var proxy = new WebProxy(url)
{
BypassProxyOnLocal = true,
UseDefaultCredentials = true
};
if (!string.IsNullOrEmpty(username) || !string.IsNullOrEmpty(password))
proxy.Credentials = new NetworkCredential(username, password);
return proxy;
}
private void OverrideClient()
{
var handler = new HttpClientHandler
{
Proxy = _proxy
};
var client = new HttpClient(handler, true) { BaseAddress = new Uri(environment.BaseUrl()) };
client.DefaultRequestHeaders.Add("User-Agent", GetUserAgent());
SetClient(client);
}
private void SetupInjectors()
{
_gzipInjector = new GzipInjector();
_authInjector = new AuthorizationInjector(_proxy, _environment);
AddInjector(_gzipInjector);
AddInjector(_authInjector);
}
protected void SetClient(HttpClient client)
{
var type = GetType();
while (type != null)
{
var field = type.GetField("client", BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
{
field.SetValue(this, client);
break;
}
type = type.BaseType;
}
}
private class AuthorizationInjector : PayPalHttp.IInjector
{
private WebProxy _proxy;
private PayPalEnvironment _environment;
private AccessToken _accessToken;
public AuthorizationInjector(WebProxy proxy, PayPalEnvironment environment)
{
_environment = environment;
_proxy = proxy;
}
public void Inject(PayPalHttp.HttpRequest request)
{
if (!request.Headers.Contains("Authorization") && !(request is AccessTokenRequest || request is RefreshTokenRequest))
{
if (_accessToken == null || _accessToken.IsExpired())
_accessToken = FetchAccessToken().Result<AccessToken>();
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _accessToken.Token);
}
}
private PayPalHttp.HttpResponse FetchAccessToken()
{
var client = new ProxiedPayPalHttpClient(_environment, _proxy);
var request = new AccessTokenRequest(_environment, null);
return Task.Run(async () => await client.Execute(request).ConfigureAwait(false)).Result;
}
}
private class GzipInjector : PayPalHttp.IInjector
{
public void Inject(PayPalHttp.HttpRequest request)
{
request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
}
}
}
}