From 3e90905a30edb9a6570cd5107e7c196e82bbb3df Mon Sep 17 00:00:00 2001 From: Adam Moore Date: Mon, 12 Feb 2018 14:40:42 +0000 Subject: [PATCH] Initial Commit --- .gitignore | 3 + ComodoCACert.cer | 34 ++++++++ composer.json | 27 ++++++ phpunit.xml | 16 ++++ src/ApiClient.php | 58 +++++++++++++ src/AuthToken.php | 21 +++++ src/Exception/ApiAuthenticationException.php | 10 +++ src/Exception/ApiAuthorisationException.php | 10 +++ src/Exception/ApiException.php | 11 +++ src/Exception/ApiValidationException.php | 9 ++ src/Exception/Exception.php | 7 ++ src/InsuranceHub.php | 86 ++++++++++++++++++++ src/Resource/Product.php | 17 ++++ src/Resource/Request.php | 20 +++++ src/Resource/Result.php | 24 ++++++ src/Resource/Sale.php | 15 ++++ tests/OfferingTest.php | 71 ++++++++++++++++ tests/boot.example.php | 7 ++ 18 files changed, 446 insertions(+) create mode 100644 .gitignore create mode 100644 ComodoCACert.cer create mode 100644 composer.json create mode 100644 phpunit.xml create mode 100644 src/ApiClient.php create mode 100644 src/AuthToken.php create mode 100644 src/Exception/ApiAuthenticationException.php create mode 100644 src/Exception/ApiAuthorisationException.php create mode 100644 src/Exception/ApiException.php create mode 100644 src/Exception/ApiValidationException.php create mode 100644 src/Exception/Exception.php create mode 100644 src/InsuranceHub.php create mode 100644 src/Resource/Product.php create mode 100644 src/Resource/Request.php create mode 100644 src/Resource/Result.php create mode 100644 src/Resource/Sale.php create mode 100644 tests/OfferingTest.php create mode 100644 tests/boot.example.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed21c81 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +tests/boot.php +vendor/* +composer\.lock diff --git a/ComodoCACert.cer b/ComodoCACert.cer new file mode 100644 index 0000000..1efdf19 --- /dev/null +++ b/ComodoCACert.cer @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB +hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV +BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5 +MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT +EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR +6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X +pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC +9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV +/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf +Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z ++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w +qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah +SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC +u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf +Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq +crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E +FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB +/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl +wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM +4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV +2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna +FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ +CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK +boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke +jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL +S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb +QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl +0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB +NVOFBkpdn627G190 +-----END CERTIFICATE----- \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..f675fa2 --- /dev/null +++ b/composer.json @@ -0,0 +1,27 @@ +{ + "name": "adamcmoore/insurance-hub", + "description": "API wrapper for Insurance Hub, based on https://github.com/Insure-Tech/InsuranceHub.Client.Php", + "homepage": "https://smccoachhire.com", + "authors": [ + { + "name": "Adam Moore", + "email": "adam@acmoore.co.uk" + } + ], + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^5" + }, + "autoload": { + "psr-4": { + "InsuranceHub\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests/" + } + } +} \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..c92e487 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,16 @@ + + + + + ./tests + + + diff --git a/src/ApiClient.php b/src/ApiClient.php new file mode 100644 index 0000000..81fca04 --- /dev/null +++ b/src/ApiClient.php @@ -0,0 +1,58 @@ +url = $serviceURL; + $this->certificatePath = $caCertificatePath; + } + + public function execute($request) + { + $authToken = new AuthToken($request->vendorId, $request->apiKey); + + $ch = curl_init($this->url); + + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($request)); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); + curl_setopt($ch, CURLOPT_CAINFO, $this->certificatePath); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-InsuranceHub-VendorId: '.$request->vendorId, + 'X-InsuranceHub-AuthToken: '.$authToken->getToken()]); + + $response = curl_exec($ch); + + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + + switch ($httpCode) { + case 401: + throw new ApiAuthenticationException(); + case 403: + throw new ApiAuthorisationException(); + case 400: + $validationError = json_decode($response); + + $validationMessages = implode(",", $validationError->validationMessages); + + throw new ApiValidationException($validationMessages); + case 500: + $apiError = json_decode($response); + throw new ApiException($apiError->message); + } + + curl_close($ch); + + return array($httpCode, json_decode($response)); + } +} diff --git a/src/AuthToken.php b/src/AuthToken.php new file mode 100644 index 0000000..29424c2 --- /dev/null +++ b/src/AuthToken.php @@ -0,0 +1,21 @@ +formattedVendorId = str_replace('-', '', strtolower($vendorId)); + $this->formattedApiKey = str_replace('-', '', strtolower($apiKey)); + } + + public function getToken() + { + $date = gmdate('dmY'); + + return base64_encode(hash_hmac('sha1', $this->formattedVendorId.$date, $this->formattedApiKey, true)); + } +} \ No newline at end of file diff --git a/src/Exception/ApiAuthenticationException.php b/src/Exception/ApiAuthenticationException.php new file mode 100644 index 0000000..47beb3b --- /dev/null +++ b/src/Exception/ApiAuthenticationException.php @@ -0,0 +1,10 @@ +getMessage(); + return $error; + } +} \ No newline at end of file diff --git a/src/Exception/ApiValidationException.php b/src/Exception/ApiValidationException.php new file mode 100644 index 0000000..fb152be --- /dev/null +++ b/src/Exception/ApiValidationException.php @@ -0,0 +1,9 @@ +getMessage(); + } +} \ No newline at end of file diff --git a/src/Exception/Exception.php b/src/Exception/Exception.php new file mode 100644 index 0000000..d281a95 --- /dev/null +++ b/src/Exception/Exception.php @@ -0,0 +1,7 @@ +vendorId = $vendorId; + $this->apiKey = $apiKey; + $this->offeringRequestURL = $offeringRequestURL; + $this->offeringResultURL = $offeringResultURL; + $this->certPath = getcwd()."/ComodoCACert.cer";; + } + + + public function getOffering($products, $reference = null) + { + $client = new ApiClient($this->offeringRequestURL, $this->certPath); + $request = new Request(); + $request->vendorId = $this->vendorId; + $request->apiKey = $this->apiKey; + $request->products = $products; + + if ($reference) { + $request->vendorRequestReference = $reference; + } + + $offering = $client->execute($request)[1]; + + return $offering; + } + + + public function sendSaleResult($offering, $reference, $customerFirstName, $customerLastName) + { + return $this->sendResult($offering, $reference, $customerFirstName, $customerLastName, true); + } + + + public function sendNoSaleResult($offering, $reference, $customerFirstName, $customerLastName) + { + return $this->sendResult($offering, $reference, $customerFirstName, $customerLastName, false); + } + + + private function sendResult($offering, $reference, $customerFirstName, $customerLastName, $isSale) + { + $client = new ApiClient($this->offeringResultURL, $this->certPath); + $result = new Result(); + $result->vendorId = $this->vendorId; + $result->apiKey = $this->apiKey; + $result->offeringId = $offering->id; + $result->vendorSaleReference = $reference; + $result->customerForename = $customerFirstName; + $result->customerSurname = $customerLastName; + + foreach ($offering->productOfferings as $i => $product) { + $sale = new Sale(); + $sale->productOfferingId = $product->id; + $sale->sold = $isSale; + + $result->sales[$i] = $sale; + } + + $responseCode = $client->execute($result)[0]; + + // check success reponse code recieved (2xx) + if ($responseCode >= 200 && $responseCode < 300) { + return true; + } else { + throw new ApiException('Sending offering Result returned HTTP status code '.$responseCode); + } + } +} diff --git a/src/Resource/Product.php b/src/Resource/Product.php new file mode 100644 index 0000000..2be0625 --- /dev/null +++ b/src/Resource/Product.php @@ -0,0 +1,17 @@ + $this->categoryCode, + 'price' => $this->price, + 'completionDate' => $this->completionDate->format(\DateTime::ISO8601), + ]; + } +} \ No newline at end of file diff --git a/src/Resource/Request.php b/src/Resource/Request.php new file mode 100644 index 0000000..dce226b --- /dev/null +++ b/src/Resource/Request.php @@ -0,0 +1,20 @@ + $this->vendorId, + 'vendorRequestReference' => $this->vendorRequestReference, + 'products' => $this->products, + 'premiumAsSummary' => $this->premiumAsSummary, + ]; + } +} \ No newline at end of file diff --git a/src/Resource/Result.php b/src/Resource/Result.php new file mode 100644 index 0000000..faef181 --- /dev/null +++ b/src/Resource/Result.php @@ -0,0 +1,24 @@ + $this->vendorId, + 'offeringId' => $this->offeringId, + 'vendorSaleReference' => $this->vendorSaleReference, + 'customerForename' => $this->customerForename, + 'customerSurname' => $this->customerSurname, + 'sales' => $this->sales, + ]; + } +} \ No newline at end of file diff --git a/src/Resource/Sale.php b/src/Resource/Sale.php new file mode 100644 index 0000000..439d2d6 --- /dev/null +++ b/src/Resource/Sale.php @@ -0,0 +1,15 @@ + $this->productOfferingId, + 'sold' => $this->sold, + ]; + } +} \ No newline at end of file diff --git a/tests/OfferingTest.php b/tests/OfferingTest.php new file mode 100644 index 0000000..d70825a --- /dev/null +++ b/tests/OfferingTest.php @@ -0,0 +1,71 @@ +client = new InsuranceHub($config['vendor_id'], $config['api_key'], $config['offering_request_url'], $config['submit_offering_url']); + } + + + private function _createOffering() + { + $product1 = new Product(); + $product1->categoryCode = 'TKT'; + $product1->price = 100.00; + $product1->completionDate = new \DateTime(); + + $product2 = new Product(); + $product2->categoryCode = 'TKT'; + $product2->price = 200.00; + $product2->completionDate = new \DateTime(); + + $products = [$product1, $product2]; + + return $this->client->getOffering($products, 'ref123'); + } + + + public function testGetOffering() + { + $offering = $this->_createOffering(); + + $this->assertObjectHasAttribute('productOfferings', $offering); + $this->assertEquals(count($offering->productOfferings), 2); + + foreach ($offering->productOfferings as $product_offer) { + $this->assertObjectHasAttribute('categoryCode', $product_offer); + $this->assertObjectHasAttribute('currencyCode', $product_offer); + $this->assertObjectHasAttribute('premium', $product_offer); + } + } + + + public function testSendSaleResult() + { + $offering = $this->_createOffering(); + + $result = $this->client->sendSaleResult($offering, 'ref123', 'John', 'Smith'); + + $this->AssertTrue($result); + } + + + public function testSendNoSaleResult() + { + $offering = $this->_createOffering(); + + $result = $this->client->sendNoSaleResult($offering, 'ref123', 'John', 'Smith'); + + $this->AssertTrue($result); + } +} \ No newline at end of file diff --git a/tests/boot.example.php b/tests/boot.example.php new file mode 100644 index 0000000..bb965eb --- /dev/null +++ b/tests/boot.example.php @@ -0,0 +1,7 @@ + 'your-vendor-id', + 'api_key' => 'your-api-key', + 'offering_request_url' => 'https://quote.uat.insure-hub.net/quote', + 'submit_offering_url' => 'https://sales.uat.insure-hub.net/sales', +]; \ No newline at end of file