Obtain referer in Java SOAP webservice - java

I feel like this should be straight forward. We are implementing a Java webservice using SOAP in Eclipse. We want to know who is calling the webservice. I would have though I could get the referer from the header somehow but am at a loss as to how to do it. We are using Axis 2.

copied from TechNick you can leverage axis2 for this. The fact you're using Eclipse is largely irrelevant, the code below should work fine.
//Import statement to import MessageContext class
import org.apache.axis2.context.MessageContext;
/*
* This method gets the client IP address using axis2 MessageContext
*
* #return Client IP : String
*/
private String getClientIP () {
return (String)(MessageContext.getCurrentMessageContext()).getProperty(MessageContext.REMOTE_ADDR);
}

Related

Extract data from soap service using java code

i am tring to extract response data from wsdl url using soapui java code. all are working good, but problem is in response.
in response i am getting ? instead of getting proper data.
Eclipse Console result
but when i am tring to hit wsdl url using soapui it is working fine.
check my code
package src.com;
import com.eviware.soapui.impl.wsdl.WsdlInterface;
import com.eviware.soapui.impl.wsdl.WsdlOperation;
import com.eviware.soapui.impl.wsdl.WsdlProject;
import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlImporter;
import com.eviware.soapui.model.iface.Operation;
public class Test {
public static void main(String[] args) throws Exception {
WsdlProject project = new WsdlProject();
WsdlInterface[] wsdls = WsdlImporter.importWsdl(project, "http://localhost:8080/SoapService/services/TestService?wsdl");
WsdlInterface wsdl = wsdls[0];
for (Operation operation : wsdl.getOperationList()) {
WsdlOperation wsdlOperation = (WsdlOperation) operation;
System.out.println("Request:\n"+wsdlOperation.createRequest(true));
System.out.println("\nResponse:\n"+wsdlOperation.createResponse(true));
}
}
}
Check Jars
Within the SoapUI application you are actually making a call out to the web service and getting a response. In your sample java code you are just generating a response XML from the WSDL file instead of actually calling out to the web service and it's defaulting any required values to have a ?. If you generate the same response within the SoapUI application you will see the same ? set for the findAllReturned element.
You can use the java SoapUI's WSDLSubmit class to make a call out to the web service and get a response back.
The answer to this linked question shows a code sample of how you would go about making an actual call out to the web service using the SoapUI java api:
https://stackoverflow.com/a/14814524/8127149
And this link has other examples of using the WSDLSubmit class:
http://www.programcreek.com/java-api-examples/index.php?api=com.eviware.soapui.impl.wsdl.WsdlSubmit

Mutual authentication with Spark Java

I am trying to achieve a mutually authenticated REST API server using spark-java and from the documentation I see:
secure(keystoreFilePath, keystorePassword, truststoreFilePath, truststorePassword);
... which looks like exactly what I need. However I am only able to do one way authentication of the server, the client certificate never seems to be verified against the truststore. I'm using version 2.1, any advise or pointers would be greatly appreciated.
It seems that Spark in version 2.6.0 has added what you need. Now, there is a second version of secure:
/**
(...)
* #param needsClientCert Whether to require client certificate to be supplied in
* request
(...)
*/
public synchronized Service secure(String keystoreFile,
String keystorePassword,
String truststoreFile,
String truststorePassword,
boolean needsClientCert)
It sets setNeedClientAuth(true) and setWantClientAuth(true) on the underlying Jetty webserver SslContextFactory object.

How to integerate Mpesa Api with android

I am making loan app. and I am stuck on this How to Integrate MPESA because I live outside Africa.
Here is the link PESAPI. I am done with step 3 but now I cant understand what to do next.
Q 1) Can I integrate it with my Loan app android ?
Q 2) What to do next please guide me I am stuck on this from last one weak.
If you are still interested, Safaricom recently introduced a REST based interface for consumption of MPesa APIs. They have documentation there, and a pretty good tutorial on how to use it can be found here. For using on your app, you will need a back-end interface to act as a mediator to MPesa, as most of their APIs are asynchronous.
Pesa pi cannot be used for the intended purpose. What pesapi does is take confirmation message from your android mobile and pushes that message to your application.
Message in this context is a message that mpesa sends to the registered mobile number of the payee once a payment is done via lipa na mpesa and pay bill.
What Mutwiri was suggesting, is for you to take the API from mpesa site http://www.safaricom.co.ke/business/sme/m-pesa-payment-solutions/m-pesa-api
and build a middle ware for your application.
Pointers: Check out the B2C and C2B- paybill and lipa na mpesa documentation.
M-PESA API Online Checkout Java / Android How to
Following release of M-PESA API, you will need to create a web service client that does SOAP requests and process responses from API calls
I will provide a quick start guide for java developers geared towards integrating existing Java applications.
Pre-requisites
JDK 7 or latest
Instruction steps
Download Full M-PESA API Guide from safaricom website
Read through Developers Guide C2B_OnlineCheckout_V2.0.doc
Generate JAX-WS artifacts . Your client will use this api to access the published web service.
Generate JAX-WS artifacts
We will use wsimport tool is used to parse checkout WSDL file and generate required files.
mkdir src
wsimport -XadditionalHeaders -clientjar safaricom-lipanampesa-onlinecheckout-wsdl.jar -s src -p ke.co.makara.integration.mpesa.lnmocheckout http://safaricom.co.ke/mpesa_online/lnmo_checkout_server.php?wsdl
Check wsimport --help to understand above options;
Note the package directory for generated artefacts. WSDL is hosted on the lipa na M-PESA endpoint. For this purpose we use the production url. -clientjar option, new in Java 7, simplifies things. You would otherwise have to use -wsdllocation /META-INF/wsdl/Checkout.wsdl option. And copy the wsdl in META-INF after to mitigate the Java 6 wsimport limitation. See limitation below.
Optionally create source jar
While inside src folder run command.
jar cvf safaricom-lipanampesa-onlinecheckout-source-wsdl.jar ke/
Next we use the web service artifacts to invoke the web service from a web service client.
Generated artifacts
Service Endpoint Interface (SEI) - LNMOPortType.java
Service class - LnmoCheckoutService.java
If a wsdl:fault is present in the WSDL, an Exception class
Java classes mapped from schema types eg ProcessCheckOutRequest.java
If a wsdl:message is present in WSDL, asynchronous response beans eg ProcessCheckOutResponse.java
Web Service Client
Next we use the web service artifacts to invoke the web service from a web service client.
This can be a servlet invoked from front-end. Out of scope. For simplicity I will create a java class ~ a standalone console
Create a java class say LNMOCheckoutTester
In the Java client application, create an instance of the LnmoCheckoutService service
LnmoCheckoutService lnmoCheckoutService = new LnmoCheckoutService(); // lina na mpesa online checkout instance
The Service class will be created during the build.
Obtain a proxy to the service from the service using the getLnmoCheckout() method
LNMOPortType soap = lnmoCheckoutService.getLnmoCheckout();
The port carries the protocol binding and service endpoint address information.
Configure the service endpoint
Configure the request context properties on the javax.xml.ws.BindingProvider interface
((BindingProvider)soap).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url + "lnmo_checkout_server.php"); // specifying this property on the RequestContext
JAX-WS provides support for the dynamic invocation of service endpoint operations.
I store the web service url in database and append the wsdl endpoint to this url. This configures the endpoint at runtime.
Compose our client request M-PESA checkout message
This is the message payload
ProcessCheckOutRequest checkOutRequest = objFactory.createProcessCheckOutRequest();
checkOutRequest.setMERCHANTTRANSACTIONID("54635469064");
checkOutRequest.setREFERENCEID("TD346534GH");
checkOutRequest.setAMOUNT(13300);
checkOutRequest.setMSISDN("0721XXXXXX");
checkOutRequest.setENCPARAMS("");
checkOutRequest.setCALLBACKURL("https://makara.co.ke:8443/odt/checkout");
checkOutRequest.setCALLBACKMETHOD("GET");
checkOutRequest.setTIMESTAMP(String.valueOf(date.getTime()));
Configure request headers
Follow business rules in Safaricom document to build the password. See attached code.
For String merchantId, String passkey, Date requestTimeStamp; Convert the concatenated string to bytes, Hash the bytes to get arbitary binary data and Convert the binary data to string use base64
CheckOutHeader requestHeader = objFactory.createCheckOutHeader();
requestHeader.setMERCHANTID(MERCHANT_ID);
Date timestamp = new Date();
String encryptedPassword = getEncryptedPassword(MERCHANT_ID, PASSKEY, timestamp);
requestHeader.setPASSWORD(encryptedPassword.toUpperCase());
requestHeader.setTIMESTAMP(String.valueOf(timestamp.getTime()));
Invoke the service endpoint with the dispatch stab-based client
soap.processCheckOut(checkOutRequest, requestHeader);
Process the response message from the service as per your business requirement
ProcessCheckOutResponse checkOutResponse = new ProcessCheckOutResponse();
checkOutResponse.getRETURNCODE();
checkOutResponse.getDESCRIPTION();
checkOutResponse.getTRXID();
checkOutResponse.getCUSTMSG();
Tracing SOAP Traffic
One of the usual steps involved in the debugging of Web Services applications is to inspect the request and response SOAP messages
Configure client to dump requests and response with JAX-WS
System.setProperty("com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump", "true");
Source code
/*
* LNMOCheckoutTester.java
*
* Nov 20, 2016 Joseph Makara - Created File to tester Lina Na M-PESA Online checkout
*
*
*/
package testMe;
import java.io.*;
import java.security.*;
import java.util.*;
import javax.net.ssl.*;
import javax.xml.ws.*;
import ke.co.makara.integration.mpesa.lnmocheckout.*;
import org.apache.commons.codec.binary.*;
/**
* #author Joseph Makara
*
*/
public class LNMOCheckoutTester {
private static final String PASSKEY = "234fdsghfsg5654dgfhgf6dsfdsafsd43dgfhdgfdgfh74567";
private static final String MERCHANT_ID = "678fsgd54354";
private static final String REFERENCE_ID = "";
private static final String ENDPOINT_URL = "https://safaricom.co.ke/mpesa_online/";
private static final String CALLBACK_URL = "https://makara.co.ke:8443/odt/checkout";
private static final String CALLBACK_METHOD = "GET";
static {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String hostname, SSLSession session) {
if (hostname.equals("safaricom.co.ke")) return true;
return false;
}
});
}
/**
* #param args
*/
public static void main(String[] args) {
LNMOPortType soap = outBoundLNMOCheckout(ENDPOINT_URL);
ObjectFactory objFactory = new ObjectFactory();
CheckOutHeader requestHeader = objFactory.createCheckOutHeader();
requestHeader.setMERCHANTID(MERCHANT_ID);
Date timestamp = new Date();
String encryptedPassword = getEncryptedPassword(MERCHANT_ID, PASSKEY, timestamp);
requestHeader.setPASSWORD(encryptedPassword);
requestHeader.setTIMESTAMP(String.valueOf(timestamp.getTime()));
ProcessCheckOutRequest checkOutRequest = objFactory.createProcessCheckOutRequest();
checkOutRequest = processCheckOut(timestamp);
soap.processCheckOut(checkOutRequest, requestHeader);
ProcessCheckOutResponse checkOutResponse = new ProcessCheckOutResponse();
checkOutResponse.getRETURNCODE();
checkOutResponse.getDESCRIPTION();
checkOutResponse.getTRXID();
checkOutResponse.getENCPARAMS();
checkOutResponse.getCUSTMSG();
}
private static ProcessCheckOutRequest processCheckOut(Date date){
ProcessCheckOutRequest checkOutRequest = new ProcessCheckOutRequest();
checkOutRequest.setMERCHANTTRANSACTIONID("54635469064");
checkOutRequest.setREFERENCEID("TD346534GH");
checkOutRequest.setAMOUNT(3.45);
checkOutRequest.setMSISDN("0721826284");
checkOutRequest.setENCPARAMS("");
checkOutRequest.setCALLBACKURL(CALLBACK_URL);
checkOutRequest.setCALLBACKMETHOD(CALLBACK_METHOD);
checkOutRequest.setTIMESTAMP(String.valueOf(date.getTime()));
return checkOutRequest;
}
/**
* Convert the concatenated string to bytes
* Hash the bytes to get arbitary binary data
* Convert the binary data to string use base64
*
* #param merchantId
* #param passkey
* #param date
* #return
*/
private static String getEncryptedPassword(String merchantId, String passkey, Date date) {
String encodedPassword = null;
StringBuilder builder = new StringBuilder(merchantId)
.append(passkey)
.append(date.getTime());
try {
String sha256 = getSHA256Hash(builder.toString());
return new String(Base64.encodeBase64(sha256.getBytes("UTF-8")));;
} catch (NoSuchAlgorithmException | UnsupportedEncodingException ex) {
ex.printStackTrace();
}
return encodedPassword;
}
private static LNMOPortType outBoundLNMOCheckout(String url) {
System.setProperty("com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump", "true");
LnmoCheckoutService lnmoCheckoutService = new LnmoCheckoutService();
LNMOPortType soap = lnmoCheckoutService.getLnmoCheckout();
((BindingProvider)soap).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
url + "lnmo_checkout_server.php");
return soap;
}
private static String getSHA256Hash(String input) throws NoSuchAlgorithmException {
MessageDigest mDigest = MessageDigest.getInstance("SHA-256");
byte[] result = mDigest.digest(input.getBytes());
StringBuffer sb = new StringBuffer();
for (int i = 0; i < result.length; i++) {
sb.append(Integer.toString((result[i] & 0xff) + 0x100, 16).substring(1));
}
return sb.toString();
}
}
Sample Soap Request
[HTTP request - https://safaricom.co.ke/mpesa_online/lnmo_checkout_server.php]---
Accept: text/xml, multipart/related
Content-Type: text/xml; charset=utf-8
SOAPAction: ""
User-Agent: JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Header>
<ns2:CheckOutHeader xmlns:ns2="tns:ns">
<MERCHANT_ID>F2678987M</MERCHANT_ID>
<PASSWORD>QQFSOITZB5OJMJTW073/SCWLN5WMDL6LO0FP6DJZ8TQ=</PASSWORD>
<TIMESTAMP>1479116220855</TIMESTAMP>
</ns2:CheckOutHeader>
</S:Header>
<S:Body>
<ns2:processCheckOutRequest xmlns:ns2="tns:ns">
<MERCHANT_TRANSACTION_ID>54635469064</MERCHANT_TRANSACTION_ID>
<REFERENCE_ID>TD346534GH</REFERENCE_ID>
<AMOUNT>3.45</AMOUNT>
<MSISDN>0721826284</MSISDN>
<ENC_PARAMS></ENC_PARAMS>
<CALL_BACK_URL>https://makara.co.ke:8443/odt/checkout</CALL_BACK_URL>
<CALL_BACK_METHOD>lnmo</CALL_BACK_METHOD>
<TIMESTAMP>1479116220855</TIMESTAMP>
</ns2:processCheckOutRequest>
</S:Body>
</S:Envelope>
You will only need to contact Safaricom to get Demo test org details (Merchant ID and PassKey)
Client jar
Source code
The M-Pesa API is currently a SOAP API and SOAP isn't native on Android so it's a bunch of work to integrate the API on your app. I wrote Chowder to help developers handle M-Pesa easily and here's all you have to do:
//Add a new dependency
dependencies {
compile 'com.toe.chowder:chowder:0.7.6'
}
Create a Chowder instance:
//You can create a single global variable for Chowder like this
Chowder chowder = new Chowder(YourActivity.this, PAYBILL_NUMBER, PASSKEY, this);
//You can also add your callback URL using this constructor
Chowder chowder = new Chowder(YourActivity.this, PAYBILL_NUMBER, callbackUrl ,PASSKEY, this);
Process your payment:
//You can then use processPayment() to process individual payments
chowder.processPayment(amount, phoneNumber, productId);
Confirm payment:
chowder.checkTransactionStatus(PAYBILL_NUMBER, transactionId);
There's more sample code and a test Paybill number and passkey here.
This looks like a year ago but you may look at this if still not found a solution.
https://bitbucket.org/mwanzias/mpesaonlinecheckout/downloads/README.md
from here you will be able to post from the android application direct to the back end system that does the mpesa communication.
The demo described here gives online checkout capabilities if you want it extended to B2C, B2B and C2B notifications then you may contact the owner.
you could also look at the following and see if you can fork and adapt it.
https://github.com/aksalj/pesajs

Write proxy/wrapper class for own service in jersey

I want to access a full rest service with basic http auth running.
However there is no way to for the javascript browser client to suppress the authenticate box when a wrong credential is provided.
I thought about different methods to solve this problem
someone suggested to remove the WWW-Authenticate Header with a filter (i dont think this is a clean approach)
i could rewrite my app to not use Basic Http Auth at all (i think this is too much trouble)
i could write a proxy that talks to my regular service
I like the last approach the best.
I keep my regular Rest Interface, but also have the option to use this interface with clients that are not that flexible.
Furthermore I can later proxy Http Requests unsupported by some browsers.
The idea is to have a /api/proxy/{request} path that proxies to /api/{request} and returns a Facebook-Graph-like JSON query { data: {data}, error: {error}}
This is the stub of the Proxy class
#Path("proxy")
public class ProxyResource {
#GET()
#Path("{url: [a-zA-Z/]*}")
public String get(#Context Request request, #PathParam("url") String url) {
// remove proxy/ from path
// resend request
// verify result
}
}
I can access the Request (which seems to be a ContainerRequest). How can I modify the request without building it from scratch to resend it.
Edit: when somebody knows a better approach i am delighted to hear about it.
As I started to digg deeper into this, i found out that not the 401 was the problem. The www-authenticate header sent back from the server caused the browser to open the login box.
If somebody is interested I've written a little nodejs proxy to remove a www-authenticate from all server requests.
https://gist.github.com/ebb9a5052575b0a3f41f
As this is not the answer to my original question I will leave it open.

Calling a Web Service from Seam

A simple question, but could someone provide sample code as to how would someone call a web service from within the JBoss Seam framework, and process the results?
I need to be able to integrate with a search platform being provided by a private vendor who is exposing his functionality as a web service. So, I'm just looking for some guidance as to what the code for calling a given web service would look like.
(Any sample web service can be chosen as an example.)
There's roughly a gajillion HTTP client libraries (Restlet is quite a bit more than that, but I already had that code snippet for something else), but they should all provide support for sending GET requests. Here's a rather less featureful snippet that uses HttpClient from Apache Commons:
HttpClient client = new HttpClient();
HttpMethod method = new GetMethod("http://api.search.yahoo.com/WebSearchService/V1/webSearch?appid=restbook&query=HttpClient");
client.executeMethod(method);
import org.restlet.Client;
import org.restlet.data.Protocol;
import org.restlet.data.Reference;
import org.restlet.data.Response;
import org.restlet.resource.DomRepresentation;
import org.w3c.dom.Node;
/**
* Uses YAHOO!'s RESTful web service with XML.
*/
public class YahooSearch {
private static final String BASE_URI = "http://api.search.yahoo.com/WebSearchService/V1/webSearch";
public static void main(final String[] args) {
if (1 != args.length) {
System.err.println("You need to pass a search term!");
} else {
final String term = Reference.encode(args[0]);
final String uri = BASE_URI + "?appid=restbook&query=" + term;
final Response response = new Client(Protocol.HTTP).get(uri);
final DomRepresentation document = response.getEntityAsDom();
document.setNamespaceAware(true);
document.putNamespace("y", "urn:yahoo:srch");
final String expr = "/y:ResultSet/y:Result/y:Title/text()";
for (final Node node : document.getNodes(expr)) {
System.out.println(node.getTextContent());
}
}
}
}
This code uses Restlet to make a request to Yahoo's RESTful search service. Obviously, the details of the web service you are using will dictate what your client for it looks like.
final Response response = new Client(Protocol.HTTP).get(uri);
So, if I understand this correctly, the above line is where the actual call to the web service is being made, with the response being converted to an appropriate format and manipulated after this line.
Assuming I were not using Restlet, how would this line differ?
(Of course, the actual processing code would be significantly different as well, so that's a given.)

Categories