Skip to content

Instantly share code, notes, and snippets.

@joglomedia
Last active December 30, 2015 07:59
Show Gist options
  • Save joglomedia/7799831 to your computer and use it in GitHub Desktop.
Save joglomedia/7799831 to your computer and use it in GitHub Desktop.
Skrill webform/offsite payment gateway for BoxBilling
<?php
/**
* BoxBilling
*
* LICENSE
*
* This source file is subject to the license that is bundled
* with this package in the file LICENSE.txt
* It is also available through the world-wide-web at this URL:
* http://www.boxbilling.com/LICENSE.txt
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@boxbilling.com so we can send you a copy immediately.
*
* @copyright Copyright (c) 2010-2012 BoxBilling (http://www.boxbilling.com)
* @license http://www.boxbilling.com/LICENSE.txt
* @version $Id$
*/
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' => 'Custom payment gateway allows you to give instructions how can your client pay invoice. All system, client, order and invoice details can be printed. HTML and JavaScript code is supported.',
'form' => array(
'email' => array(
'text',
array(
'label' => 'Skrill E-Mail address for payment',
'validators' => array('EmailAddress'),
),
),
),
);
}
/**
* 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));
$buyer = $invoice['buyer'];
$p = array(
':id'=>sprintf('%05s', $invoice['nr']),
':serie'=>$invoice['serie'],
':title'=>$invoice['lines'][0]['title']
);
$title = __('Payment for invoice :serie:id [:title]', $p);
$number = $invoice['nr'];
// Payment data.
$data = array();
// Subscription.
if($subscription) {
$subs = $invoice['subscription'];
$data['rec_amount'] = $this->moneyFormat($invoice['total'], $invoice['currency']); // Regular subscription price.
$data['rec_period'] = $subs['cycle']; //Subscription period. Specify an integer value in the allowable range for the units of duration that you specify with t3.
//$data['rec_grace_period'] = 1;
/**
* rec_cycle: Regular subscription units of period. Allowable values:
* D/day – for days; allowable range for p3 is 1 to 90
* W/week – for weeks; allowable range for p3 is 1 to 52
* M/month – for months; allowable range for p3 is 1 to 24
* Y/year – for years; allowable range for p3 is 1 to 5
*/
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'];
}
// 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['amount2'] = $this->moneyFormat($invoice['tax'], $invoice['currency']); // Tax
//$data['amount2_description'] = "Tax: ";
$data['detail1_description'] = "Invoice Number: ";
$data['detail1_text'] = $number;
$data['detail2_description'] = "Title: ";
$data['detail2_text'] = $title;
// Customer Details
$data['pay_from_email'] = $buyer['email'];
$data['firstname'] = $buyer['first_name'];
$data['lastname'] = $buyer['last_name'];
$data['address'] = $buyer['address'];
$data['city'] = $buyer['city'];
$data['state'] = $buyer['state'];
$data['country'] = $buyer['country'];
$data['phone_number'] = $buyer['phone'];
$data['postal_code'] = $buyer['zip'];
if($this->config['test_mode']) {
$url = 'https://www.skrill.com/app/test_payment.pl';
} else {
$url = 'https://www.skrill.com/app/payment.pl';
}
return $this->_generateForm($url, $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 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['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 _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 ($post as $key => $value) {
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
$ret = $this->download('https://www.skrill.com/app/payment.pl', $req);
return $ret == 'VERIFIED';
}
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",
);
if ($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 moneyFormat($amount, $currency)
{
// HUF currency do not accept decimal values.
if($currency == 'HUF') {
return number_format($amount, 0);
}
return number_format($amount, 2, '.', '');
}
private function _generateForm($url, $data, $method = 'post')
{
$form = '';
$form .= '<form name="payment_form" action="'.$url.'" method="'.$method.'">' . PHP_EOL;
foreach($data as $key => $value) {
$form .= sprintf('<input type="hidden" name="%s" value="%s" />', $key, $value) . PHP_EOL;
}
$form .= '<input class="bb-button bb-button-submit" type="submit" value="Pay with Skrill (MoneyBookers)" id="payment_button"/>'. PHP_EOL;
$form .= '</form>' . PHP_EOL . PHP_EOL;
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'].submit();});
</script>";
}
return $form;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment