To post an Update on LinkedIn via your application, that is being built with Play 2.3.x, follow these steps ( this post summarizes the work done step by step).
1) Create a LinkedIn app (if you do not have one already)
Click here – LinkedIn’s Developer Quick Start Guide and create an app. Enter all the details including Site URL. The Site URL could be something like http://www.example.com (but it should be a valid site URL). Also, select the rw_nus setting under the OAuth User Agreement section (otherwise you wont be able to post updates on LinkedIn).
Once you have saved this app, you will get API Key & Secret Key. Take a note of this API Key & Secret Key. We would use them in our code.
2) If you are using Play, then add the API Key, Secret Key & Context URL(Callback URL) in application.conf file.
linkedin.key=<your_key> linkedin.secret=<your_secret_key> contextURL="localhost:9000"
3) Download a LinkedIn login image from linkedin.png & save it in “public/images” folder of app
4) Add following dependency in build.sbt (or Build.scala for Play 2.1.x or older versions)
"org.scribe" % "scribe" % "1.3.5"
5) Add following to routes file in conf folder
GET /linkedin/login controllers.LinkedInAPIController.linkedinLogin GET /linkedin/callback controllers.LinkedInAPIController.linkedinCallback
6) Let us now create LinkedInAPIController.scala to configure API Key, Secret Key and Callback URL . We would also use this scala file to request access token from LinkedIn & post an update on LinkedIn.
package controllers import org.scribe.builder.ServiceBuilder import org.scribe.builder.api.LinkedInApi import org.scribe.model.OAuthRequest import org.scribe.model.Response import org.scribe.model.Token import org.scribe.model.Verifier import org.scribe.model.Verb import org.scribe.oauth.OAuthService import play.api.Logger import play.api.Play import play.api.mvc.Action import play.api.mvc.Controller object LinkedInAPIController extends Controller { val POST_SUCCESS = 201 val apiKey: String = Play.current.configuration.getString("linkedin.key").get val apiSecret: String = Play.current.configuration.getString("linkedin.secret").get val server = Play.current.configuration.getString("contextURL").get var requestToken: Token = _ /** * Get OAuthService Request */ def getOAuthService: OAuthService = { new ServiceBuilder() .provider(classOf[LinkedInApi]) .apiKey(apiKey) .apiSecret(apiSecret) .scope("rw_nus") .callback(server + "/linkedin/callback") .build(); } def linkedinLogin: Action[play.api.mvc.AnyContent] = Action { try { requestToken = getOAuthService.getRequestToken val authUrl: String = getOAuthService.getAuthorizationUrl(requestToken) Redirect(authUrl) } catch { case ex: Exception => { Logger.error("Error During Login Through LinkedIn - " + ex) Ok(views.html.redirectMain("failure", server, "Cannot post message on LinkedIn")) } } } def linkedinCallback: Action[play.api.mvc.AnyContent] = Action { implicit request => try { getVerifier(request.queryString) match { case None => Ok(views.html.redirectMain("failure", server, "Cannot post message on LinkedIn")) case Some(oauth_verifier) => val verifier: Verifier = new Verifier(oauth_verifier) val accessToken: Token = getOAuthService.getAccessToken(requestToken, verifier); val oAuthRequest: OAuthRequest = new OAuthRequest(Verb.POST, "http://api.linkedin.com/v1/people/~/shares") // Posting message on LinkedIn val message = "Congratulations! You have posted your first message on LinkedIn via LinkedIn API of Scribe" val url = "http://www.knoldus.com/home.knol" val xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> \n" + "<share> \n" + " <comment>" + message + "</comment> \n" + "<content> \n" + "<submitted-url>" + url + "</submitted-url> \n" + "</content> \n" + "<visibility> \n" + "<code>anyone</code> \n" + "</visibility> \n" + "</share>\n" //add xml payload to request oAuthRequest.addPayload(xml) getOAuthService.signRequest(accessToken, oAuthRequest) oAuthRequest.addHeader("Content-Type", "text/xml") val response: Response = oAuthRequest.send response.getCode match { case POST_SUCCESS => Ok(views.html.redirectMain("success", server, "Thanks for sharing it with others on LinkedIn")) case _ => Ok(views.html.redirectMain("failure", server, "Cannot post message on LinkedIn")) } } } catch { case ex: Exception => { Ok(views.html.redirectMain("failure", server, "Cannot post message on LinkedIn")) } } } def getVerifier(queryString: Map[String, Seq[String]]): Option[String] = { val seq = queryString.get("oauth_verifier").getOrElse(Seq()) seq.isEmpty match { case true => None case false => seq.headOption } } }
7) Now let us create a template redirectMain.scala.html which would show status of clicking “Share on LinkedIn” link.
@(status:String, redirectUrl: String, response: String) @main("Share on LinkedIn"){ <script type="text/javascript"> function close_win(redirectUrl) { window.opener.location=redirectUrl window.opener.focus(); window.close(); } $(function() { if ('@status' == "success") { alert("@response") close_win('@redirectUrl'); } else { alert("@response") close_win('@redirectUrl'); } }); </script> }
So, this is how we can post updates on LinkedIn via Scribe using Scala & Play.
Filed under: Agile, JavaScript, Play Framework, Scala, Web Tagged: Eclipse, Javascript, LinkedIn, OAuth, play, Play framework, sbt, scala, Scribe
