Skip to content

Instantly share code, notes, and snippets.

@gamalan
Created January 13, 2016 10:32
Show Gist options
  • Save gamalan/54c8e2df43bbe89ac8ae to your computer and use it in GitHub Desktop.
Save gamalan/54c8e2df43bbe89ac8ae to your computer and use it in GitHub Desktop.
Skrill Adapter for BoxBilling
<?php
/**
* BoxBilling
*
* @copyright BoxBilling, Inc (http://www.boxbilling.com)
* @license Apache-2.0
*
* Copyright BoxBilling, Inc
* This source file is subject to the Apache-2.0 License that is bundled
* with this source code in the file LICENSE
*/
class Payment_Adapter_Skrill
{
private $config = array();
public function __construct($config)
{
$this->config = $config;
if(!function_exists('curl_exec')) {
throw new Exception('PHP Curl extension must be enabled in order to use Skrill gateway');
}
if(!$this->config['email']) {
throw new Exception('Payment gateway "Skrill" is not configured properly. Please update configuration parameter "Skrill Email address" at "Configuration -> Payments".');
}
}
public static function getConfig()
{
return array(
'supports_one_time_payments' => true,
'supports_subscriptions' => true,
'description' => 'Skrill payment gateway for BoxBilling',
'form' => array(
'email' => array('text', array(
'label' => 'Skrill email address for payment',
),
)
),
);
}
/**
* Generate payment text
*
* @param Api_Admin $api_admin
* @param int $invoice_id
* @param bool $subscription
*
* @since BoxBilling v2.9.15
*
* @return string - html form with auto submit javascript
*/
public function getHtml($api_admin, $invoice_id, $subscription)
{
$invoice = $api_admin->invoice_get(array('id'=>$invoice_id));
$param = array(
':id'=>sprintf('%05s', $invoice['nr']),
':serie'=>$invoice['serie'],
':title'=>$invoice['lines'][0]['title']
);
$title = __('Payment for invoice :serie:id [:title]', $param);
$number = $invoice['nr'];
// Payment data.
$data = array();
// Merchant Details
$data['pay_to_email'] = $this->config['email'];
$data['transaction_id'] = $number;
$data['return_url'] = $this->config['return_url'];
$data['cancel_url'] = $this->config['cancel_url'];
$data['status_url'] = $this->config['notify_url'];
$data['dynamic_descriptor'] = "Descriptor";
$data['redirect_url'] = $this->config['redirect_url'];
$data['continue_shopping_url'] = $this->config['continue_shopping_url'];
// Payment Details
$data['currency'] = $invoice['currency'];
$data['amount'] = $this->moneyFormat($invoice['total'], $invoice['currency']);
$data['detail1_description'] = "Invoice Number: ";
$data['detail1_text'] = $number;
$data['detail2_description'] = "Title: ";
$data['detail2_text'] = $title;
// Customer Details
$data['pay_from_email'] = $invoice['buyer_email'];
$data['firstname'] = $invoice['buyer_first_name'];
$data['lastname'] = $invoice['buyer_last_name'];
$data['address'] = $invoice['buyer_address'];
$data['city'] = $invoice['buyer_city'];
$data['state'] = $invoice['buyer_state'];
$data['country'] = $invoice['buyer_country'];
$data['phone_number'] = $invoice['buyer_phone'];
$data['postal_code'] = $invoice['buyer_zip'];
if($subscription) {
$subs = $invoice['subscription'];
$data['rec_amount'] = $this->moneyFormat($invoice['total'], $invoice['currency']);
$data['rec_period'] = $subs['cycle'];
switch( $subs['unit'] ) {
case 'D':
$rec_cycle = 'day';
break;
case 'W':
$rec_cycle = 'week';
break;
case 'M':
$rec_cycle = 'month';
break;
case 'Y':
$rec_cycle = 'year';
break;
}
$data['rec_cycle'] = $rec_cycle;
$data['rec_status_url'] = $this->config['notify_url'];
}
return $this->_generateForm($this->serviceUrl(), $data);
}
/**
* Process transaction received from payment gateway
*
* @since BoxBilling v2.9.15
*
* @param Api_Admin $api_admin
* @param int $id - transaction id to process
* @param array $ipn - post, get, server, http_raw_post_data
* @param int $gateway_id - payment gateway id on BoxBilling
*
* @return mixed
*/
public function processTransaction($api_admin, $id, $data, $gateway_id)
{
if(APPLICATION_ENV != 'testing' && !$this->_isIpnValid($data)) {
throw new Payment_Exception('IPN is not valid');
}
$ipn = $data['post'];
$tx = $api_admin->invoice_transaction_get(array('id'=>$id));
if(!$tx['invoice_id']) {
$api_admin->invoice_transaction_update(array('id'=>$id, 'invoice_id'=>$data['get']['bb_invoice_id']));
}
if(!$tx['type']) {
$api_admin->invoice_transaction_update(array('id'=>$id, 'type'=>$ipn['payment_type']));
}
if(!$tx['txn_id']) {
$api_admin->invoice_transaction_update(array('id'=>$id, 'txn_id'=>$ipn['transaction_id']));
}
if(!$tx['amount']) {
$api_admin->invoice_transaction_update(array('id'=>$id, 'amount'=>$ipn['mb_amount']));
}
if(!$tx['currency']) {
$api_admin->invoice_transaction_update(array('id'=>$id, 'currency'=>$ipn['mb_currency']));
}
$data = array(
'id' => $id,
'error' => '',
'error_code'=> '',
'status' => 'processed',
'updated_at'=> date('c'),
);
$api_admin->invoice_transaction_update($data);
}
private function serviceUrl(){
$url = '';
if($this->config['test_mode']) {
$url = 'https://www.skrill.com/app/test_payment.pl';
} else {
$url = 'https://www.skrill.com/app/payment.pl';
}
return $url;
}
private function _isIpnValid($data)
{
// use http_raw_post_data instead of post due to encoding
parse_str($data['http_raw_post_data'], $post);
$req = 'cmd=_notify-validate';
foreach ((array) $post as $key => $value) {
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
$url = $this->serviceUrl();
$ret = $this->download($url, $req);
return $ret == 'VERIFIED';
}
private function moneyFormat($amount, $currency)
{
//HUF currency do not accept decimal values
if($currency == 'HUF') {
return number_format($amount, 0);
}
return number_format($amount, 2, '.', '');
}
/**
* @param string $url
*/
private function download($url, $post_vars = false, $phd = array(), $contentType = 'application/x-www-form-urlencoded')
{
$post_contents = '';
if ($post_vars) {
if (is_array($post_vars)) {
foreach($post_vars as $key => $val) {
$post_contents .= ($post_contents ? '&' : '').urlencode($key).'='.urlencode($val);
}
} else {
$post_contents = $post_vars;
}
}
$uinf = parse_url($url);
$host = $uinf['host'];
$path = $uinf['path'];
$path .= (isset($uinf['query']) && $uinf['query']) ? ('?'.$uinf['query']) : '';
$headers = Array(
($post_contents ? 'POST' : 'GET')." $path HTTP/1.1",
"Host: $host",
'Connection: Close',
'User-Agent: BoxBilling'
);
if (!empty($phd)) {
if (!is_array($phd)) {
$headers[count($headers)] = $phd;
} else {
$next = count($headers);
$count = count($phd);
for ($i = 0; $i < $count; $i++) { $headers[$next + $i] = $phd[$i]; }
}
}
if ($post_contents) {
$headers[] = "Content-Type: $contentType";
$headers[] = 'Content-Length: '.strlen($post_contents);
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 600);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Apply the XML to our curl call
if ($post_contents) {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_contents);
}
$data = curl_exec($ch);
if (curl_errno($ch)) return false;
curl_close($ch);
return $data;
}
private function _generateForm($url, $data, $method = 'post')
{
$form = '';
$form .= '<form name="payment_form_skrill" action="'.$url.'" method="'.$method.'">';
//following the procedure at http://skrill.com/app/test-payment.pl all field is hidden
foreach($data as $key => $value) {
$form .= sprintf('<input type="hidden" name="%s" value="%s" />', $key, $value);
}
$form .= '<input class="bb-button bb-button-submit" type="submit" value="Pay with Skrill" id="payment_button"/>';
$form .= '</form>';
if(isset($this->config['auto_redirect']) && $this->config['auto_redirect']) {
$form .= sprintf('<h2>%s</h2>', __('Redirecting to Skrill.com'));
$form .= "<script type='text/javascript'>$(document).ready(function(){
document.getElementById('payment_button').style.display = 'none';
document.forms['payment_form_skrill'].submit();});
</script>";
}
return $form;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment