我正在寻找一种在代码中设置PayPal SOAP API端点的方法,而不是在web.config或app.config中指定它。我需要从特定于环境的配置中读取和使用端点,该配置不是web.config / app.config。
这可能吗?我已经在他们的github repo上阅读了SDK的一些代码,但这似乎不可能,但我希望我错过了一些东西。
我正在使用PayPal Merchant SDK for .Net,ver 2.1.96.0。
我正在寻找一种在代码中设置PayPal SOAP API端点的方法,而不是在web.config或app.config中指定它。我需要从特定于环境的配置中读取和使用端点,该配置不是web.config / app.config。
这可能吗?我已经在他们的github repo上阅读了SDK的一些代码,但这似乎不可能,但我希望我错过了一些东西。
我正在使用PayPal Merchant SDK for .Net,ver 2.1.96.0。
我需要能够指定.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:但如果您对编辑PayPal的代码没问题,这样可以正常工作......
(PayPal:如果您正在阅读此请请实现此功能!!)
编辑:这不是必要的 - 请看Simon Simon先生的回答
因此,在花了HOURS并编写我的应用程序后,我可以在live和sandbox之间切换端点(就像我以前直接调用SOAP服务时那样),我决定再去深入挖掘源代码并进行计算出。
以下是我为使其发挥作用所做的更改。
假设:
脚步:
endpoint
在web.config下 <paypal>
。建议安全预防措施!PayPalAPIInterfaceServiceService.cs
来自GitHub (商家SDK)DefaultSOAPAPICallHandler.cs
来自GitHub (核心SDK)您可能需要花一点时间来确保版本与nuGet包相同。
在项目文件夹中复制这两个项目 PayPalMerchantSDK
或类似的东西
SimonsPayPalAPIInterfaceServiceService
和 SimonsSOAPAPICallHandler
- 但无论你想要什么,都可以打电话更改构造函数以添加布尔值 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;
修改构造函数以添加 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的更高版本,因为您必须重新执行此操作。
我希望有人觉得这很有用:-)
它完全可行,但您必须通过将绑定创建为对象来对值进行硬编码。这是我为自己的项目制定的:
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
代替。
答案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();
}
卫生署!不 GetEndPoint()
看起来有点像我们想要覆盖的东西。
深入研究代码 - 实例 GetEndPoint()
最终被称为这一个 DefaultSOAPAPICallHandler
- 正如你所看到的那样直接进入 ConfigManager
。
public string GetEndPoint()
{
return ConfigManager.Instance.GetProperty(BaseConstants.END_POINT);
}
ConfigManager
直接去 web.config
要么 app.config
config = (SDKConfigHandler)ConfigurationManager.GetSection("paypal");
遗憾的是,没有任何钩子或任何其他东西来改变终点。
我已经考虑过在本地编译它并修复它,但我宁愿失去在代码中更改端点的能力,也就是失去了一键更新整个包的能力。