I want to set an API Payment inside my webpage but before using endpoints, we have to generate Headers. The API is coded in Laravel.
Api docs: documentation smobilpay
Github to access Api full code: Code smobilpay
My problem : Create a form and when clicking on the submit button, the header autorization will be display on screen
Example for post Request :
Client wants to request a quote for a payment collection worth 1000.00 for payment item id SPAY-DEV-958-AES-100013333-10010.
What we have: API User Credentials ($token = Public access token and $secret = access secret)
URL of Endpoint to call https://dev.smobilpay.com/s3p/v2/quotestd
Http method Api endpoint = POST
Request Body : {“payItemId”:”SPAY-DEV-958-AES-100013333-10010″,”amount”:”1000″}
s3pAuth_nonce : “634968823463411609”
s3pAuth_signature_method : “HMAC-SHA1”
s3pAuth_timestamp : “1361281946”
s3pAuth_token: “xvz1evFS4wEEPTGEFPHBog”
What we have to do:
Step 1 : Generate parameter string by joining all components in alphabetical order (Note that for POST requests the parameters are taken from the BODY while for GET requests the parameters are taken from the query URL)
answer to step1 : amount=1000&payItemId=SPAY-DEV-958-AES-100013333-10010&s3pAuth_nonce=634968823463411609&s3pAuth_signature_method=HMAC-SHA1&s3pAuth_timestamp=1361281946&s3pAuth_token=xvz1evFS4wEEPTGEFPHBog
Step 2 : Assemble Base String by joining in the HTTP Verb + FQDN and percentage encoding the entire string
answer to step 2 : POST&https%3A%2F%2Fdev.smobilpay.com%2Fs3p%2Fv2%2Fquotestd&amount%3D1000%26payItemId%3DSPAY-DEV-958-AES-100013333-10010%26s3pAuth_nonce%3D634968823463411609%26s3pAuth_signature_method%3DHMAC-SHA1%26s3pAuth_timestamp%3D1361281946%26s3pAuth_token%3Dxvz1evFS4wEEPTGEFPHBog
Step 3 : Calculate Signature (hmac + access secret)
answer to step 3: 1CLm+TQLwelkE+5Za+Vi+7G5M8U=
Resulting Authorization Header
s3pAuth,s3pAuth_nonce=”634968823463411609″, s3pAuth_signature=”1CLm+TQLwelkE+5Za+Vi+7G5M8U=”, s3pAuth_signature_method=”HMAC-SHA1″, s3pAuth_timestamp=”1361281946″,s3pAuth_token=”xvz1evFS4wEEPTGEFPHBog”
Here is the code for ApiClient
<?php
declare(strict_types=1);
namespace MavianceS3PApiClient;
/**
* ApiClient Class Doc Comment
*
* @category Class
*
* @author Swagger Codegen team
*
* @link https://github.com/swagger-api/swagger-codegen
*/
use GuzzleHttpClient;
use GuzzleHttpUtils;
use PsrHttpMessageRequestInterface;
use PsrHttpMessageResponseInterface;
use PsrHttpMessageUriInterface;
use RamseyUuidUuid;
class ApiClient extends Client
{
public function __construct(private readonly string $token, private readonly string $secret, array $config = [])
{
parent::__construct($config);
}
public function send(RequestInterface $request, array $options = []): ResponseInterface
{
$options['headers'] = ['Authorization' => $this->buildAuthorizationHeader($request)];
return parent::send($request, $options);
}
/** Build S3P Authorization Header */
public function buildAuthorizationHeader(RequestInterface $request): string
{
$data = [];
if ($request->getMethod() == 'POST') {
$data = Utils::jsonDecode($request->getBody()->getContents(), true);
}
$auth_titleKey = 's3pAuth';
$auth_tokenKey = 's3pAuth_token';
$auth_nonceKey = 's3pAuth_nonce';
$auth_signatureKey = 's3pAuth_signature';
$auth_signatureMethodKey = 's3pAuth_signature_method';
$auth_timestampKey = 's3pAuth_timestamp';
$separator = ', ';
$signature_method = 'HMAC-SHA1';
$timestamp = time();
$nonce = Uuid::uuid4()->toString();
$params =
[
's3pAuth_nonce' => $nonce,
's3pAuth_timestamp' => $timestamp,
's3pAuth_signature_method' => $signature_method,
's3pAuth_token' => $this->token,
];
// disect GET request query parameters
if (!empty($request->getUri()->getQuery())) {
$queryparameter = explode('&', urldecode($request->getUri()->getQuery()));
foreach ($queryparameter as $v) {
$item = explode('=', $v);
$params[$item[0]] = $item[1];
}
}
$sig = new HMACSignature(
$request->getMethod(),
$this->getUrl($request->getUri()),
array_merge($data, $params)
);
$signature = $sig->generate($this->secret);
echo $signature;
return $auth_titleKey . ' ' .
$auth_timestampKey . '="' . $timestamp . '"' . $separator .
$auth_signatureKey . '="' . $signature . '"' . $separator .
$auth_nonceKey . '="' . $nonce . '"' . $separator .
$auth_signatureMethodKey . '="' . $signature_method . '"' . $separator .
$auth_tokenKey . '="' . $this->token . '"';
}
/** Build url to use in signature validation */
private function getUrl(UriInterface $uri): string
{
// in case ports are not standard -> add to url
return implode(
'',
[
$uri->getScheme(),
'://',
$uri->getHost(),
is_null($uri->getPort()) ? '' : ((!in_array($uri->getPort(), [80, 443])) ? ':' . $uri->getPort() : ''),
$uri->getPath(),
]
);
}
}
Here is the code for the HMACSignature
<?php
declare(strict_types=1);
namespace MavianceS3PApiClient;
use Exception;
class HMACSignature
{
/**
* @param string $method HTTP method
* @param string $url URL
* @param array $params parameters to include in signature
*/
public function __construct(
private readonly string $method,
private readonly string $url,
private array $params
) {
}
/** This method generates the signature based on given parameters */
public function generate(string $secret): string
{
$encodedString = hash_hmac('sha1', $this->getBaseString(), $secret, true);
return base64_encode($encodedString);
}
/** @throws Exception */
public function verify(string $signature, string $secret): bool
{
if ($signature !== $this->generate($secret)) {
throw new Exception('Signature Does Not Match');
}
return true;
}
/** compile base string */
public function getBaseString(): string
{
$glue = '&';
$sorted = $this->getParameterString();
return
// capitalize http type
strtoupper(trim($this->method)) . $glue .
// urlencoded url
rawurlencode(trim($this->url)) . $glue .
// lexically sorted parameter string
$sorted;
}
/** Prepares a string to be signed */
protected function getParameterString(): string
{
$glue = '&';
$stringToBeSigned = '';
// lexically sort parameters
ksort($this->params);
foreach ($this->params as $key => $value) {
$stringToBeSigned .= trim((string)$key) . '=' . trim((string)$value) . $glue;
}
// urlencoded and remove trailing glue
return rawurlencode(trim(substr($stringToBeSigned, 0, -1)));
}
}