WebAPI integration
Hi Stephen,
I am building something similar in Ruby at the moment and I was/am having the exact same problems and questions. So thank you for pointing most of the stuff out in the first place!
I use the gem RestClient (similar to Guzzle) and rewrote the token algorithm. I tried to establish a successful connection to the merchant/authenticate endpoint.
The token is the same as in the Java-Implementation. I tried to do it like you did, but I only get 401 Unauthorized.
This is my test implementation:
Did you do something special to get the http authorization to work? Am I missing something?
I would much appreciate your help in this matter.
Cheers,
Fabian
I am building something similar in Ruby at the moment and I was/am having the exact same problems and questions. So thank you for pointing most of the stuff out in the first place!
I use the gem RestClient (similar to Guzzle) and rewrote the token algorithm. I tried to establish a successful connection to the merchant/authenticate endpoint.
The token is the same as in the Java-Implementation. I tried to do it like you did, but I only get 401 Unauthorized.
This is my test implementation:
Code: Select all
require 'date'
require 'digest'
require 'rest-client'
require 'awesome_print'
username = 'yyy'
usergroup = 'xxx'
password = 'ccc'
def generate_token url, timestamp, password
password_digest = Digest::MD5.digest(password)
Digest::SHA256.base64digest("#{url}#{timestamp}#{password_digest}")
end
url = 'https://gateway.iveri.co.za/api/merchant/authenticate'
timestamp = DateTime.now.strftime("%Y%m%d%H%M%S%3N")
token = generate_token url, timestamp, password
auth = 'Basic usergroup="'+usergroup+'", username="'+username+'", timestamp="'+timestamp+'", token="'+token+'"'
@resource = RestClient::Resource.new( url )
@response = @resource.get( :Authorization => auth )
ap @response.body
I would much appreciate your help in this matter.
Cheers,
Fabian
Stephen wrote:For any PHP developers who run into issues with authorisation in future - let me save you some time. I've managed to get this working correctly using guzzle and setting the authorization header manually instead of using the standard expected username and password params.
First, we need to declare some credentials somewhere - Following OOP standards:
Note: The gateway is not what was mentioned earlier. The above works as expected.Code: Select all
private $backoffice_username = 'dummy_username'; private $backoffice_usergroup = 'dummy_usergroup'; private $backoffice_password = 'dummy_password'; private $backoffice_gateway = 'https://gateway.iveri.co.za/api/';
Then we need a function to generate the timestamp in the format '"yyyyMMddHHmmssfff' which is would look something like 20160330143402422 - Year, month, day, hour, minute, seconds and milliseconds.
Now, if we didn't require milliseconds, this would be as easy as:Unfortunately, PHP doesn't have an easy way to append the milliseconds to this date so we need to add a bit of additional code:Code: Select all
return date('YmdHis');
Next up, the token generation as mentioned earlier - exception this time I've wrapped the entire thing in a function called 'generateHeader'.Code: Select all
private function getTimestamp() { $microtime = microtime(true); $microseconds = sprintf("%06d",($t - floor($t)) * 1000000); $date = new DateTime( date('YmdHis'.$microseconds, $microtime) ); return $date->format("YmdHisu"); }
Finally, using GuzzleHttp we can submit the request:Code: Select all
private function generateHeader($url) { $date = $this->getTimestamp(); $password = md5($this->backoffice_password, true); $token_bytes = $this->gateway . $url . $date . $password; $token_hash = hash("sha256", $token_bytes, true); $token_base64 = base64_encode($token_hash); $auth_header = 'Basic ' . 'usergroup="' . $this->backoffice_usergroup . '", ' . 'username="' . $this->backoffice_username . '", ' . 'timestamp="' . $date . '", ' . 'token="' . $token_base64 . '"'; return $auth_header; }
And we'll receive the timestamp of the server. Success.Code: Select all
public function sendAuthorizationRequest() { $auth_header = $this->generateHeader('merchant/authenticate'); $httpRequest = new Request('GET', 'merchant/authenticate', [ 'Authorization' => $auth_header ]); $httpResponse = $this->client->send($httpRequest); if ($httpResponse->getStatusCode() != 200) { throw new Exception( "Received unexpected HTTP code from Iveri gateway. Received HTTP '{$httpResponse->getStatusCode()}'"); } return $httpResponse->getBody(); }
Of course I've skipped a few pre-configuration steps to take into consideration such as the certificate verification and what not, but that's all described within the documentation and depends on what HTTP client you're using. With Guzzle, you really just need to specify the verification location so that the HTTP client can match against the servers certificate.
Hi Stephen,
thanks for sharing your experiences! In my script was a bug. I used the incorrect time zone in my token generation method.
I changed it from
timestamp = DateTime.now.strftime("%Y%m%d%H%M%S%3N")
to
timestamp = DateTime.now.getutc.strftime("%Y%m%d%H%M%S%3N")
and it worked like a charm. I was so happy when I finally received the timestamp from the iVeri server.
Your code helped me a lot to build the token string for authentication. Thanks a lot for that.
Samora told us similar things by the way.
I have however concerns to use gateway.iveri.co.za for payment transactions because its SSL certificate is insecure. (https://www.ssllabs.com/ssltest/analyze ... veri.co.za)
Verifying agains the certificate "Builtin Object Token-Entrust Root Certification Authority - G2" from nedsecure worked in the end for portal.nedsecure.co.za. (Funny is that I coulnd not get Verification to work with gateway.iveri.co.za.)
My current status is:
https://portal.nedsecure.co.za/api/merc ... thenticate and the other "GET" Endpoints work. The "POST" endpoint 'api/transactions' however always returns error code 500 with no details for what I am doing wrong.
I find the WebAPI Developers Guide quite misleading because of the wrong links and the lack of endpoint descriptions.
Also I got XML responses where I expected JSON (e.g. GET /api/merchant/bins EP). Did I do sth. wrong?
Sorry for my incoherent sentences,
Fabian
thanks for sharing your experiences! In my script was a bug. I used the incorrect time zone in my token generation method.
I changed it from
timestamp = DateTime.now.strftime("%Y%m%d%H%M%S%3N")
to
timestamp = DateTime.now.getutc.strftime("%Y%m%d%H%M%S%3N")
and it worked like a charm. I was so happy when I finally received the timestamp from the iVeri server.
Your code helped me a lot to build the token string for authentication. Thanks a lot for that.
Samora told us similar things by the way.
I have however concerns to use gateway.iveri.co.za for payment transactions because its SSL certificate is insecure. (https://www.ssllabs.com/ssltest/analyze ... veri.co.za)
Verifying agains the certificate "Builtin Object Token-Entrust Root Certification Authority - G2" from nedsecure worked in the end for portal.nedsecure.co.za. (Funny is that I coulnd not get Verification to work with gateway.iveri.co.za.)
My current status is:
https://portal.nedsecure.co.za/api/merc ... thenticate and the other "GET" Endpoints work. The "POST" endpoint 'api/transactions' however always returns error code 500 with no details for what I am doing wrong.
I find the WebAPI Developers Guide quite misleading because of the wrong links and the lack of endpoint descriptions.
Also I got XML responses where I expected JSON (e.g. GET /api/merchant/bins EP). Did I do sth. wrong?
Sorry for my incoherent sentences,
Fabian