Sending a document to Stripe using Play! Scala 2.5 - scala

I want to send a file to Stripe using Play! Scala 2.5.
The documentation says that the request should be (curl equivalent) like this:
curl https://uploads.stripe.com/v1/files \
-u sk_test_BQokikJOvBiI2HlWgH4olfQ2: \
-F purpose=dispute_evidence \
-F file="#/path/to/a/file.jpg"
Mine is:
def test: Action[MultipartFormData[TemporaryFile]] = Action(parse.multipartFormData) { request =>
val image = request.body.file("picture").get
val info = Map("purpose" -> Seq("identity_document"))
val attachment =
FilePart[TemporaryFile](
key = "file",
filename = "file",
contentType = image.contentType,
ref = image.ref)
val formData: MultipartFormData[TemporaryFile] =
MultipartFormData(
dataParts = info,
files = Seq(attachment),
badParts = Seq.empty)
import services.MultipartFormDataWritable.anyContentAsMultipartFormWritable
wSClient
.url("https://uploads.stripe.com/v1/files")
.withAuth("secret_key", "", WSAuthScheme.BASIC)
.post(formData)
.map(response => println(response.body))
Ok
}
But Stripe returns me this Bad Request error:
"error": {
"type": "invalid_request_error",
"message": "Missing required param: file.",
"param": "file"
}
What am I doing wrong?

This works:
val file = request.body.file("picture").get
val filename = file.filename
val contentType = file.contentType.getOrElse(logAndThrowException("Id card without content type"))
if (contentType != "image/png" && contentType != "image/jpeg" && contentType != "image/jpg") {
logAndThrowException("Wrong content type (jp[e]g or png required)")
}
val tmpFile = file.ref.file
wSClient
.url("https://uploads.stripe.com/v1/files")
.withAuth(stripeTestAPIKey, "", WSAuthScheme.BASIC)
.withHeaders("Stripe-Account" -> stripeAccount)
.post(
Source(
iterable =
FilePart("file", filename, Option("text/plain"),
FileIO.fromPath(tmpFile.toPath)) ::
DataPart("purpose", "identity_document") ::
List()))

Related

Playfarmework testing: Upload file with Fake Request and mulipartFormData

I'm trying to unit test a file upload through multipartFormData and returning status 200 if it returns back the uploaded url. However, I keep getting status 400 and unsure why its been unsucessful.
I've found online of the call needs to be writeable and have included a writeable class which i've imported as lazy val
"return a 200 if successful" in new SetUp {
val fakeFileName = "testImage.png"
val fakeUploadImageUrl = "https://s3.fakeImageUrl.png"
val imageFile = new File(fakeFileName)
val tempFile = TemporaryFile(imageFile)
val multipartFormData = new MultipartFormData(
dataParts = Map(),
files = Seq(FilePart[TemporaryFile]("file", fakeFileName, Some("text/plain"), tempFile)),
badParts = Seq()
)
when(imageService.uploadWebImage(any(), any())).thenReturn(Future.successful(fakeUploadImageUrl))
val request = FakeRequest(HttpVerbs.POST, s"/internal/challengesv2/v1/instances/image/$fakeFileName")
.withBody(multipartFormData)
val response = testController.uploadImage(fakeFileName).apply(request)
assert(status(response.run()) === 200)
assert(contentAsJson(response.run()) === Json.toJson(fakeUploadImageUrl))
}
expect 200 but returning 400

how can i write the test cases for file Uploading through extractRequestContext in akka http services

Pls suggest here I have an upload service in Akka HTTP micro service it's working fine. now I need to write the test cases for below code
path( "file-upload") {
extractClientIP { ip =>
optionalHeaderValueByName(Constants.AUTH) { auth =>
(post & extractRequestContext) { request =>
extractRequestContext {
ctx => {
implicit val materializer = ctx.materializer
implicit val ec = ctx.executionContext
val currentTime = TimeObject.getCurrentTime()
fileUpload("fileUpload") {
case (fileInfo, fileStream) =>
val localPath = Configuration.excelFilePath
val uniqueidString = "12345"
val filename = uniqueidString + fileInfo.fileName
val sink = FileIO.toPath(Paths.get(localPath) resolve filename)
val writeResult = fileStream.runWith(sink)
onSuccess(writeResult) { result =>
result.status match {
case Success(_) =>
var excelPath = localPath + File.separator + uniqueidString + fileInfo.fileName
var doc_count = itemsExcelParse(excelPath, companyCode, subCompanyId, userId)
val currentTime2 = TimeObject.getCurrentTime()
var upload_time = currentTime2 - currentTime
val resp: JsValue = Json.toJson(doc_count)
complete {
val json: JsValue = Json.obj("status" -> Constants.SUCCESS,
"status_details" -> "null", "upload_details" -> resp)
HttpResponse(status = StatusCodes.OK, entity = HttpEntity(ContentType(MediaTypes.`application/json`), json.toString))
}
case Failure(e) =>
complete {
val json: JsValue = Json.obj("status" -> Constants.ERROR, "status_details" -> Constants.ERROR_445)
HttpResponse(status = StatusCodes.BandwidthLimitExceeded, entity = HttpEntity(ContentType(MediaTypes.`application/json`), json.toString))
}
}
}
}
}
}
}
}
}
}
I have tried test cases but it's not working
" File upload " should "be able to upload file" in {
val p: Path = Paths.get("E:\\Excel\\Tables.xlsx")
val formData = Multipart.FormData.fromPath("fileUpload", ContentTypes.NoContentType, p, 1000)
Post(s"/file-upload", formData) -> route -> check {
println(" File upload - file uploaded successfully")
status shouldBe StatusCodes.OK
responseAs[String] contains "File successfully uploaded"
}
}
I have changed content type also into application/octet-stream. File not uploaded to the server please suggest here how can I write the test case for file uploading.

Scala liftweb framework

I have two checkboxes and on submit I want the user to download two different files, how do I go about this? I need help as am not able to get any online material on this. I am new to this framework.
This is what I've tried so far
def render = {
def onSubmit1() : LiftResponse = {
val userInput1 = S.param("getit").openOr("")
val userInput2 = S.param("getit2").openOr("")
val checkbox1 = S.param("yes").openOr("")
val checkbox2 = S.param("yes").openOr("")
val fileToDownload = funFile(as, art, top)
val fileName = "My File"
if (fileToDownload.equals()) {
return S.redirectTo("/Somewhere")
} else {
InMemoryResponse(
fileToDownload.mkString("\n").getBytes("UTF-8"),
"Content-Type" -> "text/plain; charset=utf8" ::
"Content-Disposition" -> s"attachment; filename=$fileName" :: Nil,
cookies = Nil, code = 200)
}
"#submitButton" #> SHtml.onSubmitUnit(onSubmit1)
I found a way to do that and that is to zip the two files using this function
How do I archive multiple files into a .zip file using scala? ,
if (checkbox1.getOrElse("") == "checked" && checkbox2.getOrElse("") == "checked") {
val checkboxIterable1: Iterable[String] = filegetter1
val checkboxFile1 = new File("checkboxFile1.csv")
using(new FileWriter(checkboxFile1))(writer =>
fileGetter1.foreach { d =>
writer.write(d)
})
fileGetter1
val checkboxIterable2: Iterable[String] = fileGetter2
val checkboxFile2 = new File("checkboxFile2.csv")
using(new FileWriter(checkboxFile2))(writer =>
fileGetter2.foreach { d =>
writer.write(d)
})
fileGetter2
val zipFile = zip("Zipped file", List("checkboxFile1.csv", "checkboxFile2.csv"))
val zipFileName = "Zipped file"
val zipToBArray = new BufferedInputStream(new FileInputStream(zipFileName))
val getByteArray = Stream.continually(zipToBArray.read).takeWhile(-1 !=).map(_.toByte).toArray
InMemoryResponse(
getByteArray,
"Content-Type" -> "application/zip; charset=utf8" ::
"Content-Disposition" -> s"attachment; filename=file.zip" :: Nil,
cookies = Nil, code = 200)
}

How to form a data using MultiPart/form-data in Play scala?

I don't know how to send multipart data in play scala Test case(Specs2).
In my project, method receives multipart data, code look like this
def school_register() = Action(parse.multipartFormData) { implicit request =>
}
In my test case using Specs2 how to form multipart data manually and want hit the school_register method. Once method hitted values are inserted into DB. I have four parameters regno=100,name="xxxx", address="xxx", std=5. Without multipart its working but i have to use multipart data.
Without Multipart i'm using like this
"com.example.schooladmin" should {
"responds with 200 for addSchoolRegister action with all required parameters" in new WithApplication {
val controller = new TestController()
val result = controller.school_registerr() .apply(FakeRequest().withFormUrlEncodedBody(
“Reg No” -> “100”,“Name” -> “XXX”,“Address” -> “XXXXX”,“std” -> “5”))
status(result) must equalTo(OK)
}
}
Here is how I'm doing this, I create a temporary file and I post it with withMultipartFormDataBody:
val tempFile = TemporaryFile(new java.io.File("../server/idCards/5e7b7c6c-98b3-4245-a5fb-405c9cc904f4"))
val part = FilePart[TemporaryFile](key = "picture", filename = "the.file", contentType = Some("image/jpeg"), ref = tempFile)
val formData = MultipartFormData(dataParts = Map(), files = Seq(part), badParts = Seq(), missingFileParts = Seq())
val Some(result) = route(FakeRequest(userDomain.routes.UserController.createIdCard())
.withMultipartFormDataBody(formData))
status(result) mustEqual OK

Sending multi part form data in post method in play/scala

How can I send multi part form data in post method in play scala
using : scalaVersion:2.11.7
playVersion-2.1.5
You need to do a little code, then you can use it like
val data = MultipartFormData(formFields, "asdasboundarystringas")
WS.url(myUrl).post(data.body)
The code of MultipartFormData you can find on the github: https://gist.github.com/EECOLOR/7649144
UPDATE
Another method, I have been try it with Play 2.4.3
package controllers
import play.api.Play.current
import play.api.libs.ws._
import play.api._
import play.api.mvc._
import com.ning.http.client.AsyncHttpClient
import com.ning.http.client.multipart.FilePart
import com.ning.http.client.multipart.StringPart
import java.io.File
class Application extends Controller {
def index = Action {
val url = "http://symlink.dk/code/php/submit/"
val asyncHttpClient:AsyncHttpClient = WS.client.underlying
val postBuilder = asyncHttpClient.preparePost("http://symlink.dk/code/php/submit/")
val builder = postBuilder.addBodyPart(new StringPart("myField", "abc", "UTF-8"))
.addBodyPart(new StringPart("myField1", "abc1", "UTF-8"))
.addBodyPart(new StringPart("myField2", "abc2", "UTF-8"))
.addBodyPart(new FilePart("myFile", new File("app/controllers/Application.scala")))
val response = asyncHttpClient.executeRequest(builder.build()).get();
Ok(response.getResponseBody)
}
}
Symlink does not verify file part, so I am not sure about it, but fileds definitely was send
UPDATE
With Authentication and file verification
package controllers
import play.api.Play.current
import play.api.libs.ws._
import play.api._
import play.api.mvc._
import com.ning.http.client.AsyncHttpClient
import com.ning.http.client.multipart.FilePart
import com.ning.http.client.multipart.StringPart
import java.io.File
import org.apache.commons.codec.binary.Base64.encodeBase64
class Application extends Controller {
def index = Action {
val url = "http://httpbin.org/post"
val name = "MyUserName"
val password = "MyPassword"
val encodedCredentials =
new String(encodeBase64("%s:%s".format(name, password).getBytes))
val asyncHttpClient:AsyncHttpClient = WS.client.underlying
val postBuilder = asyncHttpClient.preparePost(url)
val builder = postBuilder
.addHeader("Authorization", "Basic " + encodedCredentials)
.addBodyPart(new StringPart("myField", "abc", "UTF-8"))
.addBodyPart(new StringPart("myField1", "abc1", "UTF-8"))
.addBodyPart(new StringPart("myField2", "abc2", "UTF-8"))
.addBodyPart(new FilePart("myFile", new File("app/controllers/Application.scala")))
val response = asyncHttpClient.executeRequest(builder.build()).get();
Ok(response.getResponseBody)
}
}
Echo of posted data:
{
"args": {},
"data": "",
"files": {
"myFile": "package controllers\n\nimport play.api.Play.current\nimport play.api.libs.ws._\nimport play.api._\nimport play.api.mvc._\nimport com.ning.http.client.AsyncHttpClient\nimport com.ning.http.client.multipart.FilePart\nimport com.ning.http.client.multipart.StringPart\nimport java.io.File\nimport org.apache.commons.codec.binary.Base64.encodeBase64\n\nclass Application extends Controller {\n\n def index = Action {\n// val url = \"http://symlink.dk/code/php/submit/\"\n val url = \"http://httpbin.org/post\"\n\n val name = \"MyUserName\"\n val password = \"MyPassword\"\n\n val encodedCredentials =\n new String(encodeBase64(\"%s:%s\".format(name, password).getBytes))\n\n val asyncHttpClient:AsyncHttpClient = WS.client.underlying\n val postBuilder = asyncHttpClient.preparePost(url)\n val builder = postBuilder\n .addHeader(\"Authorization\", \"Basic \" + encodedCredentials)\n .addBodyPart(new StringPart(\"myField\", \"abc\", \"UTF-8\"))\n .addBodyPart(new StringPart(\"myField1\", \"abc1\", \"UTF-8\"))\n .addBodyPart(new StringPart(\"myField2\", \"abc2\", \"UTF-8\"))\n .addBodyPart(new FilePart(\"myFile\", new File(\"app/controllers/Application.scala\")))\n val response = asyncHttpClient.executeRequest(builder.build()).get();\n Ok(response.getResponseBody)\n }\n\n}\n"
},
"form": {
"myField": "abc",
"myField1": "abc1",
"myField2": "abc2"
},
"headers": {
"Accept": "*/*",
"Authorization": "Basic TXlVc2VyTmFtZTpNeVBhc3N3b3Jk",
"Content-Length": "1991",
"Content-Type": "multipart/form-data; boundary=ZUeOacX0k9AyI7O12kXDuV5gucDyh2IcA",
"Host": "httpbin.org",
"User-Agent": "AHC/1.0"
},
"json": null,
"origin": "111.111.111.11",
"url": "http://httpbin.org/post"
}
UPDATE
just for clarification - if you do not need to send file as part of the form then you do not need to access underlying WSClient and can use trivial WS
val url = "http://httpbin.org/post"
val name = "MyUserName"
val password = "MyPassword"
val result = WS.url(url)
.withAuth(name, password, WSAuthScheme.BASIC)
.post(
Map(
"myField" -> Seq("myValue"),
"myField1" -> Seq("myValue1"),
"myField2" -> Seq("myValue2")
)
)
val response = Await.result(result, 10 seconds)
Ok(response.body)
request that this code send:
{
"args": {},
"data": "",
"files": {},
"form": {
"myField": "myValue",
"myField1": "myValue1",
"myField2": "myValue2"
},
"headers": {
"Accept": "*/*",
"Authorization": "Basic TXlVc2VyTmFtZTpNeVBhc3N3b3Jk",
"Content-Length": "51",
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
"Host": "httpbin.org",
"User-Agent": "AHC/1.0"
},
"json": null,
"origin": "111.111.111.11",
"url": "http://httpbin.org/post"
}
Thanks Andriy Kuba!
I've made some changes (WS.client.underlying didn't work for me)
I m running with play 2.4.
package utils
import com.ning.http.client.{AsyncHttpClient, ListenableFuture, Request, Response}
import com.ning.http.client.cookie.Cookie
import com.ning.http.client.multipart.{FilePart, StringPart}
/**
* Created by ozma on 27/05/16.
*/
object WsExtend {
def postFile(url: String,
files: List[(String, String)] = List(),
bodyParams: List[(String, String)] = List(),
cookies: List[Cookie] = List(),
headers: Map[String, String] = Map(),
encoding: String = "UTF-8"): Response = {
postFileAsync(url, files, bodyParams, cookies, headers, encoding).get()
}
def postFileAsync(url: String,
files: List[(String, String)] = List(),
bodyParams: List[(String, String)] = List(),
cookies: List[Cookie] = List(),
headers: Map[String, String] = Map(),
encoding: String = "UTF-8"): ListenableFuture[Response] = {
val asyncHttpClient:AsyncHttpClient = new AsyncHttpClient()
val postBuilder: AsyncHttpClient#BoundRequestBuilder = asyncHttpClient.preparePost(url)
files.foreach(e => postBuilder.addBodyPart(new FilePart(e._1, new java.io.File(e._2))))
bodyParams.foreach(e => postBuilder.addBodyPart(new StringPart(e._1, e._2, encoding)))
cookies.foreach(c => postBuilder.addCookie(c))
headers.foreach(h => postBuilder.addHeader(h._1, h._2))
val request: Request = postBuilder.build()
asyncHttpClient.executeRequest(request)
}
}
This is how I used it with Silhouette CookieAuthenticator
"cookie" is a header called "Set-Cookie" from login response.
WsExtend.postFile(
url=url,
files = List("fileparamname" -> filepath),
bodyParams = List("albumName" -> albumName),
headers = Map("Cookie" -> cookie)