Конечная точка 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-сервису), я решил просто пойти и заглянуть в источник и понять это.

Вот изменения, которые я сделал, чтобы заставить его работать.

Предположения:

  • Вы должны использовать новый SDK PayPal для С#.
  • Это проще всего установить с помощью менеджера пакетов nuGet: установите Core и Merchant

Шаги:

  • Вы будете редактировать исходный код 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");

К сожалению, нет никаких перехватов или чего-то еще, чтобы изменить конечную точку.

Я рассматривал его компиляцию локально и исправлял его, но я бы скорее потерял способность изменять конечную точку в коде, чем потерять возможность однократного обновления всего пакета.