这个问题与使用SOAP请求/响应模型将PayPal API与Java集成有关。
以下方法包括建立请求参数并返回响应字符串,在本例中为令牌。我看了几个假设如何进行请求调用的例子,但这些方法是为较少的版本创建的(这个版本是“109.0”,我看到的其他例子是80,60甚至40)。
无论如何,我从PayPal下载了.wsdl文件,用SOAPUI和JAX-WS Web服务样式创建了客户端java类,保存了项目并用MyEclipse打开。我在Java TomCat服务器上导入了PayPal证书,并在java的cacerts文件中使用keytool import。
以下方法假设是返回String值的请求方法:
public String setExpressCheckout(String returnURL, String cancelURL) throws ErrorGeneral {
PayPalAPIInterfaceService pp = new PayPalAPIInterfaceService();
UserIdPasswordType login = new UserIdPasswordType();
login.setUsername("carlos.martinez_api1.netijam.com");
login.setPassword("1389974315");
login.setSignature("AFcWxV21C7fd0v3bYYYRCpSSRl31AI-ujedgZR8zf1CorgeJpph2tssY");
String token = "";
String ackString;
// following class is generated by wsdl2java utility Service class
final PayPalAPIAAInterface expressCheckoutPort = pp.getPayPalAPIAA();
final Binding binding = ((BindingProvider) expressCheckoutPort).getBinding();
List<Handler> handlersList = new ArrayList<Handler>();
// now, adding instance of Handler to handlersList which should do our job:
// creating header instance
CustomSecurityHeaderType headerObj = new CustomSecurityHeaderType();
UserIdPasswordType credentials = new UserIdPasswordType();
credentials.setUsername("carlos.martinez_api1.netijam.com");
credentials.setPassword("1389974315");
credentials.setSignature("AFcWxV21C7fd0v3bYYYRCpSSRl31AI-ujedgZR8zf1CorgeJpph2tssY");
headerObj.setCredentials(credentials);
ObjectFactory objectFactory = new ObjectFactory();
// creating JAXBElement from headerObj
final JAXBElement<CustomSecurityHeaderType> requesterCredentials = objectFactory.createRequesterCredentials(headerObj);
handlersList.add(new SOAPHandler<SOAPMessageContext>() {
@Override
public boolean handleMessage(final SOAPMessageContext context) {
try {
// checking whether handled message is outbound one as per Martin Strauss answer
final Boolean outbound = (Boolean) context.get("javax.xml.ws.handler.message.outbound");
if (outbound != null && outbound) {
// obtaining marshaller which should marshal instance to xml
final Marshaller marshaller = JAXBContext.newInstance(CustomSecurityHeaderType.class).createMarshaller();
// adding header because otherwise it's null
final SOAPHeader soapHeader = context.getMessage().getSOAPPart().getEnvelope().addHeader();
// marshalling instance (appending) to SOAP header's xml node
marshaller.marshal(requesterCredentials, soapHeader);
}
} catch (final Exception e) {
throw new RuntimeException(e);
}
return true;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
// TODO Auto-generated method stub
return false;
}
@Override
public void close(MessageContext context) {
// TODO Auto-generated method stub
}
@Override
public Set<QName> getHeaders() {
// TODO Auto-generated method stub
return null;
}
// ... default implementations of other methods go here
});
// as per Jean-Bernard Pellerin's comment setting handlerChain list here, after all handlers were added to list
binding.setHandlerChain(handlersList);
try {
SetExpressCheckoutReq sECR = new SetExpressCheckoutReq();
SetExpressCheckoutRequestType sECRDT = new SetExpressCheckoutRequestType();
sECRDT.setVersion("109.0");
SetExpressCheckoutRequestDetailsType details = new SetExpressCheckoutRequestDetailsType();
PaymentDetailsType paymentDetails = new PaymentDetailsType();
paymentDetails.setOrderDescription("Integrating Stuff Test Order");
paymentDetails.setInvoiceID("INVOICE-" + Math.random());
BasicAmountType orderTotal = new BasicAmountType();
orderTotal.setCurrencyID(CurrencyCodeType.EUR);
orderTotal.setValue("120.00");
paymentDetails.setOrderTotal(orderTotal);
paymentDetails.setPaymentAction(PaymentActionCodeType.SALE);
List<PaymentDetailsType> listaDetallesPago = new ArrayList<PaymentDetailsType>();
listaDetallesPago.add(paymentDetails);
details.setPaymentDetails(listaDetallesPago);
details.setReturnURL(returnURL);
details.setCancelURL(cancelURL);
sECRDT.setSetExpressCheckoutRequestDetails(details);
sECR.setSetExpressCheckoutRequest(sECRDT);
SetExpressCheckoutResponseType response = expressCheckoutPort.setExpressCheckout(sECR);
ackString = response.getAck().value();
System.out.println(ackString);
token = response.getToken();
for (ErrorType msg : response.getErrors()) {
System.out.println(msg.getLongMessage());
}
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
// get the token from the response
return token;
}
这是我收到的错误:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1959)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1077)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1091)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:250)
at com.sun.xml.ws.transport.http.client.HttpClientTransport.getOutput(HttpClientTransport.java:92)
at com.sun.xml.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:110)
at com.sun.xml.ws.protocol.soap.ClientMUPipe.process(ClientMUPipe.java:72)
at com.sun.xml.ws.handler.HandlerPipe.process(HandlerPipe.java:134)
at com.sun.xml.ws.handler.HandlerPipe.process(HandlerPipe.java:134)
at com.sun.xml.ws.client.Stub.process(Stub.java:125)
at com.sun.xml.ws.client.sei.SEIStub.doProcess(SEIStub.java:127)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:238)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:212)
at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:110)
at com.sun.proxy.$Proxy39.setExpressCheckout(Unknown Source)
at capsula.SetExpressCheckoutService.setExpressCheckout(SetExpressCheckoutService.java:168)
at capsula.SetExpressCheckoutService.main(SetExpressCheckoutService.java:56)
我试图搜索网络的每个部分以找到解决方案,但我不能。我从PayPal中读到了很多例子,但是它并没有告诉任何关于新版本的例子,因为在旧版本中有一种简单的方法来提出请求,包括请求中的凭据,而不是做那些糟糕的部分:
ObjectFactory objectFactory = new ObjectFactory();
// creating JAXBElement from headerObj
final JAXBElement<CustomSecurityHeaderType> requesterCredentials = objectFactory.createRequesterCredentials(headerObj);
handlersList.add(new SOAPHandler<SOAPMessageContext>() {
@Override
public boolean handleMessage(final SOAPMessageContext context) {
try {
// checking whether handled message is outbound one as per Martin Strauss answer
final Boolean outbound = (Boolean) context.get("javax.xml.ws.handler.message.outbound");
if (outbound != null && outbound) {
// obtaining marshaller which should marshal instance to xml
final Marshaller marshaller = JAXBContext.newInstance(CustomSecurityHeaderType.class).createMarshaller();
// adding header because otherwise it's null
final SOAPHeader soapHeader = context.getMessage().getSOAPPart().getEnvelope().addHeader();
// marshalling instance (appending) to SOAP header's xml node
marshaller.marshal(requesterCredentials, soapHeader);
}
} catch (final Exception e) {
throw new RuntimeException(e);
}
return true;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
// TODO Auto-generated method stub
return false;
}
@Override
public void close(MessageContext context) {
// TODO Auto-generated method stub
}
@Override
public Set<QName> getHeaders() {
// TODO Auto-generated method stub
return null;
}
// ... default implementations of other methods go here
});
// as per Jean-Bernard Pellerin's commententer code here setting handlerChain list here, after all handlers were added to list
binding.setHandlerChain(handlersList);
因为我不确定这是否正确解决。
所有帮助将不胜感激。谢谢! =)
答案 0 :(得分:1)
问题出在我自己生成的类中,当我尝试调用webservice时,我无法传递CustomSecurityHeader,因为没有正确生成类APIService。对于这种情况,经过调查,我弄清楚发生了什么。
起初我使用soapUI程序自动生成发送Paypal提供给开发人员的.wsdl文件的类。但是,我没有做的重要事情是建立一个必要的自定义参数来执行正确生成的代码:
-XadditionalHeaders -Xnocompile
这是为使用“wsimport”命令(对于Jax-WS库生成的代码)的其他教程提取的,并且使用此命令的人添加了这些参数。完整的一行是。我可以使用这样的终端控制台命令:
wsimport -keep -XadditionalHeaders -Xnocompile -p paypal.test Desktop / PayPalSvc.wsdl /
生成正确的类并传递CustomSecurityHeader。
我目前执行正确请求的代码是:
String usuario = "carlos.martinez_api1.netijam.com";
String password = "XEDdsafXSCE4";
String firma = "A6aFJz-KhDsdf7f-668iCsdfweFplAcbDlof-vWP5wsdfsdEAy9T-d.";
//Make encapsulated object of my own class cabeceraPeticiones
CabeceraPeticiones cabeceraPeticiones = CabeceraPeticiones.getInstanceCabecera(usuario, password, firma);
//Call the method that takes the header in the format that webservice needs
Holder<CustomSecurityHeaderType> cabeceraSeguridad = cabeceraPeticiones.getCabecera();
//Set the connection params to work properly and the webservice method that I want to execute
PayPalAPIInterfaceService pp = new PayPalAPIInterfaceService();
GetExpressCheckoutDetailsReq gECR = new GetExpressCheckoutDetailsReq();
GetExpressCheckoutDetailsRequestType gECDRT = new GetExpressCheckoutDetailsRequestType();
PayPalAPIAAInterface expressCheckoutPort = pp.getPayPalAPIAA();
((BindingProvider) expressCheckoutPort).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "https://api-aa-3t.sandbox.paypal.com/2.0/");
//I take the response from the webservice operation that I execute, passing the header and the webservice request param
GetExpressCheckoutDetailsResponseType response = expressCheckoutPort.getExpressCheckoutDetails(gECR, cabeceraSeguridad);