Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
denisdulici committed Mar 4, 2021
0 parents commit 0dd3914
Show file tree
Hide file tree
Showing 31 changed files with 942 additions and 0 deletions.
50 changes: 50 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Tests

on:
schedule:
- cron: '0 0 * * 0'
workflow_dispatch:

jobs:
tests:

name: PHP ${{ matrix.php }}

runs-on: ubuntu-latest

strategy:
matrix:
php: ['7.3', '7.4']

steps:
- name: Checkout Akaunting
uses: actions/checkout@v2
with:
repository: akaunting/akaunting

- name: Checkout Paypal Standard module
uses: actions/checkout@v2
with:
path: modules/PaypalStandard

- name: Cache Composer
uses: actions/cache@v1
with:
path: ~/.composer/cache/files
key: php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: bcmath, ctype, dom, fileinfo, intl, gd, json, mbstring, pdo, pdo_sqlite, openssl, sqlite, xml, zip
coverage: none

- name: Copy .env
run: cp .env.testing .env

- name: Install Composer
run: cd modules/PaypalStandard ; composer test ; cd ../.. ; composer test

- name: Execute tests
run: php artisan test --parallel
37 changes: 37 additions & 0 deletions .github/workflows/translations.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Translations

on:
schedule:
- cron: '0 0 * * 0'
workflow_dispatch:

jobs:
sync:
name: Sync

runs-on: ubuntu-latest

steps:

- name: Checkout
uses: actions/checkout@v2

- name: Sync with Crowdin
uses: crowdin/github-action@master
with:
upload_sources: true
upload_translations: true
download_translations: true
skip_untranslated_files: true

localization_branch_name: 'translations'
commit_message: 'new crowdin translations'
pull_request_title: 'New Crowdin translations'
pull_request_body: 'https://crowdin.com/project/akaunting-apps'
pull_request_labels: 'Translation'

config: 'crowdin.yml'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_APPS_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/.idea
/.history
/.vscode
/.vagrant
/node_modules
/storage/*.key
/vendor
145 changes: 145 additions & 0 deletions Http/Controllers/Payment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<?php

namespace Modules\PaypalStandard\Http\Controllers;

use App\Abstracts\Http\PaymentController;
use App\Events\Document\PaymentReceived;
use App\Http\Requests\Portal\InvoicePayment as PaymentRequest;
use App\Models\Document\Document;
use GuzzleHttp\Client;
use Illuminate\Http\Request;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;

class Payment extends PaymentController
{
public $alias = 'paypal-standard';

public $type = 'redirect';

public function show(Document $invoice, PaymentRequest $request)
{
$setting = $this->setting;

$this->setContactFirstLastName($invoice);

$setting['action'] = ($setting['mode'] == 'live') ? 'https://www.paypal.com/cgi-bin/webscr' : 'https://www.sandbox.paypal.com/cgi-bin/webscr';

$invoice_url = $this->getInvoiceUrl($invoice);

$html = view('paypal-standard::show', compact('setting', 'invoice', 'invoice_url'))->render();

return response()->json([
'code' => $setting['code'],
'name' => $setting['name'],
'description' => trans('paypal-standard::general.description'),
'redirect' => false,
'html' => $html,
]);
}

public function return(Document $invoice, Request $request)
{
$success = true;

switch ($request['payment_status']) {
case 'Completed':
$message = trans('messages.success.added', ['type' => trans_choice('general.payments', 1)]);
break;
case 'Canceled_Reversal':
case 'Denied':
case 'Expired':
case 'Failed':
case 'Pending':
case 'Processed':
case 'Refunded':
case 'Reversed':
case 'Voided':
$message = trans('messages.error.added', ['type' => trans_choice('general.payments', 1)]);
$success = false;
break;
}

if ($success) {
flash($message)->success();
} else {
flash($message)->warning();
}

$invoice_url = $this->getInvoiceUrl($invoice);

return redirect($invoice_url);
}

public function complete(Document $invoice, Request $request)
{
$setting = $this->setting;

$paypal_log = new Logger('Paypal');

$paypal_log->pushHandler(new StreamHandler(storage_path('logs/paypal.log')), Logger::INFO);

if (!$invoice) {
return;
}

$url = ($setting['mode'] == 'live') ? 'https://ipnpb.paypal.com/cgi-bin/webscr' : 'https://www.sandbox.paypal.com/cgi-bin/webscr';

$client = new Client(['verify' => false]);

$paypal_request['cmd'] = '_notify-validate';

foreach ($request->toArray() as $key => $value) {
$paypal_request[$key] = urlencode(html_entity_decode($value, ENT_QUOTES, 'UTF-8'));
}

$response = $client->post($url, $paypal_request);

if ($response->getStatusCode() != 200) {
$paypal_log->info('PAYPAL_STANDARD :: CURL failed ', $response->getBody()->getContents());
} else {
$response = $response->getBody()->getContents();
}

if ($setting['debug']) {
$paypal_log->info('PAYPAL_STANDARD :: IPN REQUEST: ', $request->toArray());
}

if ((strcmp($response, 'VERIFIED') != 0 || strcmp($response, 'UNVERIFIED') != 0)) {
$paypal_log->info('PAYPAL_STANDARD :: VERIFIED != 0 || UNVERIFIED != 0 ' . $request->toArray());

return;
}

switch ($request['payment_status']) {
case 'Completed':
$receiver_match = (strtolower($request['receiver_email']) == strtolower($setting['email']));

$total_paid_match = ((double) $request['mc_gross'] == $invoice->amount);

if ($receiver_match && $total_paid_match) {
event(new PaymentReceived($invoice, $request->merge(['type' => 'income'])));
}

if (!$receiver_match) {
$paypal_log->info('PAYPAL_STANDARD :: RECEIVER EMAIL MISMATCH! ' . strtolower($request['receiver_email']));
}

if (!$total_paid_match) {
$paypal_log->info('PAYPAL_STANDARD :: TOTAL PAID MISMATCH! ' . $request['mc_gross']);
}
break;
case 'Canceled_Reversal':
case 'Denied':
case 'Expired':
case 'Failed':
case 'Pending':
case 'Processed':
case 'Refunded':
case 'Reversed':
case 'Voided':
$paypal_log->info('PAYPAL_STANDARD :: NOT COMPLETED ' . $request->toArray());
break;
}
}
}
19 changes: 19 additions & 0 deletions Listeners/AddLandingPage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Modules\PaypalStandard\Listeners;

use App\Events\Auth\LandingPageShowing as Event;

class AddLandingPage
{
/**
* Handle the event.
*
* @param Event $event
* @return void
*/
public function handle(Event $event)
{
$event->user->landing_pages['paypal-standard.settings.edit'] = trans('paypal-standard::general.name');
}
}
23 changes: 23 additions & 0 deletions Listeners/ShowAsPaymentMethod.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Modules\PaypalStandard\Listeners;

use App\Events\Module\PaymentMethodShowing as Event;

class ShowAsPaymentMethod
{
/**
* Handle the event.
*
* @param Event $event
* @return void
*/
public function handle(Event $event)
{
$method = setting('paypal-standard');

$method['code'] = 'paypal-standard';

$event->modules->payment_methods[] = $method;
}
}
30 changes: 30 additions & 0 deletions Providers/Event.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Modules\PaypalStandard\Providers;

use Illuminate\Foundation\Support\Providers\EventServiceProvider as Provider;

class Event extends Provider
{
/**
* Determine if events and listeners should be automatically discovered.
*
* @return bool
*/
public function shouldDiscoverEvents()
{
return true;
}

/**
* Get the listener directories that should be used to discover events.
*
* @return array
*/
protected function discoverEventsWithin()
{
return [
__DIR__ . '/../Listeners',
];
}
}
Loading

0 comments on commit 0dd3914

Please sign in to comment.