Конечная точка SDK PayPal С#
Я ищу способ установить конечную точку API-интерфейса PayPal SOAP в коде, а не указывать его в файле web.config или app.config. Мне нужно прочитать и использовать конечную точку из конфигурации среды, которая не является файлом web.config/app.config.
Возможно ли это? Я прочитал некоторые из кода для SDK в своем реестре github, и это кажется невозможным, но я надеюсь, что что-то пропустил.
Я использую PayPal Merchant SDK для .Net, версия 2.1.96.0.
Ответы
Ответ 1
Мне нужно было указать все важные настройки вне файла .config. Я ленив, вот как я это сделал:
paypalConfig = new Dictionary<string, string>();
paypalConfig.Add("apiUsername", "xxxxx");
paypalConfig.Add("apiPassword", "xxxxx");
paypalConfig.Add("apiSignature", "xxxxx");
==>paypalConfig.Add("mode","live|sandbox");
И затем вам нужно вызвать свой метод, указав снова учетные данные (не исследовали многое, почему это необходимо):
var service = new PayPalAPIInterfaceServiceService(paypalConfig);
var doCaptureResponse = service.DoCapture(amount, new SignatureCredential(paypalConfig["apiUsername"], paypalConfig["apiPassword"], paypalConfig["apiSignature"]));
Ответ 2
Ответ 2: НО Если вы в порядке с редактированием кода PayPal, это будет нормально работать...
(PayPal: если вы читаете этот ПОЖАЛУЙСТА, реализуйте эту функцию!)
РЕДАКТИРОВАТЬ: ЭТО НЕ БОЛЬШЕ НЕОБХОДИМО - СМОТРИТЕ ОТВЕТ by Simon Labrecque
Итак, потратив HOURS на это и написав свое приложение вокруг ожидания, что я могу переключить конечную точку между live и sandbox (как и раньше, когда я напрямую обращался к SOAP-сервису), я решил просто пойти и заглянуть в источник и понять это.
Вот изменения, которые я сделал, чтобы заставить его работать.
Предположения:
Шаги:
- Вы будете редактировать исходный код PayPal и компилировать локально, но только 2 файла:
- Удалите
endpoint
в web.config в <paypal>
. Рекомендуемая мера предосторожности!
- Загрузите источник для
PayPalAPIInterfaceServiceService.cs
из GitHub (Merchant SDK)
- Загрузите источник для
DefaultSOAPAPICallHandler.cs
из GitHub (Core SDK)
-
Вероятно, вы хотите потратить минуту, чтобы убедиться, что версия такая же, как ваш пакет nuGet.
-
Сделайте копию обоих из них в своем проекте в папке PayPalMerchantSDK
или что-то вроде этого
- Я бы рекомендовал переименовать оба файла, чтобы избежать путаницы и конфликта с версиями NuGet. Я расстроился и просто назвал их
SimonsPayPalAPIInterfaceServiceService
и SimonsSOAPAPICallHandler
- но назовите их, как хотите.
Изменения в SimonsSOAPAPICallHandler.cs
Измените конструктор, чтобы добавить boolean useSandbox
:
Примечание. Это должен быть первый параметр, потому что мы скоро сделаем поиск и заменим магию.
public SimonsSOAPAPICallHandler(bool useSandbox, string rawPayLoad, string attributesNamespace,
string headerString)
: base()
{
this.rawPayLoad = rawPayLoad;
this.nmespceAttributes = attributesNamespace;
this.headElement = headerString;
// you can get these from config if you wish but I doubt they'll ever change
this.endpoint = useSandbox ? "https://api-3t.sandbox.paypal.com/2.0" : "https://api-3t.paypal.com/2.0";
}
Измените GetEndPoint()
:
/// <summary>
/// Returns the endpoint for the API call
/// </summary>
/// <returns></returns>
public string GetEndPoint()
{
return this.endpoint;
}
Добавьте соответствующий элемент:
/// <summary>
/// Endpoint
/// </summary>
private string endpoint;
Изменения в SimonsPayPalAPIInterfaceServiceService.cs
Измените конструктор, чтобы добавить параметр useSandbox
public SimonsPayPalAPIInterfaceServiceService(bool useSandbox)
{
this.useSandbox = useSandbox;
}
Добавьте соответствующий элемент
private bool useSandbox;
Сделайте два поиска и замените в этом файле. У вас будет около 100 замен для каждого
- Замените
new DefaultSOAPAPICallHandler(
на new SimonsSOAPAPICallHandler(useSandbox,
- Замените
DefaultSOAPAPICallHandler defaultHandler
на var defaultHandler
То, что вы только что сделали, было добавлено useSandbox
в качестве параметра конструктору SimonsSOAPAPICallHandler
(который, к счастью, реализует IAPICallPreHandler
), и вы получите это для каждого метода:
public DoExpressCheckoutPaymentResponseType DoExpressCheckoutPayment(DoExpressCheckoutPaymentReq doExpressCheckoutPaymentReq, string apiUserName)
{
IAPICallPreHandler apiCallPreHandler = null;
string portName = "PayPalAPIAA";
setStandardParams(doExpressCheckoutPaymentReq.DoExpressCheckoutPaymentRequest);
var defaultHandler = new SimonsSOAPAPICallHandler(useSandbox, doExpressCheckoutPaymentReq.ToXMLString(null, "DoExpressCheckoutPaymentReq"), null, null);
apiCallPreHandler = new MerchantAPICallPreHandler(defaultHandler, apiUserName, getAccessToken(), getAccessTokenSecret());
((MerchantAPICallPreHandler) apiCallPreHandler).SDKName = SDKName;
((MerchantAPICallPreHandler) apiCallPreHandler).SDKVersion = SDKVersion;
((MerchantAPICallPreHandler) apiCallPreHandler).PortName = portName;
string response = Call(apiCallPreHandler);
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(response);
XmlNode xmlNode = xmlDocument.SelectSingleNode("*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='DoExpressCheckoutPaymentResponse']");
return new DoExpressCheckoutPaymentResponseType(xmlNode);
}
Что это!
Теперь, когда вы вызываете метод, вы можете сказать...
bool useSandbox = true; // or false
var service = new SimonsPayPalAPIInterfaceServiceService(useSandbox);
Затем вызовите метод как обычно
caller.DoExpressCheckoutPayment(pp_request, config.AccountName);
Примечание. Он по-прежнему будет искать имя учетной записи в вашем конфиге, чтобы найти соответствующие ключи. Очевидно, что будьте осторожны, обновляя более позднюю версию Merchant SDK, потому что вам придется делать это снова и снова.
Я надеюсь, что кто-то найдет это полезным: -)
Ответ 3
Это полностью выполнимо, но вам нужно жестко закодировать значения, создав привязки как объекты. Это то, что я разработал для своего проекта:
protected static PayPalAPIInterface GetService()
{
return new PayPalAPIInterfaceClient(new BasicHttpBinding()
{
SendTimeout = new TimeSpan(0, 5, 0),
MaxReceivedMessageSize = 200000,
Security = new BasicHttpSecurity()
{
Mode = BasicHttpSecurityMode.Transport,
Transport = new HttpTransportSecurity()
{
ClientCredentialType = HttpClientCredentialType.None,
ProxyCredentialType = HttpProxyCredentialType.None,
},
Message = new BasicHttpMessageSecurity()
{
ClientCredentialType = BasicHttpMessageCredentialType.Certificate,
}
}
},
new EndpointAddress(@"https://api-3t.paypal.com/2.0/")
).ChannelFactory.CreateChannel();
}
Здесь вы можете указать больше параметров - теоретически, все в файле .config
можно воспроизвести здесь. Однако это работает для меня, поэтому я больше не принимал этого.
Также стоит отметить, что это позволяет отправлять вызовы PayPal в библиотеку и не копировать привязку в файл конфигурации проекта, который включает эту библиотеку, поэтому я ее разработал в первую очередь.
Изменить: здесь базовое определение PayPalAPIInterfaceClient
- не гарантирует, что на самом деле этого будет достаточно для использования.
public partial class PayPalAPIInterfaceClient : System.ServiceModel.ClientBase<PayPalAPIInterfaceServiceService>
{
public PayPalAPIInterfaceClient(System.ServiceModel.Channels.Binding binding,
System.ServiceModel.EndpointAddress remoteAddress)
: base(binding, remoteAddress) { }
}
Вы также изменили бы более ранний код, чтобы вместо него использовать возвращаемый тип PayPalAPIInterfaceServiceService
.
Ответ 4
Ответ 1: Я согласен - невозможно из коробки.
Это действительно не представляется возможным без компиляции кода и изменения довольно много. Здесь текущий код из GitHub для PayPalAPIInterfaceServiceService
, который фактически сгенерирован, возможно, с использованием шаблона T4. Это массивный файл 2489 строк с таким кодом для каждого метода API.
Главное здесь IAPICallPreHandler
. Вы увидите, что он установлен в null, а затем инициализирован экземпляром MerchantAPICallPreHandler
. Невозможно передать его.
public SetExpressCheckoutResponseType SetExpressCheckout(SetExpressCheckoutReq setExpressCheckoutReq, ICredential credential)
{
IAPICallPreHandler apiCallPreHandler = null;
string portName = "PayPalAPIAA";
setStandardParams(setExpressCheckoutReq.SetExpressCheckoutRequest);
DefaultSOAPAPICallHandler defaultHandler = new DefaultSOAPAPICallHandler(setExpressCheckoutReq.ToXMLString(null, "SetExpressCheckoutReq"), null, null);
apiCallPreHandler = new MerchantAPICallPreHandler(defaultHandler, credential);
((MerchantAPICallPreHandler) apiCallPreHandler).SDKName = SDKName;
((MerchantAPICallPreHandler) apiCallPreHandler).SDKVersion = SDKVersion;
((MerchantAPICallPreHandler) apiCallPreHandler).PortName = portName;
string response = Call(apiCallPreHandler);
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(response);
XmlNode xmlNode = xmlDocument.SelectSingleNode("*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='SetExpressCheckoutResponse']");
return new SetExpressCheckoutResponseType(xmlNode);
}
Теперь посмотрим на интерфейс:
public interface IAPICallPreHandler
{
ICredential GetCredential();
string GetEndPoint();
Dictionary<string, string> GetHeaderMap();
string GetPayLoad();
}
Doh! Не выглядит GetEndPoint()
вроде того, что мы хотели бы переопределить.
Вникаем глубже в код - экземпляр GetEndPoint()
, который в конечном итоге называется, это тот, что находится в DefaultSOAPAPICallHandler
, который, как вы можете видеть, подходит прямо к ConfigManager
.
public string GetEndPoint()
{
return ConfigManager.Instance.GetProperty(BaseConstants.END_POINT);
}
ConfigManager
просто переходит прямо к web.config
или app.config
config = (SDKConfigHandler)ConfigurationManager.GetSection("paypal");
К сожалению, нет никаких перехватов или чего-то еще, чтобы изменить конечную точку.
Я рассматривал его компиляцию локально и исправлял его, но я бы скорее потерял способность изменять конечную точку в коде, чем потерять возможность однократного обновления всего пакета.