Skip to content
Permalink
Browse files

feat(shop): add payrexx psp (CLX-2117)

  • Loading branch information...
daeppen committed May 8, 2018
1 parent 22d7bce commit ea673d21706b6937c3de84c64d41719fdcd9b45f
Showing with 6,721 additions and 2 deletions.
  1. +4 −0 installer/data/contrexx_dump_data.sql
  2. +26 −0 lib/Payrexx/CommunicationAdapter/AbstractCommunication.php
  3. +117 −0 lib/Payrexx/CommunicationAdapter/CurlCommunication.php
  4. +146 −0 lib/Payrexx/Communicator.php
  5. +72 −0 lib/Payrexx/Models/Base.php
  6. +45 −0 lib/Payrexx/Models/Request/AuthToken.php
  7. +318 −0 lib/Payrexx/Models/Request/Gateway.php
  8. +414 −0 lib/Payrexx/Models/Request/Invoice.php
  9. +312 −0 lib/Payrexx/Models/Request/Page.php
  10. +23 −0 lib/Payrexx/Models/Request/SignatureCheck.php
  11. +187 −0 lib/Payrexx/Models/Request/Subscription.php
  12. +25 −0 lib/Payrexx/Models/Request/Transaction.php
  13. +83 −0 lib/Payrexx/Models/Response/AuthToken.php
  14. +121 −0 lib/Payrexx/Models/Response/Gateway.php
  15. +92 −0 lib/Payrexx/Models/Response/Invoice.php
  16. +41 −0 lib/Payrexx/Models/Response/Page.php
  17. +17 −0 lib/Payrexx/Models/Response/SignatureCheck.php
  18. +137 −0 lib/Payrexx/Models/Response/Subscription.php
  19. +115 −0 lib/Payrexx/Models/Response/Transaction.php
  20. +69 −0 lib/Payrexx/Payrexx.php
  21. +16 −0 lib/Payrexx/PayrexxException.php
  22. +4,043 −0 lib/Payrexx/certs/ca.pem
  23. +7 −1 modules/shop/lang/de/backend.php
  24. +7 −1 modules/shop/lang/en/backend.php
  25. +5 −0 modules/shop/lib/Payment.class.php
  26. +27 −0 modules/shop/lib/PaymentProcessing.class.php
  27. +13 −0 modules/shop/lib/ShopSettings.class.php
  28. +212 −0 modules/shop/payments/payrexx/PayrexxProcessor.class.php
  29. +27 −0 modules/shop/template/module_shop_settings_payment.html
INSERT INTO `contrexx_core_setting` (`section`, `name`, `group`, `type`, `value`, `values`, `ord`) VALUES ('shop','paymill_test_public_key','config','text','','',16);
INSERT INTO `contrexx_core_setting` (`section`, `name`, `group`, `type`, `value`, `values`, `ord`) VALUES ('shop','paymill_use_test_account','config','text','0','',15);
INSERT INTO `contrexx_core_setting` (`section`, `name`, `group`, `type`, `value`, `values`, `ord`) VALUES ('shop','orderitems_amount_min','config','text','0','',0);
INSERT INTO `contrexx_core_setting` (`section`, `name`, `group`, `type`, `value`, `values`, `ord`) VALUES ('shop','payrexx_active','config','checkbox','0','',15);
INSERT INTO `contrexx_core_setting` (`section`, `name`, `group`, `type`, `value`, `values`, `ord`) VALUES ('shop','payrexx_instance_name','config','text','','',16);
INSERT INTO `contrexx_core_setting` (`section`, `name`, `group`, `type`, `value`, `values`, `ord`) VALUES ('shop','payrexx_api_secret','config','text','','',17);
INSERT INTO `contrexx_core_text` (`id`, `lang_id`, `section`, `key`, `text`) VALUES (1,1,'core','core_country_name','Afghanistan');
INSERT INTO `contrexx_core_text` (`id`, `lang_id`, `section`, `key`, `text`) VALUES (1,1,'shop','attribute_name','Zusatzleistungen');
INSERT INTO `contrexx_core_text` (`id`, `lang_id`, `section`, `key`, `text`) VALUES (1,1,'shop','core_mail_template_bcc','');
INSERT INTO `contrexx_module_shop_payment_processors` (`id`, `type`, `name`, `description`, `company_url`, `status`, `picture`) VALUES (12,'external','paymill_cc','','https://www.paymill.com',1,'');
INSERT INTO `contrexx_module_shop_payment_processors` (`id`, `type`, `name`, `description`, `company_url`, `status`, `picture`) VALUES (13,'external','paymill_elv','','https://www.paymill.com',1,'');
INSERT INTO `contrexx_module_shop_payment_processors` (`id`, `type`, `name`, `description`, `company_url`, `status`, `picture`) VALUES (14,'external','paymill_iban','','https://www.paymill.com',1,'');
INSERT INTO `contrexx_module_shop_payment_processors` (`id`, `type`, `name`, `description`, `company_url`, `status`, `picture`) VALUES (15,'external','payrexx','Payrexx is a payment gateway solution developed in Switzerland.','https://www.payrexx.com',1,'');
INSERT INTO `contrexx_module_shop_pricelists` (`id`, `name`, `lang_id`, `border_on`, `header_on`, `header_left`, `header_right`, `footer_on`, `footer_left`, `footer_right`, `categories`) VALUES (1,'Beispiel Preisliste',1,1,1,'Beispiel Preisliste',NULL,1,'<--DATE-->','<--PAGENUMBER-->','*');
INSERT INTO `contrexx_module_shop_products` (`id`, `picture`, `category_id`, `distribution`, `normalprice`, `resellerprice`, `stock`, `stock_visible`, `discountprice`, `discount_active`, `active`, `b2b`, `b2c`, `date_start`, `date_end`, `manufacturer_id`, `ord`, `vat_id`, `weight`, `flags`, `group_id`, `article_id`, `usergroup_ids`) VALUES (12,'cmVzcG9uc2l2ZS1kZXZpY2VzLmpwZw==?MTExNg==?MzAw:?MA==?MA==:?MA==?MA==','12','delivery',1950.00,0.00,50,0,500.00,0,1,1,1,'0000-00-00 00:00:00','0000-00-00 00:00:00',1,0,10,0,'',NULL,NULL,NULL);
INSERT INTO `contrexx_module_shop_products` (`id`, `picture`, `category_id`, `distribution`, `normalprice`, `resellerprice`, `stock`, `stock_visible`, `discountprice`, `discount_active`, `active`, `b2b`, `b2c`, `date_start`, `date_end`, `manufacturer_id`, `ord`, `vat_id`, `weight`, `flags`, `group_id`, `article_id`, `usergroup_ids`) VALUES (13,'Y29udHJleHhfcHJlbWl1bS5qcGc=?NDA5?NDgw:?MA==?MA==:?MA==?MA==','10','delivery',948.00,0.00,10000,0,0.00,0,1,1,1,'0000-00-00 00:00:00','0000-00-00 00:00:00',4,0,10,0,'',0,0,'');
@@ -0,0 +1,26 @@
<?php
/**
* This class is a template for all communication handler classes.
* @author Ueli Kramer <ueli.kramer@comvation.com>
* @copyright 2014 Payrexx AG
* @since v1.0
*/
namespace Payrexx\CommunicationAdapter;
/**
* Class AbstractCommunication
* @package Payrexx\CommunicationAdapter
*/
abstract class AbstractCommunication
{
/**
* Perform an API request
*
* @param string $apiUrl
* @param array $params
* @param string $method
*
* @return mixed
*/
abstract public function requestApi($apiUrl, $params = array(), $method = 'POST');
}
@@ -0,0 +1,117 @@
<?php
/**
* This is the cURL communication adapter
* @author Ueli Kramer <ueli.kramer@comvation.com>
* @copyright 2014 Payrexx AG
* @since v1.0
*/
namespace Payrexx\CommunicationAdapter;
// check for php version 5.2 or higher
if (version_compare(PHP_VERSION, '5.2.0', '<')) {
throw new \Exception('Your PHP version is not supported. Minimum version should be 5.2.0');
} else if (!function_exists('json_decode')) {
throw new \Exception('json_decode function missing. Please install the JSON extension');
}
// is the curl extension available?
if (!extension_loaded('curl')) {
throw new \Exception('Please install the PHP cURL extension');
}
/**
* Class CurlCommunication for the communication with cURL
* @package Payrexx\CommunicationAdapter
*/
class CurlCommunication extends \Payrexx\CommunicationAdapter\AbstractCommunication
{
/**
* {@inheritdoc}
*/
public function requestApi($apiUrl, $params = array(), $method = 'POST')
{
$curlOpts = array(
CURLOPT_URL => $apiUrl,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_USERAGENT => 'payrexx-php/1.0.0',
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_CAINFO => dirname(__DIR__) . '/certs/ca.pem',
);
if (defined(PHP_QUERY_RFC3986)) {
$paramString = http_build_query($params, null, '&', PHP_QUERY_RFC3986);
} else {
// legacy, because the $enc_type has been implemented with PHP 5.4
$paramString = str_replace(
array('+', '%7E'),
array('%20', '~'),
http_build_query($params, null, '&')
);
}
if ($method == 'GET') {
if (!empty($params)) {
$curlOpts[CURLOPT_URL] .= strpos($curlOpts[CURLOPT_URL], '?') === false ? '?' : '&';
$curlOpts[CURLOPT_URL] .= $paramString;
}
} else {
$curlOpts[CURLOPT_POSTFIELDS] = $paramString;
$curlOpts[CURLOPT_URL] .= strpos($curlOpts[CURLOPT_URL], '?') === false ? '?' : '&';
$curlOpts[CURLOPT_URL] .= 'instance=' . $params['instance'];
}
$curl = curl_init();
curl_setopt_array($curl, $curlOpts);
$responseBody = $this->curlExec($curl);
$responseInfo = $this->curlInfo($curl);
if ($responseBody === false) {
$responseBody = array('status' => 'error', 'message' => $this->curlError($curl));
}
curl_close($curl);
if ($responseInfo['content_type'] === 'application/json') {
$responseBody = json_decode($responseBody, true);
}
return array(
'info' => $responseInfo,
'body' => $responseBody
);
}
/**
* The wrapper method for curl_exec
*
* @param resource $curl the cURL resource
*
* @return mixed
*/
protected function curlExec($curl)
{
return curl_exec($curl);
}
/**
* The wrapper method for curl_getinfo
*
* @param resource $curl the cURL resource
*
* @return mixed
*/
protected function curlInfo($curl)
{
return curl_getinfo($curl);
}
/**
* The wrapper method for curl_errno
*
* @param resource $curl the cURL resource
*
* @return mixed
*/
protected function curlError($curl)
{
return curl_errno($curl);
}
}
@@ -0,0 +1,146 @@
<?php
/**
* This class has the definition of the API used for the communication.
* @author Ueli Kramer <ueli.kramer@comvation.com>
* @copyright 2014 Payrexx AG
* @since v1.0
*/
namespace Payrexx;
/**
* This object handles the communication with the API server
* @package Payrexx
*/
class Communicator
{
const VERSION = 'v1';
const API_URL = 'https://api.payrexx.com/%s/%s/%d/';
/**
* @var array A set of methods which can be used to communicate with the API server.
*/
protected static $methods = array(
'create' => 'POST',
'charge' => 'POST',
'cancel' => 'DELETE',
'delete' => 'DELETE',
'update' => 'PUT',
'getAll' => 'GET',
'getOne' => 'GET',
);
/**
* @var string The Payrexx instance name.
*/
protected $instance;
/**
* @var string The API secret which is used to generate a signature.
*/
protected $apiSecret;
/**
* @var string The communication handler which handles the HTTP requests. Default cURL Communication handler
*/
protected $communicationHandler;
/**
* Generates a communicator object with a communication handler like cURL.
*
* @param string $instance The instance name, needed for the generation of the API url.
* @param string $apiSecret The API secret which is the key to hash all the parameters passed to the API
* server.
* @param string $communicationHandler The preferred communication handler. Default is cURL.
*
* @throws \Payrexx\PayrexxException
*/
public function __construct($instance, $apiSecret, $communicationHandler = '\Payrexx\CommunicationAdapter\CurlCommunication')
{
$this->instance = $instance;
$this->apiSecret = $apiSecret;
if (!class_exists($communicationHandler)) {
throw new \Payrexx\PayrexxException('Communication handler class ' . $communicationHandler . ' not found');
}
$this->communicationHandler = new $communicationHandler();
}
/**
* Gets the version of the API used.
*
* @return string The version of the API
*/
public function getVersion()
{
return self::VERSION;
}
/**
* Perform a simple API request by method name and Request model.
*
* @param string $method The name of the API method to call
* @param \Payrexx\Models\Base $model The model which has the same functionality like a filter.
*
* @return \Payrexx\Models\Base[]|\Payrexx\Models\Base An array of models or just one model which
* is the result of the API call
* @throws \Payrexx\PayrexxException An error occurred during the Payrexx Request
*/
public function performApiRequest($method, \Payrexx\Models\Base $model)
{
$params = $model->toArray($method);
$params['ApiSignature'] =
base64_encode(hash_hmac('sha256', http_build_query($params, null, '&'), $this->apiSecret, true));
$params['instance'] = $this->instance;
$id = isset($params['id']) ? $params['id'] : 0;
$response = $this->communicationHandler->requestApi(
sprintf(self::API_URL, self::VERSION, $params['model'], $id),
$params,
$this->getHttpMethod($method)
);
$convertedResponse = array();
if (!isset($response['body']['data']) || !is_array($response['body']['data'])) {
if (!isset($response['body']['message'])) {
throw new \Payrexx\PayrexxException('Payrexx PHP: Configuration is wrong! Check instance name and API secret', $response['info']['http_code']);
}
throw new \Payrexx\PayrexxException($response['body']['message'], $response['info']['http_code']);
}
foreach ($response['body']['data'] as $object) {
$responseModel = $model->getResponseModel();
$convertedResponse[] = $responseModel->fromArray($object);
}
if (
strpos($method, 'One') !== false ||
strpos($method, 'create') !== false
) {
$convertedResponse = current($convertedResponse);
}
return $convertedResponse;
}
/**
* Gets the HTTP method to use for a specific API method
*
* @param string $method The API method to check for
*
* @return string The HTTP method to use for the queried API method
* @throws \Payrexx\PayrexxException The method is not implemented yet.
*/
protected function getHttpMethod($method)
{
if (!$this->methodAvailable($method)) {
throw new \Payrexx\PayrexxException('Method ' . $method . ' not implemented');
}
return self::$methods[$method];
}
/**
* Checks whether a method is available and activated in methods array.
*
* @param string $method The method name to check
*
* @return bool True if the method exists, False if not
*/
public function methodAvailable($method)
{
return array_key_exists($method, self::$methods);
}
}
@@ -0,0 +1,72 @@
<?php
/**
* The Base model class for request and response models.
* @author Ueli Kramer <ueli.kramer@comvation.com>
* @copyright 2014 Payrexx AG
* @since v1.0
*/
namespace Payrexx\Models;
/**
* Class Base
* @package Payrexx\Models
*/
abstract class Base
{
protected $id;
/**
* Converts array to response model
*
* @param array $data
*
* @return $this
*/
public function fromArray($data)
{
foreach ($data as $param => $value) {
if (!method_exists($this, 'set' . ucfirst($param))) {
continue;
}
$this->{'set' . ucfirst($param)}($value);
}
return $this;
}
/**
* Convert object to an associative array
*
* @param string $method The API method called
*
* @return array
*/
public function toArray($method)
{
$vars = get_object_vars($this);
$className = explode('\\', get_called_class());
return $vars + array('model' => end($className));
}
/**
* Returns the corresponding response model object
*
* @return \Payrexx\Models\Response\Base
*/
public abstract function getResponseModel();
/**
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* @param integer $id
*/
public function setId($id)
{
$this->id = $id;
}
}

0 comments on commit ea673d2

Please sign in to comment.
You can’t perform that action at this time.