1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-17 16:42:48 +01:00

Support for custom gateway

This commit is contained in:
Hillel Coren 2016-09-26 12:33:30 +03:00
parent 078527443f
commit 6088a36175
14 changed files with 145 additions and 33 deletions

View File

@ -48,8 +48,10 @@ class AccountGatewayController extends BaseController
$accountGateway = AccountGateway::scope($publicId)->firstOrFail();
$config = $accountGateway->getConfig();
foreach ($config as $field => $value) {
$config->$field = str_repeat('*', strlen($value));
if ($accountGateway->gateway_id != GATEWAY_CUSTOM) {
foreach ($config as $field => $value) {
$config->$field = str_repeat('*', strlen($value));
}
}
$data = self::getViewModel($accountGateway);
@ -100,7 +102,7 @@ class AccountGatewayController extends BaseController
if ($otherProviders) {
$availableGatewaysIds = $account->availableGatewaysIds();
$data['primaryGateways'] = Gateway::primary($availableGatewaysIds)->orderBy('name', 'desc')->get();
$data['primaryGateways'] = Gateway::primary($availableGatewaysIds)->orderBy('sort_order')->get();
$data['secondaryGateways'] = Gateway::secondary($availableGatewaysIds)->orderBy('name')->get();
$data['hiddenFields'] = Gateway::$hiddenFields;
@ -132,7 +134,9 @@ class AccountGatewayController extends BaseController
foreach ($gateways as $gateway) {
$fields = $gateway->getFields();
asort($fields);
if ( ! $gateway->isCustom()) {
asort($fields);
}
$gateway->fields = $gateway->id == GATEWAY_WEPAY ? [] : $fields;
if ($accountGateway && $accountGateway->gateway_id == $gateway->id) {
$accountGateway->fields = $gateway->fields;
@ -247,6 +251,8 @@ class AccountGatewayController extends BaseController
}
if (!$value && ($field == 'testMode' || $field == 'developerMode')) {
// do nothing
} elseif ($gatewayId == GATEWAY_CUSTOM && $field == 'text') {
$config->$field = strip_tags($value);
} else {
$config->$field = $value;
}

View File

@ -104,7 +104,9 @@ class ClientPortalController extends BaseController
$paymentURL = '';
if (count($paymentTypes) == 1) {
$paymentURL = $paymentTypes[0]['url'];
if (!$account->isGatewayConfigured(GATEWAY_PAYPAL_EXPRESS)) {
if ($paymentTypes[0]['gatewayTypeId'] == GATEWAY_TYPE_CUSTOM) {
// do nothing
} elseif (!$account->isGatewayConfigured(GATEWAY_PAYPAL_EXPRESS)) {
$paymentURL = URL::to($paymentURL);
}
}
@ -143,7 +145,12 @@ class ClientPortalController extends BaseController
];
}
if ($accountGateway = $account->getGatewayByType(GATEWAY_TYPE_CUSTOM)) {
$data += [
'customGatewayName' => $accountGateway->getConfigField('name'),
'customGatewayText' => $accountGateway->getConfigField('text'),
];
}
if($account->hasFeature(FEATURE_DOCUMENTS) && $this->canCreateZip()){
$zipDocs = $this->getInvoiceZipDocuments($invoice, $size);

View File

@ -605,6 +605,7 @@ if (!defined('CONTACT_EMAIL')) {
define('GATEWAY_CYBERSOURCE', 49);
define('GATEWAY_WEPAY', 60);
define('GATEWAY_BRAINTREE', 61);
define('GATEWAY_CUSTOM', 62);
// The customer exists, but only as a local concept
// The remote gateway doesn't understand the concept of customers
@ -713,6 +714,7 @@ if (!defined('CONTACT_EMAIL')) {
define('GATEWAY_TYPE_PAYPAL', 3);
define('GATEWAY_TYPE_BITCOIN', 4);
define('GATEWAY_TYPE_DWOLLA', 5);
define('GATEWAY_TYPE_CUSTOM', 6);
define('GATEWAY_TYPE_TOKEN', 'token');
define('REMINDER1', 'reminder1');

View File

@ -14,6 +14,12 @@ class Gateway extends Eloquent
*/
public $timestamps = true;
protected $fillable = [
'provider',
'is_offsite',
'sort_order',
];
/**
* @var array
*/
@ -39,6 +45,7 @@ class Gateway extends Eloquent
GATEWAY_BRAINTREE,
GATEWAY_AUTHORIZE_NET,
GATEWAY_MOLLIE,
GATEWAY_CUSTOM,
];
// allow adding these gateway if another gateway
@ -174,6 +181,18 @@ class Gateway extends Eloquent
*/
public function getFields()
{
return Omnipay::create($this->provider)->getDefaultParameters();
if ($this->isCustom()) {
return [
'name' => '',
'text' => '',
];
} else {
return Omnipay::create($this->provider)->getDefaultParameters();
}
}
public function isCustom()
{
return $this->id === GATEWAY_CUSTOM;
}
}

View File

@ -10,6 +10,8 @@ use App\Models\AccountGateway;
class AccountGatewayDatatable extends EntityDatatable
{
private static $accountGateways;
public $entityType = ENTITY_ACCOUNT_GATEWAY;
public function columns()
@ -20,10 +22,14 @@ class AccountGatewayDatatable extends EntityDatatable
function ($model) {
if ($model->deleted_at) {
return $model->name;
} elseif ($model->gateway_id == GATEWAY_CUSTOM) {
$accountGateway = $this->getAccountGateway($model->id);
$name = $accountGateway->getConfigField('name') . ' [' . trans('texts.custom') . ']';
return link_to("gateways/{$model->public_id}/edit", $name)->toHtml();
} elseif ($model->gateway_id != GATEWAY_WEPAY) {
return link_to("gateways/{$model->public_id}/edit", $model->name)->toHtml();
} else {
$accountGateway = AccountGateway::find($model->id);
$accountGateway = $this->getAccountGateway($model->id);
$config = $accountGateway->getConfig();
$endpoint = WEPAY_ENVIRONMENT == WEPAY_STAGE ? 'https://stage.wepay.com/' : 'https://www.wepay.com/';
$wepayAccountId = $config->accountId;
@ -53,10 +59,14 @@ class AccountGatewayDatatable extends EntityDatatable
[
'limit',
function ($model) {
$accountGateway = AccountGateway::find($model->id);
$paymentDriver = $accountGateway->paymentDriver();
$gatewayTypes = $paymentDriver->gatewayTypes();
$gatewayTypes = array_diff($gatewayTypes, array(GATEWAY_TYPE_TOKEN));
if ($model->gateway_id == GATEWAY_CUSTOM) {
$gatewayTypes = [GATEWAY_TYPE_CUSTOM];
} else {
$accountGateway = $this->getAccountGateway($model->id);
$paymentDriver = $accountGateway->paymentDriver();
$gatewayTypes = $paymentDriver->gatewayTypes();
$gatewayTypes = array_diff($gatewayTypes, array(GATEWAY_TYPE_TOKEN));
}
$html = '';
foreach ($gatewayTypes as $gatewayTypeId) {
@ -123,7 +133,7 @@ class AccountGatewayDatatable extends EntityDatatable
], [
uctrans('texts.manage_account'),
function ($model) {
$accountGateway = AccountGateway::find($model->id);
$accountGateway = $this->getAccountGateway($model->id);
$endpoint = WEPAY_ENVIRONMENT == WEPAY_STAGE ? 'https://stage.wepay.com/' : 'https://www.wepay.com/';
return [
'url' => $endpoint.'account/'.$accountGateway->getConfig()->accountId,
@ -148,20 +158,25 @@ class AccountGatewayDatatable extends EntityDatatable
$actions[] = [
trans('texts.set_limits', ['gateway_type' => $gatewayType->name]),
function () use ($gatewayType) {
$accountGatewaySettings = AccountGatewaySettings::scope()->where('account_gateway_settings.gateway_type_id',
'=', $gatewayType->id)->first();
$accountGatewaySettings = AccountGatewaySettings::scope()
->where('account_gateway_settings.gateway_type_id', '=', $gatewayType->id)
->first();
$min = $accountGatewaySettings && $accountGatewaySettings->min_limit !== null ? $accountGatewaySettings->min_limit : 'null';
$max = $accountGatewaySettings && $accountGatewaySettings->max_limit !== null ? $accountGatewaySettings->max_limit : 'null';
return "javascript:showLimitsModal('{$gatewayType->name}',{$gatewayType->id},$min,$max)";
return "javascript:showLimitsModal('{$gatewayType->name}', {$gatewayType->id}, $min, $max)";
},
function ($model) use ($gatewayType) {
// Only show this action if the given gateway supports this gateway type
$accountGateway = AccountGateway::find($model->id);
$paymentDriver = $accountGateway->paymentDriver();
$gatewayTypes = $paymentDriver->gatewayTypes();
if ($model->gateway_id == GATEWAY_CUSTOM) {
return $gatewayType->id == GATEWAY_TYPE_CUSTOM;
} else {
$accountGateway = $this->getAccountGateway($model->id);
$paymentDriver = $accountGateway->paymentDriver();
$gatewayTypes = $paymentDriver->gatewayTypes();
return in_array($gatewayType->id, $gatewayTypes);
return in_array($gatewayType->id, $gatewayTypes);
}
}
];
}
@ -169,4 +184,15 @@ class AccountGatewayDatatable extends EntityDatatable
return $actions;
}
private function getAccountGateway($id)
{
if (isset(static::$accountGateways[$id])) {
return static::$accountGateways[$id];
}
static::$accountGateways[$id] = AccountGateway::find($id);
return static::$accountGateways[$id];
}
}

View File

@ -818,9 +818,18 @@ class BasePaymentDriver
$gatewayTypeAlias = GatewayType::getAliasFromId($gatewayTypeId);
if ($gatewayTypeId == GATEWAY_TYPE_CUSTOM) {
$url = "javascript:showCustomModal();";
$label = $this->accountGateway->getConfigField('name');
} else {
$url = $this->paymentUrl($gatewayTypeAlias);
$label = trans("texts.{$gatewayTypeAlias}");
}
$links[] = [
'url' => $this->paymentUrl($gatewayTypeAlias),
'label' => trans("texts.{$gatewayTypeAlias}")
'gatewayTypeId' => $gatewayTypeId,
'url' => $url,
'label' => $label,
];
}

View File

@ -0,0 +1,12 @@
<?php namespace App\Ninja\PaymentDrivers;
class CustomPaymentDriver extends BasePaymentDriver
{
public function gatewayTypes()
{
return [
GATEWAY_TYPE_CUSTOM
];
}
}

View File

@ -60,6 +60,7 @@ class CurrenciesSeeder extends Seeder
['name' => 'Pakistani Rupee', 'code' => 'PKR', 'symbol' => 'Rs ', 'precision' => '0', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Polish Zloty', 'code' => 'PLN', 'symbol' => 'zł', 'precision' => '2', 'thousand_separator' => ' ', 'decimal_separator' => ',', 'swap_currency_symbol' => true],
['name' => 'Sri Lankan Rupee', 'code' => 'LKR', 'symbol' => 'LKR', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.', 'swap_currency_symbol' => true],
//['name' => 'Bahraini Dinar', 'code' => 'BHD', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
];
foreach ($currencies as $currency) {

View File

@ -15,6 +15,7 @@ class GatewayTypesSeeder extends Seeder
['alias' => 'paypal', 'name' => 'PayPal'],
['alias' => 'bitcoin', 'name' => 'Bitcoin'],
['alias' => 'dwolla', 'name' => 'Dwolla'],
['alias' => 'custom', 'name' => 'Custom'],
];
foreach ($gateway_types as $gateway_type) {

View File

@ -15,7 +15,7 @@ class PaymentLibrariesSeeder extends Seeder
Eloquent::unguard();
$gateways = [
['name' => 'Authorize.Net AIM', 'provider' => 'AuthorizeNet_AIM'],
['name' => 'Authorize.Net AIM', 'provider' => 'AuthorizeNet_AIM', 'sort_order' => 3],
['name' => 'Authorize.Net SIM', 'provider' => 'AuthorizeNet_SIM', 'payment_library_id' => 2],
['name' => 'CardSave', 'provider' => 'CardSave'],
['name' => 'Eway Rapid', 'provider' => 'Eway_RapidShared', 'is_offsite' => true],
@ -23,7 +23,7 @@ class PaymentLibrariesSeeder extends Seeder
['name' => 'GoCardless', 'provider' => 'GoCardless', 'is_offsite' => true],
['name' => 'Migs ThreeParty', 'provider' => 'Migs_ThreeParty'],
['name' => 'Migs TwoParty', 'provider' => 'Migs_TwoParty'],
['name' => 'Mollie', 'provider' => 'Mollie', 'is_offsite' => true],
['name' => 'Mollie', 'provider' => 'Mollie', 'is_offsite' => true, 'sort_order' => 6],
['name' => 'MultiSafepay', 'provider' => 'MultiSafepay'],
['name' => 'Netaxept', 'provider' => 'Netaxept'],
['name' => 'NetBanx', 'provider' => 'NetBanx'],
@ -37,7 +37,7 @@ class PaymentLibrariesSeeder extends Seeder
['name' => 'SagePay Direct', 'provider' => 'SagePay_Direct'],
['name' => 'SagePay Server', 'provider' => 'SagePay_Server'],
['name' => 'SecurePay DirectPost', 'provider' => 'SecurePay_DirectPost'],
['name' => 'Stripe', 'provider' => 'Stripe'],
['name' => 'Stripe', 'provider' => 'Stripe', 'sort_order' => 1],
['name' => 'TargetPay Direct eBanking', 'provider' => 'TargetPay_Directebanking'],
['name' => 'TargetPay Ideal', 'provider' => 'TargetPay_Ideal'],
['name' => 'TargetPay Mr Cash', 'provider' => 'TargetPay_Mrcash'],
@ -56,8 +56,8 @@ class PaymentLibrariesSeeder extends Seeder
['name' => 'Realex', 'provider' => 'Realex_Remote'],
['name' => 'Sisow', 'provider' => 'Sisow'],
['name' => 'Skrill', 'provider' => 'Skrill'],
['name' => 'BitPay', 'provider' => 'BitPay', 'is_offsite' => true],
['name' => 'Dwolla', 'provider' => 'Dwolla', 'is_offsite' => true],
['name' => 'BitPay', 'provider' => 'BitPay', 'is_offsite' => true, 'sort_order' => 5],
['name' => 'Dwolla', 'provider' => 'Dwolla', 'is_offsite' => true, 'sort_order' => 4],
['name' => 'AGMS', 'provider' => 'Agms'],
['name' => 'Barclays', 'provider' => 'BarclaysEpdq\Essential'],
['name' => 'Cardgate', 'provider' => 'Cardgate'],
@ -75,14 +75,14 @@ class PaymentLibrariesSeeder extends Seeder
['name' => 'SecPay', 'provider' => 'SecPay'],
['name' => 'WeChat Express', 'provider' => 'WeChat_Express'],
['name' => 'WePay', 'provider' => 'WePay', 'is_offsite' => false],
['name' => 'Braintree', 'provider' => 'Braintree'],
['name' => 'Braintree', 'provider' => 'Braintree', 'sort_order' => 2],
['name' => 'Custom', 'provider' => 'Custom', 'is_offsite' => true, 'sort_order' => 7],
];
foreach ($gateways as $gateway) {
$record = Gateway::where('name', '=', $gateway['name'])->first();
if ($record) {
$record->provider = $gateway['provider'];
$record->is_offsite = isset($gateway['is_offsite']) ? boolval($gateway['is_offsite']) : false;
$record->fill($gateway);
$record->save();
} else {
Gateway::create($gateway);

View File

@ -2141,6 +2141,7 @@ $LANG = array(
'invoice_error' => 'There was an error saving your invoice.',
'enable_recurring' => 'Enable Recurring',
'disable_recurring' => 'Disable Recurring',
'text' => 'Text',
);

View File

@ -80,6 +80,8 @@
{!! Former::checkbox($gateway->id.'_'.$field)->label(ucwords(Utils::toSpaceCase($field)))->text('Enable')->value('true') !!}
@elseif ($field == 'username' || $field == 'password')
{!! Former::text($gateway->id.'_'.$field)->label('API '. ucfirst(Utils::toSpaceCase($field))) !!}
@elseif ($gateway->isCustom() && $field == 'text')
{!! Former::textarea($gateway->id.'_'.$field)->label(trans('texts.text'))->rows(6) !!}
@else
{!! Former::text($gateway->id.'_'.$field)->label($gateway->id == GATEWAY_STRIPE ? trans('texts.secret_key') : ucwords(Utils::toSpaceCase($field))) !!}
@endif

View File

@ -153,8 +153,8 @@
@if (count($account->account_gateways) > 1)
@foreach (\App\Models\Gateway::$gatewayTypes as $type)
@if ($account->getGatewayByType($type))
<li>${{ Utils::toCamelCase($type) }}Link</li>
<li>${{ Utils::toCamelCase($type) }}Button</li>
<li>${{ Utils::toCamelCase(\App\Models\GatewayType::getAliasFromId($type)) }}Link</li>
<li>${{ Utils::toCamelCase(\App\Models\GatewayType::getAliasFromId($type)) }}Button</li>
@endif
@endforeach
@endif

View File

@ -109,7 +109,7 @@
{!! Button::normal(trans('texts.download_pdf'))->withAttributes(['onclick' => 'onDownloadClick()'])->large() !!}&nbsp;&nbsp;
@if (count($paymentTypes) > 1)
{!! DropdownButton::success(trans('texts.pay_now'))->withContents($paymentTypes)->large() !!}
@else
@elseif (count($paymentTypes) == 1)
<a href='{!! $paymentURL !!}' class="btn btn-success btn-lg">{{ trans('texts.pay_now') }}</a>
@endif
@else
@ -199,6 +199,10 @@
doc.save(fileName + '-' + invoice.invoice_number + '.pdf');
}
function showCustomModal() {
$('#customGatewayModal').modal('show');
}
</script>
@include('invoices.pdf', ['account' => $invoice->client->account, 'viewPDF' => true])
@ -206,4 +210,26 @@
<p>&nbsp;</p>
</div>
@if (isset($customGatewayName))
<div class="modal fade" id="customGatewayModal" tabindex="-1" role="dialog" aria-labelledby="customGatewayModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">{{ $customGatewayName }}</h4>
</div>
<div class="panel-body">
{!! nl2br(e($customGatewayText)) !!}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{ trans('texts.close') }}</button>
</div>
</div>
</div>
</div>
@endif
@stop