Skip to content

Instantly share code, notes, and snippets.

@sahyung
Last active July 25, 2020 12:16
Show Gist options
  • Select an option

  • Save sahyung/25680049eb2c601294231c996da15b58 to your computer and use it in GitHub Desktop.

Select an option

Save sahyung/25680049eb2c601294231c996da15b58 to your computer and use it in GitHub Desktop.
Payment adapter custom for Boxbilling using Paylane gateway
<?php
/**
* filepath: __DIR__/bb-library/Payment/Adapter/Paylane.php
*/
class Payment_Adapter_Paylane implements \Box\InjectionAwareInterface
{
private $config = array();
protected $di;
public function setDi($di)
{
$this->di = $di;
}
public function getDi()
{
return $this->di;
}
public function __construct($config)
{
if(!function_exists('curl_exec')) {
throw new Payment_Exception('PHP Curl extension not enabled');
}
if(!isset($this->config['merchant_id'])) {
throw new Payment_Exception('Payment gateway "PayLane" is not configured properly. Please update configuration parameter "PayLane Merchant Id" at "Configuration -> Payments".');
}
if(!isset($this->config['salt'])) {
throw new Payment_Exception('Payment gateway "PayLane" is not configured properly. Please update configuration parameter "PayLane Has Salt" at "Configuration -> Payments".');
}
if (!isset($config['test_mode'])) $config['test_mode'] = false;
$this->config = $config;
}
public static function getConfig()
{
return array(
'can_load_in_iframe' => true,
'supports_one_time_payments' => true,
'supports_subscriptions' => false,
'description' => 'Enter your Paylane data to start accepting payments by Paylane.',
'form' => array(
'merchant_id' => array('text', array(
'label' => 'Paylane Merchant ID',
),
),
'salt' => array('text', array(
'label' => 'Paylane Hash salt',
),
),
),
);
}
/**
* 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));
if($subscription) {
$data = $this->getSubscriptionFields($invoice);
} else {
$data = $this->getOneTimePaymentFields($invoice);
}
$url = $this->serviceUrl();
return $this->_generateForm($url, $data);
}
public function processTransaction($api_admin, $id, $data, $gateway_id)
{
$ipn = $data['post'];
if($this->config['test_mode']) {
return json_encode($ipn);
}
if ($this->isIpnDuplicate($ipn)){
throw new Payment_Exception('IPN is duplicate');
}
$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['txn_id'] && isset($ipn['id_sale'])) {
$api_admin->invoice_transaction_update(array('id'=>$id, 'txn_id'=>$ipn['id_sale']));
}
if(!$tx['txn_status'] && isset($ipn['status'])) {
$api_admin->invoice_transaction_update(array('id'=>$id, 'txn_status'=>$ipn['status']));
}
if(!$tx['amount'] && isset($ipn['amount'])) {
$api_admin->invoice_transaction_update(array('id'=>$id, 'amount'=>$ipn['amount']));
}
if(!$tx['currency'] && isset($ipn['currency'])) {
$api_admin->invoice_transaction_update(array('id'=>$id, 'currency'=>$ipn['currency']));
}
$invoice = $api_admin->invoice_get(array('id'=>$data['get']['bb_invoice_id']));
$client_id = $invoice['client']['id'];
if($ipn['status'] == 'PERFORMED') {
$bd = array(
'id' => $client_id,
'amount' => $ipn['amount'],
'description' => 'Paylane transaction '.$ipn['id_sale'],
'type' => 'Paylane',
'rel_id' => $ipn['id_sale'],
);
$api_admin->client_balance_add_funds($bd);
if($tx['invoice_id']) {
$api_admin->invoice_pay_with_credits(array('id'=>$tx['invoice_id']));
}
$api_admin->invoice_batch_pay_with_credits(array('client_id'=>$client_id));
}
$d = array(
'id' => $id,
'error' => '',
'error_code'=> '',
'status' => 'processed',
'updated_at'=> date('Y-m-d H:i:s'),
);
$api_admin->invoice_transaction_update($d);
header("Location: ". $this->config['return_url']);
exit;
}
public function isIpnDuplicate(array $ipn)
{
$sql = 'SELECT id
FROM transaction
WHERE txn_id = :transaction_id
AND txn_status = :transaction_status
AND amount = :transaction_amount
LIMIT 2';
$bindings = array(
':transaction_id' => $ipn['ik_trn_id'],
':transaction_status' => $ipn['ik_inv_st'],
':transaction_amount' => $ipn['ik_am'],
);
$rows = $this->di['db']->getAll($sql, $bindings);
if (count($rows) > 1){
return true;
}
return false;
}
public function getInvoiceItemDescription(array $invoice)
{
$desc = '';
if (sizeof($invoice['lines']) > 0) {
$desc = $invoice['lines'][0]['description'];
for ($i=1; $i < sizeof($invoice['lines']); $i++) {
$desc .= ", " . $invoice['lines'][$i]['description'];
}
}
return substr($desc, 0, 10000);
}
/**
* @see https://devzone.paylane.com/secure-form-guide/implementation/
*/
public function getOneTimePaymentFields(array $invoice)
{
$data = array();
$data['amount'] = $this->moneyFormat($invoice['total'], $invoice['currency']); // Regular subscription price.
$data['currency'] = $invoice['currency'];
$data['merchant_id'] = $this->config["merchant_id"];
$data['description'] = substr($invoice['title'], 0, 20);
$data['transaction_description'] = $this->getInvoiceItemDescription($invoice);
$data['transaction_type'] = "S";
$data['back_url'] = $this->config['notify_url'];
$data['language'] = "en";
$data['hash'] = $this->setHash($data);
}
public function getSubscriptionFields(array $invoice)
{
throw new Payment_Exception('Not implemented yet');
}
/**
* @param string $url
*/
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 PayLane" 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 PayLane.com'));
$form .= "<script type='text/javascript'>$(document).ready(function(){ document.getElementById('payment_button').style.display = 'none'; document.forms['payment_form'].submit();});</script>";
}
return $form;
}
private function setHash($data)
{
$array = array(
$this->config["salt"],
$data['description'],
$data['amount'],
$data['currency'],
"S"
);
$string = implode("|", $array);
return SHA1($string);
}
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 serviceUrl()
{
return 'https://secure.paylane.com/order/cart.html';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment