First Commit

This commit is contained in:
mark committed 2026-10-19 15:22:52 -07:00
1 parent 5eb9dd037d
commit 2e62c0e60b
11877 files changed
+2035312

No files matched your search

+8
View File
@@ -0,0 +1,8 @@
root = true
[*.php]
charset = utf-8
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
+19
View File
@@ -0,0 +1,19 @@
Copyright (c) 2014 Pavel Kulbakin <p.kulbakin@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+128
View File
@@ -0,0 +1,128 @@
Beanstream PHP API
==================
Composer ready PHP wrapper for [Beanstream API](http://developer.beanstream.com/documentation/).
## Help Contribute
Send us pull requests and help improve the code, and we will send you a t-shirt.
## Installation
The recommended way to install the library is using [Composer](https://getcomposer.org).
1) Add this json to your composer.json file:
```json
{
"require": {
"beanstream/beanstream": "dev-master"
}
}
```
2) Next, run this from the command line:
```
composer install
```
3) Finally, add this line to your php file that will be using the SDK:
```
require 'vendor/autoload.php';
```
## Handling Exceptions
If the server returns an unexpected response or error, PHP API throws *\Beanstream\Exception*.
Positive error codes correspond to Beanstream API errors, see
[Take Payment Errors](http://developer.beanstream.com/documentation/take-payments/errors/),
[Analyze Payment Errors](http://developer.beanstream.com/documentation/analyze-payments/errors/),
[Tokenize Payments Errors](http://developer.beanstream.com/documentation/tokenize-payments/errors/).
Negative codes correspond to [cURL errors](http://curl.haxx.se/libcurl/c/libcurl-errors.html)
(original cURL error codes are positive, in *\Beanstream\Exception* those are just reversed).
Exception with zero error code are PHP API specific, e.g. *The curl extension is required* or
*Unexpected response format*.
Generally, any unsuccessful request, e.g. insufficient data or declined transaction, results in *\Beanstream\Exception*,
thus *try..catch* is recommended for intercepting and handling them, see example below.
## Your First Integration
The sample below is an equivalent of original [example](http://developer.beanstream.com/documentation/your-first-integration/)
from Beanstream.
```php
<?php
require 'vendor/autoload.php';
$merchant_id = ''; //INSERT MERCHANT ID (must be a 9 digit string)
$api_key = ''; //INSERT API ACCESS PASSCODE
$api_version = 'v1'; //default
$platform = 'api'; //default
//Create Beanstream Gateway
$beanstream = new \Beanstream\Gateway($merchant_id, $api_key, $platform, $api_version);
//Example Card Payment Data
$payment_data = array(
'order_number' => 'a1b2c3',
'amount' => 1.00,
'payment_method' => 'card',
'card' => array(
'name' => 'Mr. Card Testerson',
'number' => '4030000010001234',
'expiry_month' => '07',
'expiry_year' => '22',
'cvd' => '123'
)
);
$complete = TRUE; //set to FALSE for PA
//Try to submit a Card Payment
try {
$result = $beanstream->payments()->makeCardPayment($payment_data, $complete);
/*
* Handle successful transaction, payment method returns
* transaction details as result, so $result contains that data
* in the form of associative array.
*/
} catch (\Beanstream\Exception $e) {
/*
* Handle transaction error, $e->code can be checked for a
* specific error, e.g. 211 corresponds to transaction being
* DECLINED, 314 - to missing or invalid payment information
* etc.
*/
}
```
See examples.php for more examples.
## Tips
### Authentication
Beanstream defines separate API access passcodes for payment, profile and reporting API requests. It is possible
to use the same value for all of them, and create a single instance of \Beanstream\Gateway. You can also
initialize separate \Beanstream\Gateway instances for each type of request. API access passcodes are
configured via the Beanstream dashboard (See *administration -> account settings -> order settings*
for payment and search passcodes, *configuration -> payment profile configuration* for profile passcode).
### Billing Address Province
Beanstream requires the *province* field submitted along with *billing* data to be a two-letter code. It only requires it when
the specified *country* is *US* or *CA*, for other country codes set it to *--* (two dashes) even if the corresponding country
does have states or provinces.
### Backwards Compatibility
The default `$platform` value assigned is `'api'`, which sends your requests to the endpoint `'api.na.bambora.com'`. The ensure backwards compatibility, you may assign `$platform = 'www'` which will send your requests to the legacy endpoint `'www.beanstream.com/api'`.
### Ensuring TLS 1.2-Only Compatibility
If you would like to test compatibility with the LIVE TLS 1.2-only environment, assign `$platform = 'tls12-api'`, instead of `'api'`; This will point your requests to the endpoint `'tls12-api.na.bambora.com'`. Please be advised that this endpoint is provided for a limited time, and is intended for integration compatibility testing only, and is not intended for any type of load tests. More details can be found on the [Bambora North America Knowledge Base](https://help.na.bambora.com/hc/en-us/articles/115015460087-TLS-Upgrade-TLS-1-2).
+22
View File
@@ -0,0 +1,22 @@
{
"name": "beanstream/beanstream",
"description": "Beanstream PHP API",
"type": "library",
"license": "MIT",
"version": "1.0.1",
"authors": [
{
"name": "Pavel Kulbakin",
"email": "p.kulbakin@gmail.com"
},
{
"name": "Kevin Saliba"
}
],
"require": {
"php": ">=5.3.0"
},
"autoload": {
"psr-0": {"Beanstream": "src/"}
}
}
+20
View File
@@ -0,0 +1,20 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "f9da054d18ca907c6a1e485748c85126",
"content-hash": "4743d72a16fc19ce129105ff123e0ed6",
"packages": [],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=5.3.0"
},
"platform-dev": []
}
@@ -0,0 +1,129 @@
<?php namespace Beanstream;
/**
* Configuration class to handle merchant id, api keys, platform & version
*
* @author Kevin Saliba
*/
class Configuration {
/**
* Configuration: API Version
*
* @var string $_version
*/
protected $_version = 'v1'; //default
/**
* Configuration: API Platform
*
* @var string $_platform
*/
protected $_platform = 'api'; //default
/**
* Configuration: Merchant ID
*
* @var string $_merchantId
*/
protected $_merchantId;
/**
* Configuration: API Key
*
* @var string $_apiKey
*/
protected $_apiKey;
/**
* setMerchantId() function
*
* @param string $merchantId
*
* @throws ConfigurationException
*/
public function setMerchantId($merchantId = '') {
//check to make sure string strlen is 9 containing only digits 0-9
if (!preg_match('/^[0-9]{9}$/', $merchantId)) { //TODO switch to actual real assertmerchantId
//throw exception
throw new ConfigurationException('Invalid Merchant ID provided: '.$merchantId. ' Expected 9 digits.');
}
$this->_merchantId = $merchantId;
}
/**
* getMerchantId() function
*
* @return string merchant id
*/
public function getMerchantId() {
return $this->_merchantId;
}
/**
* setApiKey() function
*
* @param string $apiKey
* @return void
*/
public function setApiKey($apiKey) {
$this->_apiKey=$apiKey;
}
/**
* getApiKey() function
*
* @return string api key
*/
public function getApiKey() {
return $this->_apiKey;
}
/**
* setPlatform() function
*
* @param string $platform
* @return void
*/
public function setPlatform($platform = '') {
//make sure it's not blank
//if blank, don't set it and use default declared above
if (strlen($platform) > 0) { //TODO switch to actual real assertnotempty
$this->_platform=$platform;
}
}
/**
* getPlatform() function
*
* @return string platform
*/
public function getPlatform() {
return $this->_platform;
}
/**
* setApiVersion() function
*
* @param string $version
* @return void
*/
public function setApiVersion($version = '') {
//make sure it's not blank
//if blank, don't set it and use default declared above
if (strlen($version) > 0) { //TODO switch to actual real assertnotempty
$this->_version=$version;
}
}
/**
* getApiVersion() function
*
* @return string version
*/
public function getApiVersion() {
return $this->_version;
}
}
@@ -0,0 +1,71 @@
<?php namespace Beanstream;
/**
* Exception class
*
* Beanstream specific exception types
*
* Zero error code corresponds to PHP API specific errors
*
* Positive error codes correspond to those of Beanstream API
* @link http://developer.beanstream.com/documentation/take-payments/errors/
* @link http://developer.beanstream.com/documentation/analyze-payments/errors/
* @link http://developer.beanstream.com/documentation/analyze-payments/api-messages/
* @link http://developer.beanstream.com/documentation/tokenize-payments/errors/
*
* Negative error codes corresponde to those of cURL
* @link http://curl.haxx.se/libcurl/c/libcurl-errors.html
*
* @author Kevin Saliba
*/
class Exception extends \Exception {
/**
* Exception: Message class variable
*
* @var string $_message holds the human-readable error message string
*/
protected $_message;
/**
* Exception: Code class variable
*
* @var int $_code holds the error message code (0=PHP, Positive=Beanstream API, Negative=cURL)
*/ protected $_code;
/**
* Constructor
*
* @param string $message Human-readable exception message
* @param int $code Exception code (0=PHP[default], Positive=Beanstream API, Negative=cURL)
*/
public function __construct($message, $code = 0) {
//set class vars
$this->_message = $message;
$this->_code = $code;
//send to super
parent::__construct($this->_message, $this->_code);
}
}
/**
* ConfigurationException class
*/
class ConfigurationException extends Exception {}
/**
* ConnectorException class
*/
class ConnectorException extends Exception {}
/**
* ApiException class
*/
class ApiException extends Exception {}
@@ -0,0 +1,123 @@
<?php namespace Beanstream;
//TODO implement loader
require_once 'Exception.php';
require_once 'Configuration.php';
require_once 'communications/Endpoints.php';
require_once 'communications/HttpConnector.php';
require_once 'api/Payments.php';
require_once 'api/Profiles.php';
require_once 'api/Reporting.php';
/**
* Gateway class - Main class to facilitate comms with Beanstream Gateway,
*
* @author Kevin Saliba
*/
class Gateway {
/**
* Config object
*
* Holds mid, apikey, platform, api version
*
* @var \Beanstream\Configuration $_config
*/
protected $_config;
/**
* API Objects
*
* Holds API objects with appropriate config
*
* @var \Beanstream\Payments $_paymentsAPI
* @var \Beanstream\Profiles $_profilesAPI
* @var \Beanstream\Reporting $_reportingAPI
*/
protected $_paymentsAPI;
protected $_profilesAPI;
protected $_reportingAPI;
/**
* Constructor
*
* @param string $merchantId Merchant ID
* @param string $apiKey API Access Passcode
* @param string $platform API Platform (default 'www')
* @param string $version API Version (default 'v1')
*/
public function __construct($merchantId = '', $apiKey, $platform, $version) {
//set configs
$this->_config = new Configuration();
$this->_config->setMerchantId($merchantId);
$this->_config->setApiKey($apiKey);
$this->_config->setPlatform($platform);
$this->_config->setApiVersion($version);
}
/**
* getConfig() function
*
* @return \Beanstream\Configuration this gateway's set config
*/
public function getConfig() {
return $this->_config;
}
/**
* payments() function
*
* Public facing function to return the configured payment API
* All comms with the Payments API will go through this function
*
* @return \Beanstream\Payments this gateway's payment api object
*/
public function payments() {
//check to see if we already have it created
if (is_null($this->_paymentsAPI)) {
//if we don't, create it
$this->_paymentsAPI = new Payments($this->_config);
}
return $this->_paymentsAPI;
}
/**
* profiles() function.
*
* Public facing function to return the configured profiles API
* All comms with the Profiles API will go through this function
*
* @return \Beanstream\Profiles this gateway's profiles api object
*/
public function profiles() {
//check to see if we already have it created
if (is_null($this->_profilesAPI)) {
//if we don't, create it
$this->_profilesAPI = new Profiles($this->_config);
}
return $this->_profilesAPI;
}
/**
* reporting() function
*
* Public facing function to return the configured reporting API
* All comms with the Reporting API will go through this function
*
* @return \Beanstream\Reporting this gateway's reporting api object
*/
public function reporting() {
//check to see if we already have it created
if (is_null($this->_reportingAPI)) {
//if we don't, create it
$this->_reportingAPI = new Reporting($this->_config);
}
return $this->_reportingAPI;
}
}
@@ -0,0 +1,282 @@
<?php namespace Beanstream;
/**
* Enpoints class to build, format and return API endpoint urls based on incoming platform and version
*
* @author Kevin Saliba
*/
class Endpoints {
/**
* Endpoints: Set BASE API Endpoint URL with inline {0} platform variable
*/
CONST BASE_URL_BAMBORANA = 'https://{0}.na.bambora.com';
CONST BASE_URL_BEANSTREAM = 'https://{0}.beanstream.com'; //keeping beanstream endpoint for backwards compatibility when $platform = 'www'
/**
* Endpoint URL holders
*
* Holds each of the URLS for the API endpoints
* platform and version are added in the constructor
*
* @var string $basePaymentsURL
* @var string $getPaymentURL
* @var string $baseProfilesURL
* @var string $preAuthCompletionsURL
* @var string $returnsURL
* @var string $voidsURL
* @var string $profileURI
* @var string $cardsURI
* @var string $reportsURL
* @var string $continuationsURL
* @var string $tokenizationURL
*/
protected $basePaymentsURL;
protected $getPaymentURL;
protected $baseProfilesURL;
protected $preAuthCompletionsURL;
protected $returnsURL;
protected $unreferencedReturnsURL;
protected $voidsURL;
protected $profileURI;
protected $cardsURI;
protected $reportsURL;
protected $continuationsURL;
protected $tokenizationURL;
/**
* Endpoint: incoming API Platform
*
* @var string $_platform
*/
protected $_platform;
/**
* Endpoint: incoming API Version
*
* @var string $_version
*/
protected $_version;
/**
* Constructor
*
* @param string $platform API Platform
* @param string $version API Version
*/
function __construct($platform, $version) {
//assign endpoints
$baseUrl = ($platform == 'www' ? self::BASE_URL_BEANSTREAM . '/api' : self::BASE_URL_BAMBORANA);
//payments
$this->basePaymentsURL = $baseUrl . '/{1}/payments';
$this->preAuthCompletionsURL = $this->basePaymentsURL . '/{2}/completions';
$this->returnsURL = $this->basePaymentsURL . '/{2}/returns';
$this->unreferencedReturnsURL = $this->basePaymentsURL . '/0/returns';
$this->voidsURL = $this->basePaymentsURL . '/{2}/void';
$this->continuationsURL = $this->basePaymentsURL . '/{2}/continue';
$this->tokenizationURL = ($platform == 'www' ? self::BASE_URL_BEANSTREAM . '/scripts/tokenization/tokens' : $baseUrl . '/scripts/tokenization/tokens');
//profiles
$this->baseProfilesURL = $baseUrl . '/{1}/profiles';
$this->profileURI = $this->baseProfilesURL . '/{2}';
$this->cardsURI = $this->profileURI . '/cards';
$this->cardURI = $this->cardsURI . '/{3}';
//reporting
$this->reportsURL = $baseUrl . '/{1}/reports';
$this->getPaymentURL = $this->basePaymentsURL . '/{2}';
//assign incoming platform and version
$this->_platform = $platform;
$this->_version = $version;
}
//methods to build out and return endpoints
//payments
/**
* getBasePaymentsURL() function
*
* @return string Endpoint URL
*/
public function getBasePaymentsURL() {
//parse url and replace variables via messageformat
//return msgfmt_format_message('en_US', $this->basePaymentsURL, array($this->_platform, $this->_version));
//or use less-stringent str_replace instead of msgfmt above
return str_replace(array('{0}', '{1}'), array($this->_platform, $this->_version), $this->basePaymentsURL);
}
/**
* getContinuationsURL() function
*
* @param string $merchant_data The IDEBIT_MERCHDATA value returned by the Interac response
* @return string Endpoint URL
*/
public function getContinuationsURL($merchant_data) {
return str_replace(array('{0}', '{1}', '{2}'), array($this->_platform, $this->_version, $merchant_data), $this->continuationsURL);
}
/**
* getPreAuthCompletionsURL() function
*
* @param string $tid Transaction Id
* @return string Endpoint URL
*/
public function getPreAuthCompletionsURL($tid) {
//parse url and replace variables via messageformat
//return msgfmt_format_message('en_US', $this->preAuthCompletionsURL, array($this->_platform, $this->_version, $tid));
//or use less-stringent str_replace instead of messageformat above
return str_replace(array('{0}', '{1}', '{2}'), array($this->_platform, $this->_version, $tid), $this->preAuthCompletionsURL);
}
/**
* getReturnsURL() function
*
* @param string $tid Transaction Id
* @return string Endpoint URL
*/
public function getReturnsURL($tid) {
//parse url and replace variables via messageformat
//return msgfmt_format_message('en_US', $this->returnsURL, array($this->_platform, $this->_version, $tid));
//or use less-stringent str_replace instead of messageformat above
return str_replace(array('{0}', '{1}', '{2}'), array($this->_platform, $this->_version, $tid), $this->returnsURL);
}
/**
* getUnreferencedReturnsURL() function
*
* @return string Endpoint URL
*/
public function getUnreferencedReturnsURL() {
//parse url and replace variables via messageformat
//return msgfmt_format_message('en_US', $this->unreferencedReturnsURL, array($this->_platform, $this->_version));
//or use less-stringent str_replace instead of messageformat above
return str_replace(array('{0}', '{1}'), array($this->_platform, $this->_version), $this->unreferencedReturnsURL);
}
/**
* getVoidsURL() function
*
* @param string $tid Transaction Id
* @return string Endpoint URL
*/
public function getVoidsURL($tid) {
//parse url and replace variables via messageformat
//return msgfmt_format_message('en_US', $this->voidsURL, array($this->_platform, $this->_version, $tid));
//or use less-stringent str_replace instead of messageformat above
return str_replace(array('{0}', '{1}', '{2}'), array($this->_platform, $this->_version, $tid), $this->voidsURL);
}
/**
* getTokenURL() function
*
* @return string Endpoint URL
*/
public function getTokenURL() {
//parse url and replace variables via messageformat
//return msgfmt_format_message('en_US', $this->tokenizationURL, array($this->_platform));
//or use less-stringent str_replace instead of messageformat above
return str_replace(array('{0}'), array($this->_platform), $this->tokenizationURL);
}
//profiles
/**
* getProfilesURL() function
*
* @return string Endpoint URL
*/
public function getProfilesURL() {
//parse url and replace variables via messageformat
//return msgfmt_format_message('en_US', $this->baseProfilesURL, array($this->_platform, $this->_version));
//or use less-stringent str_replace instead of messageformat above
return str_replace(array('{0}', '{1}'), array($this->_platform, $this->_version), $this->baseProfilesURL);
}
/**
* getProfileURI() function
*
* @param string $pid Profile Id
* @return string Endpoint URL
*/
public function getProfileURI($pid) {
//parse url and replace variables via messageformat
//return msgfmt_format_message('en_US', $this->profileURI, array($this->_platform, $this->_version, $pid));
//or use less-stringent str_replace instead of messageformat above
return str_replace(array('{0}', '{1}', '{2}'), array($this->_platform, $this->_version, $pid), $this->profileURI);
}
/**
* getCardsURI() function
*
* @param string $pid Profile Id
* @return string Endpoint URL
*/
public function getCardsURI($pid) {
//parse url and replace variables via messageformat
//return msgfmt_format_message('en_US', $this->cardsURI, array($this->_platform, $this->_version, $pid));
//or use less-stringent str_replace instead of messageformat above
return str_replace(array('{0}', '{1}', '{2}'), array($this->_platform, $this->_version, $pid), $this->cardsURI);
}
/**
* getCardURI() function
*
* @param string $pid Profile Id
* @param string $cid Card Id
* @return string Endpoint URL
*/
public function getCardURI($pid, $cid) {
//parse url and replace variables via messageformat
//return msgfmt_format_message('en_US', $this->cardURI, array($this->_platform, $this->_version, $pid, $cid));
//or use less-stringent str_replace instead of messageformat above
return str_replace(array('{0}', '{1}', '{2}', '{3}'), array($this->_platform, $this->_version, $pid, $cid), $this->cardURI);
}
//reporting
/**
* getReportingURL() function
*
* @return string Endpoint URL
*/
public function getReportingURL() {
//parse url and replace variables via messageformat
//return msgfmt_format_message('en_US', $this->reportsURL, array($this->_platform, $this->_version));
//or use less-stringent str_replace instead of messageformat above
return str_replace(array('{0}', '{1}'), array($this->_platform, $this->_version), $this->reportsURL);
}
/**
* getPaymentUrl() function
*
* @param string $tid Transaction Id
* @return string Endpoint URL
*/
public function getPaymentUrl($tid) {
//parse url and replace variables via messageformat
//return msgfmt_format_message('en_US', $this->getPaymentURL, array($this->_platform, $this->_version, $tid));
//or use less-stringent str_replace instead of messageformat above
return str_replace(array('{0}', '{1}', '{2}'), array($this->_platform, $this->_version, $tid), $this->getPaymentURL);
}
}
@@ -0,0 +1,124 @@
<?php namespace Beanstream;
/**
* HTTPConnector class to handle HTTP requests to the REST API
*
* @author Kevin Saliba
*/
class HttpConnector {
/**
* Base64 Encoded Auth String
*
* @var string $_auth
*/
protected $_auth;
/**
* Constructor
*
* @param string $auth base64 encoded string to assign to the http header
*/
function __construct($auth) {
//set auth for this connection only
$this->_auth = $auth;
}
/**
* processTransaction() function - Public facing function to send a request to an endpoint.
*
* @param string $http_method HTTP method to use (defaults to GET if $data==null; defaults to PUT if $data!=null)
* @param string $endpoint Incoming API Endpoint
* @param array $data Data for POST requests, not needed for GETs
* @access public
* @return array Parsed API response from private request method
*
*/
public function processTransaction($http_method, $endpoint, $data) {
//call internal request function
return $this->request($http_method, $endpoint, $data);
}
/**
* request() function - Internal function to send a request to an endpoint.
*
* @param string|null $http_method HTTP method to use (defaults to GET if $data==null; defaults to PUT if $data!=null)
* @param string $url Incoming API Endpoint
* @param array|null $data Data for POST requests, not needed for GETs
* @access private
* @return array Parsed API response
*
* @throws ApiException
* @throws ConnectorException
*/
private function request($http_method = NULL, $url, $data = NULL)
{
//check to see if we have curl installed on the server
if ( ! extension_loaded('curl')) {
//no curl
throw new ConnectorException('The cURL extension is required', 0);
}
//init the curl request
//via endpoint to curl
$req = curl_init($url);
//set request headers with encoded auth
curl_setopt($req, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Authorization: Passcode '.$this->_auth,
));
//set other curl options
curl_setopt($req, CURLOPT_RETURNTRANSFER, true);
curl_setopt($req, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($req, CURLOPT_TIMEOUT, 30);
//test ssl3 (remember to set platform to 'ssltest')
//should no longer work after 01/01/2015
//curl_setopt($req, CURLOPT_SSLVERSION, 3);
//set http method
//default to GET if data is null
//default to POST if data is not null
if (is_null($http_method)) {
if (is_null($data)) {
$http_method = 'GET';
} else {
$http_method = 'POST';
}
}
//set http method in curl
curl_setopt($req, CURLOPT_CUSTOMREQUEST, $http_method);
//make sure incoming payload is good to go, set it
if ( ! is_null($data)) {
curl_setopt($req, CURLOPT_POSTFIELDS, json_encode($data));
}
//execute curl request
$raw = curl_exec($req);
if (false === $raw) { //make sure we got something back
throw new ConnectorException(curl_error($req), -curl_errno($req));
}
//decode the result
$res = json_decode($raw, true);
if (is_null($res)) { //make sure the result is good to go
throw new ConnectorException('Unexpected response format', 0);
}
//check for return errors from the API
if (isset($res['code']) && 1 < $res['code'] && !($req['http_code'] >= 200 && $req['http_code'] < 300)) {
throw new ApiException($res['message'], $res['code']);
}
return $res;
}
}
@@ -0,0 +1,248 @@
<pre><?php
//BEANSTREAM REST API SDK USAGE EXAMPLES
//get Beanstream Gateway
require_once 'Gateway.php';
//init api settings (beanstream dashboard > administration > account settings > order settings)
$merchant_id = ''; //INSERT MERCHANT ID (must be a 9 digit string)
$api_key = ''; //INSERT API ACCESS PASSCODE
$api_version = 'v1'; //default
$platform = 'api'; //default (or use 'tls12-api' for the TLS 1.2-Only endpoint)
//generate a random order number, and set a default $amount (only used for example functions)
$order_number = bin2hex(mcrypt_create_iv(22, MCRYPT_DEV_URANDOM));
$amount = 1.00;
//init new Beanstream Gateway object
$beanstream = new \Beanstream\Gateway($merchant_id, $api_key, $platform, $api_version);
//example array data for use in example functions
//example payment transaction data
$payment_data = array(
'order_number' => $order_number,
'amount' => $amount,
'payment_method' => 'card',
'card' => array(
'name' => 'Mr. Card Testerson',
'number' => '4030000010001234',
'expiry_month' => '07',
'expiry_year' => '22',
'cvd' => '123'
),
'billing' => array(
'name' => 'Mr. John Doe',
'email_address' => 'johndoe@email.com',
'phone_number' => '1234567890',
'address_line1' => 'Main St.',
'city' => 'Anytown',
'province' => 'BC',
'postal_code' => 'V8J9I5',
'country' => 'CA'
),
'shipping' => array(
'name' => 'Shipping Name',
'email_address' => 'email@email.com',
'phone_number' => '1234567890',
'address_line1' => '789-123 Shipping St.',
'city' => 'Shippingsville',
'province' => 'BC',
'postal_code' => 'V8J9I5',
'country' => 'CA'
)
);
//example profile function test vars
$profile_id = ''; //enter a profile_id to get a profile
$card_id = '1'; //default card, 1-based index
//example profile data to create
$profile_data = array(
'billing' => array(
'name' => 'Profile Billing Name',
'email_address' => 'email@email.com',
'phone_number' => '1234567890',
'address_line1' => '456-123 Shipping St.',
'city' => 'Shippingville',
'province' => 'BC',
'postal_code' => 'V8J9I5',
'country' => 'CA'
)
);
//example card data to add to a profile
$card_data = array(
'card' => array(
'name' => 'Test Testerson',
'number' => '4030000010001234',
'expiry_month' => '07',
'expiry_year' => '22',
'cvd' => '123'
)
);
//example unreferenced return data
$return_data = array(
'order_number' => $order_number,
'amount' => $amount,
'payment_method' => 'card',
'card' => array(
'name' => 'Mr. Refund Testerson',
'number' => '4030000010001234',
'expiry_month' => '07',
'expiry_year' => '22',
'cvd' => '123'
)
);
//example profile payment data
$profile_payment_data = array(
'order_number' => $order_number,
'amount' => $amount
);
//example data to simulate getting a legato token
$legato_token_data = array(
'number' => '4030000010001234',
'expiry_month' => '07',
'expiry_year' => '22',
'cvd' => '123'
);
//example legato payment data
//name is actually insterted into ['token']['name']
$legato_payment_data = array(
'order_number' => $order_number,
'amount' => $amount,
'name' => 'Mrs. Legato Testerson'
);
//example search criteria data
$search_criteria = array(
'name' => 'TransHistoryMinimal', // or 'Search',
'start_date' => '1999-01-01T00:00:00',
'end_date' => '2016-01-01T23:59:59',
'start_row' => '1',
'end_row' => '15000',
'criteria' => array(
'field' => '1',
'operator' => '%3E',
'value' => '1000000'
)
);
//example payment function test vars
$transaction_id = ''; //enter a transaction id to use in below functions
$complete = TRUE;
//REQUEST EXAMPLE FUNCTIONS BELOW
//UNCOMMENT THE ONES YOU WOULD LIKE TO TEST
try {
//**** PAYMENTS EXAMPLES
//make a credit card payment
//$result = $beanstream->payments()->makeCardPayment($payment_data, $complete);
//$transaction_id = $result['id'];
//complete a PA
//$result = $beanstream->payments()->complete($transaction_id, $amount, $order_number);
//cash payment
//$result = $beanstream->payments()->makeCashPayment($payment_data);
//cheque payment
//$result = $beanstream->payments()->makeChequePayment($payment_data);
//return a payment
//$result = $beanstream->payments()->returnPayment($transaction_id, $amount, $order_number);
//return a payment (unreferenced)
//$result = $beanstream->payments()->unreferencedReturn($return_data);
//void a payment
//$result = $beanstream->payments()->voidPayment($transaction_id, $amount);
//simulate legato token payment (SHOULD NEVER BE CALLED IN PRODUCTION)
//$token = $beanstream->payments()->getTokenTest($legato_token_data);
//make legato payment with above token
//$result = $beanstream->payments()->makeLegatoTokenPayment($token, $legato_payment_data, $complete);
//**** PROFILES EXAMPLES
//create a profile
//$profile_id = $beanstream->profiles()->createProfile($profile_data);
//get a profile based on a profile cust code
//$result = $beanstream->profiles()->getProfile($profile_id);
//update a profile based on a profile cust code
//$result = $beanstream->profiles()->updateProfile($profile_id, $profile_data);
//delete a profile
//$result = $beanstream->profiles()->deleteProfile($profile_id);
//add a card to a profile
//$result = $beanstream->profiles()->addCard($profile_id, $card_data);
//profile payment
//$result = $beanstream->payments()->makeProfilePayment($profile_id, $card_id, $profile_payment_data, $complete);
//$transaction_id = $result['id'];
//complete a profile payment
//$result = $beanstream->payments()->complete($transaction_id, $profile_payment_data['amount'], $order_number);
//get all cards in profile
//$result = $beanstream->profiles()->getCards($profile_id);
//update a specfic card in a profile
//$result = $beanstream->profiles()->updateCard($profile_id, $card_id, $card_data);
//delete a specfic card in a profile
//$result = $beanstream->profiles()->deleteCard($profile_id, $card_id);
//**** REPORTING EXAMPLES
//search for transactions that match criteria //DOESN'T RETURN ALL TX (ie. VP/VR)?
//$result = $beanstream->reporting()->getTransactions($search_criteria);
//get a specific transaction
//$result = $beanstream->reporting()->getTransaction($transaction_id);
//display result
is_null($result)?:print_r($result);
} catch (\Beanstream\Exception $e) {
/*
* Handle transaction error, $e->code can be checked for a
* specific error, e.g. 211 corresponds to transaction being
* DECLINED, 314 - to missing or invalid payment information
* etc.
*/
print_r($e);
}
?></pre>
+7
View File
@@ -0,0 +1,7 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer' . '/autoload_real.php';
return ComposerAutoloaderInit0264f0d97ee3d68f182236ddbed8af04::getLoader();
@@ -0,0 +1,413 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see http://www.php-fig.org/psr/psr-0/
* @see http://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
// PSR-4
private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
private $fallbackDirsPsr4 = array();
// PSR-0
private $prefixesPsr0 = array();
private $fallbackDirsPsr0 = array();
private $useIncludePath = false;
private $classMap = array();
private $classMapAuthoritative = false;
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', $this->prefixesPsr0);
}
return array();
}
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array $classMap Class to filename map
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 base directories
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
/**
* Unregisters this instance as an autoloader.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return bool|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
if ('\\' == $class[0]) {
$class = substr($class, 1);
}
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative) {
return false;
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if ($file === null && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if ($file === null) {
// Remember that this class does not exist.
return $this->classMap[$class] = false;
}
return $file;
}
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
if (0 === strpos($class, $prefix)) {
foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*/
function includeFile($file)
{
include $file;
}
+21
View File
@@ -0,0 +1,21 @@
Copyright (c) 2016 Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,9 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);
@@ -0,0 +1,10 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Beanstream' => array($baseDir . '/src'),
);
@@ -0,0 +1,9 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);
@@ -0,0 +1,45 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit0264f0d97ee3d68f182236ddbed8af04
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit0264f0d97ee3d68f182236ddbed8af04', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit0264f0d97ee3d68f182236ddbed8af04', 'loadClassLoader'));
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
$loader->register(true);
return $loader;
}
}
@@ -0,0 +1 @@
[]