1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-10 05:02:36 +01:00
This commit is contained in:
David Bomba 2021-07-22 11:30:16 +10:00
parent c6ed151813
commit b5697966b5
12 changed files with 468 additions and 8 deletions

View File

@ -81,6 +81,9 @@ class Gateway extends StaticModel
case 1:
return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true]];//Authorize.net
break;
case 3:
return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true]];//eWay
break;
case 15:
return [GatewayType::PAYPAL => ['refund' => true, 'token_billing' => false]]; //Paypal
break;

View File

@ -0,0 +1,58 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\PaymentDrivers\Eway;
use App\Exceptions\PaymentFailed;
use App\Jobs\Mail\PaymentFailureMailer;
use App\Jobs\Util\SystemLogger;
use App\Models\ClientGatewayToken;
use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentHash;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\PaymentDrivers\EwayPaymentDriver;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
class CreditCard
{
public $eway;
public function __construct(EwayPaymentDriver $eway)
{
$this->eway = $eway;
}
public function authorizeView($data)
{
}
public function authorizeRequest($request)
{
}
public function paymentView($data)
{
}
public function processPaymentResponse($request)
{
}
}

View File

@ -0,0 +1,104 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\PaymentDrivers;
use App\Http\Requests\Payments\PaymentWebhookRequest;
use App\Models\ClientGatewayToken;
use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentHash;
use App\Models\SystemLog;
use App\PaymentDrivers\Eway\CreditCard;
use App\Utils\Traits\MakesHash;
class EwayPaymentDriver extends BaseDriver
{
use MakesHash;
public $refundable = true; //does this gateway support refunds?
public $token_billing = true; //does this gateway support token billing?
public $can_authorise_credit_card = true; //does this gateway support authorizations?
public $eway; //initialized gateway
public $payment_method; //initialized payment method
public static $methods = [
GatewayType::CREDIT_CARD => CreditCard::class, //maps GatewayType => Implementation class
];
const SYSTEM_LOG_TYPE = SystemLog::TYPE_STRIPE; //define a constant for your gateway ie TYPE_YOUR_CUSTOM_GATEWAY - set the const in the SystemLog model
public function init()
{
$apiKey = $this->company_gateway->getConfigField('apiKey');
$password = $this->company_gateway->getConfigField('password');
$apiEndpoint = $this->company_gateway->getConfigField('testMode') ? \Eway\Rapid\Client::MODE_SANDBOX : \Eway\Rapid\Client::MODE_PRODUCTION;
$this->eway = \Eway\Rapid::createClient($apiKey, $apiPassword, $apiEndpoint);
return $this;
}
/* Returns an array of gateway types for the payment gateway */
public function gatewayTypes(): array
{
$types = [];
$types[] = GatewayType::CREDIT_CARD;
return $types;
}
/* Sets the payment method initialized */
public function setPaymentMethod($payment_method_id)
{
$class = self::$methods[$payment_method_id];
$this->payment_method = new $class($this);
return $this;
}
public function authorizeView(array $data)
{
return $this->payment_method->authorizeView($data); //this is your custom implementation from here
}
public function authorizeResponse($request)
{
return $this->payment_method->authorizeResponse($request); //this is your custom implementation from here
}
public function processPaymentView(array $data)
{
return $this->payment_method->paymentView($data); //this is your custom implementation from here
}
public function processPaymentResponse($request)
{
return $this->payment_method->paymentResponse($request); //this is your custom implementation from here
}
public function refund(Payment $payment, $amount, $return_client_response = false)
{
return $this->payment_method->yourRefundImplementationHere(); //this is your custom implementation from here
}
public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash)
{
return $this->payment_method->yourTokenBillingImplmentation(); //this is your custom implementation from here
}
public function processWebhookRequest(PaymentWebhookRequest $request, Payment $payment = null)
{
}
}

View File

@ -0,0 +1,72 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\PaymentDrivers\Eway;
use App\Exceptions\PaymentFailed;
use App\Jobs\Mail\PaymentFailureMailer;
use App\Jobs\Util\SystemLogger;
use App\Models\ClientGatewayToken;
use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentHash;
use App\Models\PaymentType;
use App\Models\SystemLog;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
class CreditCard
{
public $driver_class;
public function __construct(PaymentDriver $driver_class)
{
$this->driver_class = $driver_class;
}
public function authorizeView($data)
{
}
public function authorizeRequest($request)
{
}
public function paymentView($data)
{
}
public function processPaymentResponse($request)
{
}
/* Helpers */
/*
You will need some helpers to handle successful and unsuccessful responses
Some considerations after a succesful transaction include:
Logging of events: success +/- failure
Recording a payment
Notifications
*/
}

View File

@ -17,10 +17,9 @@ use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentHash;
use App\Models\SystemLog;
use App\PaymentDrivers\Stripe\CreditCard;
use App\Utils\Traits\MakesHash;
class DriverTemplate extends BaseDriver
class PaymentDriver extends BaseDriver
{
use MakesHash;
@ -85,12 +84,12 @@ class DriverTemplate extends BaseDriver
public function refund(Payment $payment, $amount, $return_client_response = false)
{
return $this->payment_method->yourRefundImplementationHere(); //this is your custom implementation from here
//this is your custom implementation from here
}
public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash)
{
return $this->payment_method->yourTokenBillingImplmentation(); //this is your custom implementation from here
//this is your custom implementation from here
}
public function processWebhookRequest(PaymentWebhookRequest $request, Payment $payment = null)

View File

@ -0,0 +1,34 @@
@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.credit_card'), 'card_title' => ctrans('texts.credit_card')])
@section('gateway_head')
@endsection
@section('gateway_content')
<form action="{{ $payment_endpoint_url }}" method="post" id="server_response">
@if(!Request::isSecure())
<p class="alert alert-failure">{{ ctrans('texts.https_required') }}</p>
@endif
<div class="alert alert-failure mb-4" hidden id="errors"></div>
<!-- This is a generic credit card component utilizing CardJS -->
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.method')])
{{ ctrans('texts.credit_card') }}
@endcomponent
<div class="bg-white px-4 py-5 flex justify-end">
<button
type="submit"
id="{{ $id ?? 'pay-now' }}"
class="button button-primary bg-primary {{ $class ?? '' }}">
<span>{{ ctrans('texts.add_payment_method') }}</span>
</button>
</div>
</form>
@endsection
@section('gateway_footer')
<!-- Your JS includes go here -->
@endsection

View File

@ -0,0 +1,64 @@
@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.credit_card'), 'card_title' => ctrans('texts.credit_card')])
@section('gateway_head')
@endsection
@section('gateway_content')
<form action="{{ $payment_endpoint_url }}" method="post" id="server_response">
<div class="alert alert-failure mb-4" hidden id="errors"></div>
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.method')])
{{ ctrans('texts.credit_card') }}
@endcomponent
@include('portal.ninja2020.gateways.includes.payment_details')
<-- If there are existing tokens available these are displayed here for you -->
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.pay_with')])
@if(count($tokens) > 0)
@foreach($tokens as $token)
<label class="mr-4">
<input
type="radio"
data-token="{{ $token->token }}"
name="payment-type"
class="form-radio cursor-pointer toggle-payment-with-token"/>
<span class="ml-1 cursor-pointer">**** {{ optional($token->meta)->last4 }}</span>
</label>
@endforeach
@endisset
<label>
<input
type="radio"
id="toggle-payment-with-credit-card"
class="form-radio cursor-pointer"
name="payment-type"
checked/>
<span class="ml-1 cursor-pointer">{{ __('texts.new_card') }}</span>
</label>
@endcomponent
<!-- This include gives the options to save the payment method -->
@include('portal.ninja2020.gateways.includes.save_card')
<!-- This include pops up a credit card form -->
@include('portal.ninja2020.gateways.wepay.includes.credit_card')
@include('portal.ninja2020.gateways.includes.pay_now')
</form>
@endsection
@section('gateway_footer')
<script>
document.getElementById('pay-now').addEventListener('click', function() {
document.getElementById('server_response').submit();
});
</script>
@endsection

View File

@ -41,6 +41,7 @@
"codedge/laravel-selfupdater": "^3.2",
"composer/composer": "^2",
"doctrine/dbal": "^2.10",
"eway/eway-rapid-php": "^1.3",
"fakerphp/faker": "^1.14",
"fideloper/proxy": "^4.2",
"fruitcake/laravel-cors": "^2.0",

60
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "d2beb37ff5fbee59ad4bb792e944eb10",
"content-hash": "c9f7d76428c6f556ae531570b7761bf5",
"packages": [
{
"name": "asm/php-ansible",
@ -1964,6 +1964,62 @@
],
"time": "2020-12-29T14:50:06+00:00"
},
{
"name": "eway/eway-rapid-php",
"version": "v1.3.4",
"source": {
"type": "git",
"url": "https://github.com/eWAYPayment/eway-rapid-php.git",
"reference": "5b765d83ef69e1783f391ae85aed48d47dd5f8eb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/eWAYPayment/eway-rapid-php/zipball/5b765d83ef69e1783f391ae85aed48d47dd5f8eb",
"reference": "5b765d83ef69e1783f391ae85aed48d47dd5f8eb",
"shasum": ""
},
"require": {
"ext-curl": "*",
"ext-json": "*",
"php": ">=5.4.0"
},
"require-dev": {
"internations/http-mock": "~0.7",
"jeremeamia/superclosure": "1.0.2",
"phpdocumentor/phpdocumentor": "~2.8",
"phpunit/phpunit": "4.8.*",
"squizlabs/php_codesniffer": "2.*"
},
"type": "library",
"autoload": {
"psr-4": {
"Eway\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "eWAY",
"homepage": "https://www.eway.com.au"
}
],
"description": "eWAY Rapid PHP library",
"homepage": "https://www.eway.com.au",
"keywords": [
"eway",
"payment processing",
"payments",
"rapid"
],
"support": {
"issues": "https://github.com/eWAYPayment/eway-rapid-php/issues",
"source": "https://github.com/eWAYPayment/eway-rapid-php/tree/master"
},
"time": "2016-09-12T05:46:41+00:00"
},
{
"name": "fakerphp/faker",
"version": "v1.15.0",
@ -14881,5 +14937,5 @@
"platform-dev": {
"php": "^7.3|^7.4|^8.0"
},
"plugin-api-version": "2.1.0"
"plugin-api-version": "2.0.0"
}

View File

@ -0,0 +1,35 @@
<?php
use App\Models\Gateway;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class ActivateEwayPaymentDriver extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
if($eway = Gateway::find(3))
{
$eway->visible = true;
$eway->provider = 'Eway';
$eway->save();
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@ -27,7 +27,7 @@ class PaymentLibrariesSeeder extends Seeder
'],
['id' => 2, 'name' => 'CardSave', 'provider' => 'CardSave', 'key' => '46c5c1fed2c43acf4f379bae9c8b9f76', 'fields' => '{"merchantId":"","password":""}
'],
['id' => 3, 'name' => 'Eway Rapid', 'provider' => 'Eway_RapidShared', 'is_offsite' => true, 'key' => '944c20175bbe6b9972c05bcfe294c2c7', 'fields' => '{"apiKey":"","password":"","testMode":false}'],
['id' => 3, 'name' => 'Eway Rapid', 'provider' => 'Eway', 'is_offsite' => true, 'key' => '944c20175bbe6b9972c05bcfe294c2c7', 'fields' => '{"apiKey":"","password":"","testMode":false}'],
['id' => 4, 'name' => 'FirstData Connect', 'provider' => 'FirstData_Connect', 'key' => '4e0ed0d34552e6cb433506d1ac03a418', 'fields' => '{"storeId":"","sharedSecret":"","testMode":false}'],
['id' => 5, 'name' => 'Migs ThreeParty', 'provider' => 'Migs_ThreeParty', 'key' => '513cdc81444c87c4b07258bc2858d3fa', 'fields' => '{"merchantId":"","merchantAccessCode":"","secureHash":""}'],
['id' => 6, 'name' => 'Migs TwoParty', 'provider' => 'Migs_TwoParty', 'key' => '99c2a271b5088951334d1302e038c01a', 'fields' => '{"merchantId":"","merchantAccessCode":"","secureHash":""}'],
@ -96,7 +96,7 @@ class PaymentLibrariesSeeder extends Seeder
Gateway::query()->update(['visible' => 0]);
Gateway::whereIn('id', [1,15,20,39,55,50])->update(['visible' => 1]);
Gateway::whereIn('id', [1,3,15,20,39,55,50])->update(['visible' => 1]);
if (Ninja::isHosted()) {
Gateway::whereIn('id', [20])->update(['visible' => 0]);

View File

@ -0,0 +1,34 @@
@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.credit_card'), 'card_title' => ctrans('texts.credit_card')])
@section('gateway_head')
@endsection
@section('gateway_content')
<form action="{{ $payment_endpoint_url }}" method="post" id="server_response">
@if(!Request::isSecure())
<p class="alert alert-failure">{{ ctrans('texts.https_required') }}</p>
@endif
<div class="alert alert-failure mb-4" hidden id="errors"></div>
<!-- This is a generic credit card component utilizing CardJS -->
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.method')])
{{ ctrans('texts.credit_card') }}
@endcomponent
<div class="bg-white px-4 py-5 flex justify-end">
<button
type="submit"
id="{{ $id ?? 'pay-now' }}"
class="button button-primary bg-primary {{ $class ?? '' }}">
<span>{{ ctrans('texts.add_payment_method') }}</span>
</button>
</div>
</form>
@endsection
@section('gateway_footer')
<!-- Your JS includes go here -->
@endsection