Using the Holvi API with ruby

Warning, this a rather old article I am moving over from an old blog, it might be deprecated. — Originally posted on April, 7 2015

Since the holvi API is still in beta, I won’t publish the API link as it could change in future and nobody want’s obsolete links in the wild.

What you need for the API to work

  1. A Token from holvi (contact holvi support to receive one)
  2. The pool. This is in the URL of your holvi account, for example https://holvi.com/group/VBk12y this means VBk12y is your pool.
  3. The API URL (contact holvi support)
  4. One or multiple products from in your holvi shop.

Configuration

So let’s get started. First of all we will create a yaml file containing the configuration.

development:
token: 9IkxlgAV9mpdYNzvSeFvFJ0d34rR4P
pool: VBk12y
cancel_url: https://localhost:3000/cancel/
success_url: http://localhost:3000/success/
failure_url: https://localhost:3000/failure/

test:
token: mytoken
pool: mypool
cancel_url: https://lcx.wien/cancel/
success_url: https://lcx.wien/success/
failure_url: https://lcx.wien/failure/

production:
token: 9IkxlgAV9mpdYNzvSeFvFJ0d34rR4P
pool: VBk12y
cancel_url: http://www.myapp.at/cancel/
success_url: http://www.myapp.at/success/
failure_url: http://www.myapp.at/failure/

Now to the code

We first have to send the holvi API a request for the shop URL. We will pass in the product the customer want’s to purchase, customer details and the cancel, success and failure url. Holvi in turn will send us a checkout URL and a details URL. More about those later.

First we create the holiv_request hash and fill in our data.

holvi_request = {}
holvi_request["pool"] = SHOP_CONFIG["pool"]
holvi_request["purchases"] = [{"product"=>holvi_product_id}]
holvi_request["firstname"] = "firstname"
holvi_request["lastname"] = "lastname"
holvi_request["email"] = "email"
holvi_request["cancel_url"] = SHOP_CONFIG["cancel_url"]
holvi_request["success_url"] = SHOP_CONFIG["success_url"]
holvi_request["failure_url"] = SHOP_CONFIG["failure_url"]
holvi_request["country"] = "AT"

These are the mandatory fields at the time of writing. This could change later but if this happens, Holvi will send an appropiate error message. These are the optional fields you can pass in and it will be displayed during chekcout.
The country field should be given a two letter country code according to the ISO-3166–1 alpha-2 standard: http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2

holvi_request["city"]         = "city"
holvi_request["street"] = "street"
holvi_request["postcode"] = "123456"

In the purhcases array you must put all holvi product id’s for this order.

Time to send the post request

uri          = URI.parse(**HOLVI API URL GOES HERE**)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri.request_uri)
request["Content-Type"] = "application/json"
request["Authorization"] = "Token #{SHOP_CONFIG["token"]}"
request.body = holvi_request.to_json
response = http.request(request)

this will send a post request to holvi with your token and the data from the holvi_request converted to json.

The reponse will look something like this:

{"details_uri"=>"HOLVI API URL/order/hSaFnBFnzKvxAZaCtb4YQWJeY9kVdFd7/", "checkout_uri"=>"https://holvi.com/shop/VBk12y/order/hSaFnBFnzKvxAZaCtb4YQWJeY9kVdFd7/"}

We now need to send the user to the checkout URL, from here on holvi takes over and the user will be returned to the success, cancel or failure url but we can’t use that to finalize our process since no data is returned when the user comes back.

This is where the details URL comes in, sending a request to the details URL will tell you what happened with that transaction.

We now need to send the user to the checkout URL, from here on holvi takes over and the user will be returned to the success, cancel or failure url but we can’t use that to finalize our process since no data is returned when the user comes back.

This is where the details URL comes in, sending a request to the details URL will tell you what happened with that transaction.

uri          = URI.parse(details_url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request                  = Net::HTTP::Get.new(uri.request_uri)
request["Content-Type"] = "application/json"
request["Authorization"] = "Token #{SHOP_CONFIG["token"]}"
response = http.request(request)

After sending a request to the details URL we will receive a reponse simmilar to this:

{"code"=>"hSaFnBFnzKvxAZaCtb4YQWJeY9kVdFd7", 
"pool"=>"VBk12y",
"purchases"=>[{"code"=>"t6cKhP9ldBtHCpf5O4IBQIvh4TwMuO7z",
"product"=>"j3YLqa5pn6juqUKvy7CZLghiaOJ4o7oE",
"detailed_price"=>{"net"=>"4.17", "gross"=>"5.00", "vat_rate"=>"kpu1OB1hwPzWgPgxBL49UnzCQtydLVQh", "currency"=>"EUR"},
"used"=>false,
"answers"=>[],
"product_name"=>"Some product",
"create_time"=>"2015-04-03T06:26:48.201Z",
"update_time"=>"2015-04-03T06:26:48.201Z"}],
"success_url"=>"http://lcx.wien/success/",
"failure_url"=>"http://lcx.wien/failure/",
"cancel_url"=>"http://lcx.wien/cancel/",
"firstname"=>"Foo",
"lastname"=>"Bar",
"company"=>"",
"email"=>"foo@example.com",
"city"=>"",
"country"=>"Österreich",
"street"=>"",
"postcode"=>"",
"language"=>"de",
"paid"=>true,
"create_time"=>"2015-04-03T06:26:48.180Z",
"update_time"=>"2015-04-03T06:28:42.094Z",
"paid_time"=>"2015-04-03T06:28:41.616Z",
"processed"=>false,
"processed_time"=>nil,
"discount_code"=>nil,
"country_code"=>nil,
"country_name"=>"Österreich"}

The important part is the “paid”=>true which tells us if the payment was processed which most of the times will be instant but it can occur that the payment wasn’t yet processed so you will have to retry fetching the data until the payment is processed. 
A second option would be to fetch all new orders with a different API request, but I won’t go into that now.

So let’s put this all together.

Like what you read? Give Cristian Livadaru a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.