mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-01 06:34:35 -04:00
Merge PayPal PPCP
This commit is contained in:
commit
10b37b1a1b
@ -25,6 +25,7 @@ use App\Models\Account;
|
|||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use App\Models\Country;
|
use App\Models\Country;
|
||||||
use App\Models\Expense;
|
use App\Models\Expense;
|
||||||
|
use App\Models\Gateway;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
|
@ -194,21 +194,27 @@ class CompanyGatewayController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function store(StoreCompanyGatewayRequest $request)
|
public function store(StoreCompanyGatewayRequest $request)
|
||||||
{
|
{
|
||||||
$company_gateway = CompanyGatewayFactory::create(auth()->user()->company()->id, auth()->user()->id);
|
/** @var \App\Models\User $user */
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
$company_gateway = CompanyGatewayFactory::create($user->company()->id, $user->id);
|
||||||
$company_gateway->fill($request->all());
|
$company_gateway->fill($request->all());
|
||||||
$company_gateway->save();
|
$company_gateway->save();
|
||||||
|
|
||||||
/*Always ensure at least one fees and limits object is set per gateway*/
|
/*Always ensure at least one fees and limits object is set per gateway*/
|
||||||
if (! isset($company_gateway->fees_and_limits)) {
|
$gateway_types = $company_gateway->driver(new Client)->getAvailableMethods();
|
||||||
$gateway_types = $company_gateway->driver(new Client)->gatewayTypes();
|
|
||||||
|
$fees_and_limits = $company_gateway->fees_and_limits;
|
||||||
$fees_and_limits = new \stdClass;
|
|
||||||
$fees_and_limits->{$gateway_types[0]} = new FeesAndLimits;
|
foreach($gateway_types as $key => $gateway_type)
|
||||||
|
{
|
||||||
$company_gateway->fees_and_limits = $fees_and_limits;
|
if(!property_exists($fees_and_limits, $key))
|
||||||
$company_gateway->save();
|
$fees_and_limits->{$key} = new FeesAndLimits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$company_gateway->fees_and_limits = $fees_and_limits;
|
||||||
|
$company_gateway->save();
|
||||||
|
|
||||||
ApplePayDomain::dispatch($company_gateway, $company_gateway->company->db);
|
ApplePayDomain::dispatch($company_gateway, $company_gateway->company->db);
|
||||||
|
|
||||||
if (in_array($company_gateway->gateway_key, $this->stripe_keys)) {
|
if (in_array($company_gateway->gateway_key, $this->stripe_keys)) {
|
||||||
@ -381,10 +387,18 @@ class CompanyGatewayController extends BaseController
|
|||||||
{
|
{
|
||||||
$company_gateway->fill($request->all());
|
$company_gateway->fill($request->all());
|
||||||
|
|
||||||
if (! $request->has('fees_and_limits')) {
|
/*Always ensure at least one fees and limits object is set per gateway*/
|
||||||
$company_gateway->fees_and_limits = '';
|
$gateway_types = $company_gateway->driver(new Client)->getAvailableMethods();
|
||||||
|
|
||||||
|
$fees_and_limits = $company_gateway->fees_and_limits;
|
||||||
|
|
||||||
|
foreach($gateway_types as $key => $gateway_type) {
|
||||||
|
if(!property_exists($fees_and_limits, $key)) {
|
||||||
|
$fees_and_limits->{$key} = new FeesAndLimits;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$company_gateway->fees_and_limits = $fees_and_limits;
|
||||||
$company_gateway->save();
|
$company_gateway->save();
|
||||||
|
|
||||||
if($company_gateway->gateway_key == $this->checkout_key) {
|
if($company_gateway->gateway_key == $this->checkout_key) {
|
||||||
|
@ -42,7 +42,11 @@ class VendorReportController extends BaseController
|
|||||||
|
|
||||||
$hash = \Illuminate\Support\Str::uuid();
|
$hash = \Illuminate\Support\Str::uuid();
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
PreviewReport::dispatch($user->company(), $request->all(), VendorExport::class, $hash);
|
PreviewReport::dispatch($user->company(), $request->all(), VendorExport::class, $hash);
|
||||||
|
=======
|
||||||
|
$hash = \Illuminate\Support\Str::uuid()->toString();
|
||||||
|
>>>>>>> paypal_ppcp
|
||||||
|
|
||||||
return response()->json(['message' => $hash], 200);
|
return response()->json(['message' => $hash], 200);
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Requests\CompanyGateway;
|
namespace App\Http\Requests\CompanyGateway;
|
||||||
|
|
||||||
|
use App\DataMapper\FeesAndLimits;
|
||||||
use App\Http\Requests\Request;
|
use App\Http\Requests\Request;
|
||||||
use App\Http\ValidationRules\ValidCompanyGatewayFeesAndLimitsRule;
|
use App\Http\ValidationRules\ValidCompanyGatewayFeesAndLimitsRule;
|
||||||
use App\Models\Gateway;
|
use App\Models\Gateway;
|
||||||
@ -28,7 +29,10 @@ class StoreCompanyGatewayRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function authorize() : bool
|
public function authorize() : bool
|
||||||
{
|
{
|
||||||
return auth()->user()->isAdmin();
|
/** @var \App\Models\User $user */
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
return $user->isAdmin();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function rules()
|
public function rules()
|
||||||
@ -64,6 +68,7 @@ class StoreCompanyGatewayRequest extends Request
|
|||||||
if (isset($input['fees_and_limits'])) {
|
if (isset($input['fees_and_limits'])) {
|
||||||
$input['fees_and_limits'] = $this->cleanFeesAndLimits($input['fees_and_limits']);
|
$input['fees_and_limits'] = $this->cleanFeesAndLimits($input['fees_and_limits']);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->replace($input);
|
$this->replace($input);
|
||||||
|
@ -27,7 +27,10 @@ class UpdateCompanyGatewayRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function authorize()
|
public function authorize()
|
||||||
{
|
{
|
||||||
return auth()->user()->isAdmin();
|
/** @var \App\Models\User $user */
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
return $user->isAdmin();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function rules()
|
public function rules()
|
||||||
|
43
app/Listeners/LogRequestSending.php
Normal file
43
app/Listeners/LogRequestSending.php
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||||
|
use Illuminate\Foundation\Events\Dispatchable;
|
||||||
|
use Illuminate\Http\Client\Events\RequestSending;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class LogRequestSending
|
||||||
|
{
|
||||||
|
|
||||||
|
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the event listener.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(RequestSending $event)
|
||||||
|
{
|
||||||
|
nlog("Request");
|
||||||
|
nlog($event->request->headers());
|
||||||
|
nlog($event->request->url());
|
||||||
|
nlog(json_encode($event->request->headers()));
|
||||||
|
nlog($event->request->body());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
56
app/Listeners/LogResponseReceived.php
Normal file
56
app/Listeners/LogResponseReceived.php
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use App\Utils\Ninja;
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
|
use App\Mail\User\UserAdded;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use App\Jobs\Mail\NinjaMailerJob;
|
||||||
|
use Illuminate\Support\Facades\App;
|
||||||
|
use App\Jobs\Mail\NinjaMailerObject;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Events\Dispatchable;
|
||||||
|
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||||
|
use Illuminate\Http\Client\Events\ResponseReceived;
|
||||||
|
|
||||||
|
class LogResponseReceived
|
||||||
|
{
|
||||||
|
|
||||||
|
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the event listener.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(ResponseReceived $event)
|
||||||
|
{
|
||||||
|
nlog("Request");
|
||||||
|
nlog($event->request->headers());
|
||||||
|
nlog($event->request->url());
|
||||||
|
nlog(json_encode($event->request->headers()));
|
||||||
|
nlog($event->request->body());
|
||||||
|
|
||||||
|
nlog("Response");
|
||||||
|
nlog($event->response->headers());
|
||||||
|
nlog(json_encode($event->response->headers()));
|
||||||
|
nlog($event->response->body());
|
||||||
|
nlog($event->response->json());
|
||||||
|
}
|
||||||
|
}
|
@ -117,7 +117,6 @@ class CompanyGateway extends BaseModel
|
|||||||
16 => ['card' => 'images/credit_cards/Test-Discover-Icon.png', 'text' => 'Discover'],
|
16 => ['card' => 'images/credit_cards/Test-Discover-Icon.png', 'text' => 'Discover'],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
// const TYPE_PAYPAL = 300;
|
// const TYPE_PAYPAL = 300;
|
||||||
// const TYPE_STRIPE = 301;
|
// const TYPE_STRIPE = 301;
|
||||||
// const TYPE_LEDGER = 302;
|
// const TYPE_LEDGER = 302;
|
||||||
@ -132,6 +131,7 @@ class CompanyGateway extends BaseModel
|
|||||||
// const TYPE_MOLLIE = 312;
|
// const TYPE_MOLLIE = 312;
|
||||||
// const TYPE_EWAY = 313;
|
// const TYPE_EWAY = 313;
|
||||||
// const TYPE_FORTE = 314;
|
// const TYPE_FORTE = 314;
|
||||||
|
// const PAYPAL_PPCP = 323;
|
||||||
|
|
||||||
public $gateway_consts = [
|
public $gateway_consts = [
|
||||||
'38f2c48af60c7dd69e04248cbb24c36e' => 300,
|
'38f2c48af60c7dd69e04248cbb24c36e' => 300,
|
||||||
@ -150,6 +150,7 @@ class CompanyGateway extends BaseModel
|
|||||||
'65faab2ab6e3223dbe848b1686490baz' => 320,
|
'65faab2ab6e3223dbe848b1686490baz' => 320,
|
||||||
'b9886f9257f0c6ee7c302f1c74475f6c' => 321,
|
'b9886f9257f0c6ee7c302f1c74475f6c' => 321,
|
||||||
'hxd6gwg3ekb9tb3v9lptgx1mqyg69zu9' => 322,
|
'hxd6gwg3ekb9tb3v9lptgx1mqyg69zu9' => 322,
|
||||||
|
'80af24a6a691230bbec33e930ab40666' => 323,
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $touches = [];
|
protected $touches = [];
|
||||||
|
@ -90,7 +90,7 @@ class Gateway extends StaticModel
|
|||||||
|
|
||||||
if ($this->id == 1) {
|
if ($this->id == 1) {
|
||||||
$link = 'http://reseller.authorize.net/application/?id=5560364';
|
$link = 'http://reseller.authorize.net/application/?id=5560364';
|
||||||
} elseif ($this->id == 15) {
|
} elseif (in_array($this->id,[15,60,61])) {
|
||||||
$link = 'https://www.paypal.com/us/cgi-bin/webscr?cmd=_login-api-run';
|
$link = 'https://www.paypal.com/us/cgi-bin/webscr?cmd=_login-api-run';
|
||||||
} elseif ($this->id == 24) {
|
} elseif ($this->id == 24) {
|
||||||
$link = 'https://www.2checkout.com/referral?r=2c37ac2298';
|
$link = 'https://www.2checkout.com/referral?r=2c37ac2298';
|
||||||
@ -202,7 +202,19 @@ class Gateway extends StaticModel
|
|||||||
// GatewayType::PRZELEWY24 => ['refund' => false, 'token_billing' => false],
|
// GatewayType::PRZELEWY24 => ['refund' => false, 'token_billing' => false],
|
||||||
// GatewayType::SOFORT => ['refund' => false, 'token_billing' => false],
|
// GatewayType::SOFORT => ['refund' => false, 'token_billing' => false],
|
||||||
]; //Paypal
|
]; //Paypal
|
||||||
|
case 61:
|
||||||
|
return [
|
||||||
|
GatewayType::PAYPAL => ['refund' => false, 'token_billing' => false],
|
||||||
|
GatewayType::CREDIT_CARD => ['refund' => false, 'token_billing' => false],
|
||||||
|
GatewayType::VENMO => ['refund' => false, 'token_billing' => false],
|
||||||
|
// GatewayType::SEPA => ['refund' => false, 'token_billing' => false],
|
||||||
|
// GatewayType::BANCONTACT => ['refund' => false, 'token_billing' => false],
|
||||||
|
// GatewayType::EPS => ['refund' => false, 'token_billing' => false],
|
||||||
|
// GatewayType::MYBANK => ['refund' => false, 'token_billing' => false],
|
||||||
|
// GatewayType::PAYLATER => ['refund' => false, 'token_billing' => false],
|
||||||
|
// GatewayType::PRZELEWY24 => ['refund' => false, 'token_billing' => false],
|
||||||
|
// GatewayType::SOFORT => ['refund' => false, 'token_billing' => false],
|
||||||
|
]; //Paypal PPCP
|
||||||
default:
|
default:
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
@ -110,6 +110,11 @@ class ClientPresenter extends EntityPresenter
|
|||||||
return $str;
|
return $str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function shipping_country_code(): string
|
||||||
|
{
|
||||||
|
return $this->entity->shipping_country ? $this->entity->shipping_country->iso_3166_2 : $this->entity->country->iso_3166_2;
|
||||||
|
}
|
||||||
|
|
||||||
public function phone()
|
public function phone()
|
||||||
{
|
{
|
||||||
return $this->entity->phone ?: '';
|
return $this->entity->phone ?: '';
|
||||||
|
@ -148,6 +148,8 @@ class SystemLog extends Model
|
|||||||
|
|
||||||
const TYPE_RAZORPAY = 322;
|
const TYPE_RAZORPAY = 322;
|
||||||
|
|
||||||
|
const TYPE_PAYPAL_PPCP = 323;
|
||||||
|
|
||||||
const TYPE_QUOTA_EXCEEDED = 400;
|
const TYPE_QUOTA_EXCEEDED = 400;
|
||||||
|
|
||||||
const TYPE_UPSTREAM_FAILURE = 401;
|
const TYPE_UPSTREAM_FAILURE = 401;
|
||||||
|
@ -108,6 +108,11 @@ class BaseDriver extends AbstractPaymentDriver
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getAvailableMethods(): array
|
||||||
|
{
|
||||||
|
return self::$methods;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Required fields for client to fill, to proceed with gateway actions.
|
* Required fields for client to fill, to proceed with gateway actions.
|
||||||
*
|
*
|
||||||
|
512
app/PaymentDrivers/PayPalPPCPPaymentDriver.php
Normal file
512
app/PaymentDrivers/PayPalPPCPPaymentDriver.php
Normal file
@ -0,0 +1,512 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\PaymentDrivers;
|
||||||
|
|
||||||
|
use App\Exceptions\PaymentFailed;
|
||||||
|
use App\Jobs\Util\SystemLogger;
|
||||||
|
use App\Models\GatewayType;
|
||||||
|
use App\Models\Invoice;
|
||||||
|
use App\Models\PaymentType;
|
||||||
|
use App\Models\SystemLog;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Support\Facades\Http;
|
||||||
|
use Omnipay\Omnipay;
|
||||||
|
use Str;
|
||||||
|
|
||||||
|
class PayPalPPCPPaymentDriver extends BaseDriver
|
||||||
|
{
|
||||||
|
use MakesHash;
|
||||||
|
|
||||||
|
public $token_billing = false;
|
||||||
|
|
||||||
|
public $can_authorise_credit_card = false;
|
||||||
|
|
||||||
|
private $omnipay_gateway;
|
||||||
|
|
||||||
|
private float $fee = 0;
|
||||||
|
|
||||||
|
public const SYSTEM_LOG_TYPE = SystemLog::TYPE_PAYPAL_PPCP;
|
||||||
|
|
||||||
|
private string $api_endpoint_url = '';
|
||||||
|
|
||||||
|
private string $paypal_payment_method = '';
|
||||||
|
|
||||||
|
private ?int $gateway_type_id = null;
|
||||||
|
|
||||||
|
protected mixed $access_token = null;
|
||||||
|
|
||||||
|
protected ?Carbon $token_expiry = null;
|
||||||
|
|
||||||
|
private array $funding_options = [
|
||||||
|
3 => 'paypal',
|
||||||
|
1 => 'card',
|
||||||
|
25 => 'venmo',
|
||||||
|
// 9 => 'sepa',
|
||||||
|
// 12 => 'bancontact',
|
||||||
|
// 17 => 'eps',
|
||||||
|
// 15 => 'giropay',
|
||||||
|
// 13 => 'ideal',
|
||||||
|
// 26 => 'mercadopago',
|
||||||
|
// 27 => 'mybank',
|
||||||
|
// 28 => 'paylater',
|
||||||
|
// 16 => 'p24',
|
||||||
|
// 7 => 'sofort'
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an array of
|
||||||
|
* enabled gateway payment methods
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function gatewayTypes(): array
|
||||||
|
{
|
||||||
|
|
||||||
|
return collect($this->company_gateway->fees_and_limits)
|
||||||
|
->filter(function ($fee){
|
||||||
|
return $fee->is_enabled;
|
||||||
|
})->map(function ($fee, $key){
|
||||||
|
return (int)$key;
|
||||||
|
})->toArray();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getPaymentMethod($gateway_type_id): int
|
||||||
|
{
|
||||||
|
$method = PaymentType::PAYPAL;
|
||||||
|
|
||||||
|
match($gateway_type_id){
|
||||||
|
"1" => $method = PaymentType::CREDIT_CARD_OTHER,
|
||||||
|
"3" => $method = PaymentType::PAYPAL,
|
||||||
|
"25" => $method = PaymentType::VENMO,
|
||||||
|
};
|
||||||
|
|
||||||
|
return $method;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getFundingOptions():string
|
||||||
|
{
|
||||||
|
|
||||||
|
$enums = [
|
||||||
|
1 => 'card',
|
||||||
|
3 => 'paypal',
|
||||||
|
25 => 'venmo',
|
||||||
|
// 9 => 'sepa',
|
||||||
|
// 12 => 'bancontact',
|
||||||
|
// 17 => 'eps',
|
||||||
|
// 15 => 'giropay',
|
||||||
|
// 13 => 'ideal',
|
||||||
|
// 26 => 'mercadopago',
|
||||||
|
// 27 => 'mybank',
|
||||||
|
// 28 => 'paylater',
|
||||||
|
// 16 => 'p24',
|
||||||
|
// 7 => 'sofort'
|
||||||
|
];
|
||||||
|
|
||||||
|
$funding_options = '';
|
||||||
|
|
||||||
|
foreach($this->company_gateway->fees_and_limits as $key => $value) {
|
||||||
|
|
||||||
|
if($value->is_enabled) {
|
||||||
|
|
||||||
|
$funding_options .=$enums[$key].',';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return rtrim($funding_options, ',');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the Paypal gateway.
|
||||||
|
*
|
||||||
|
* Attempt to generate and return the access token.
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function init(): self
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->api_endpoint_url = $this->company_gateway->getConfigField('testMode') ? 'https://api-m.sandbox.paypal.com' : 'https://api-m.paypal.com';
|
||||||
|
|
||||||
|
$secret = config('ninja.paypal.secret');
|
||||||
|
$client_id = config('ninja.paypal.client_id');
|
||||||
|
|
||||||
|
if($this->access_token && $this->token_expiry && $this->token_expiry->isFuture())
|
||||||
|
return $this;
|
||||||
|
|
||||||
|
$response = Http::withBasicAuth($client_id, $secret)
|
||||||
|
->withHeaders(['Content-Type' => 'application/x-www-form-urlencoded'])
|
||||||
|
->withQueryParameters(['grant_type' => 'client_credentials'])
|
||||||
|
->post("{$this->api_endpoint_url}/v1/oauth2/token");
|
||||||
|
|
||||||
|
// nlog($response->body());
|
||||||
|
|
||||||
|
if($response->successful()) {
|
||||||
|
$this->access_token = $response->json()['access_token'];
|
||||||
|
$this->token_expiry = now()->addSeconds($response->json()['expires_in'] - 60);
|
||||||
|
} else {
|
||||||
|
throw new PaymentFailed('Unable to gain access token from Paypal. Check your configuration', 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPaymentMethod($payment_method_id)
|
||||||
|
{
|
||||||
|
if(!$payment_method_id) {
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->gateway_type_id = $payment_method_id;
|
||||||
|
|
||||||
|
$this->paypal_payment_method = $this->funding_options[$payment_method_id];
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function authorizeView($payment_method)
|
||||||
|
{
|
||||||
|
// PayPal doesn't support direct authorization.
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function authorizeResponse($request)
|
||||||
|
{
|
||||||
|
// PayPal doesn't support direct authorization.
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkPaymentsReceivable(): self
|
||||||
|
{
|
||||||
|
|
||||||
|
if($this->company_gateway->getConfigField('status') != 'activated'){
|
||||||
|
|
||||||
|
if (class_exists(\Modules\Admin\Services\PayPal\PayPalService::class)) {
|
||||||
|
$pp = new \Modules\Admin\Services\PayPal\PayPalService($this->company_gateway->company, $this->company_gateway->user);
|
||||||
|
$pp->updateMerchantStatus($this->company_gateway);
|
||||||
|
|
||||||
|
$this->company_gateway = $this->company_gateway->fresh();
|
||||||
|
$config = $this->company_gateway->getConfig();
|
||||||
|
|
||||||
|
if($config->status == 'activated')
|
||||||
|
return $this;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new PaymentFailed('Unable to accept payments at this time, please contact PayPal for more information.', 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processPaymentView($data)
|
||||||
|
{
|
||||||
|
$this->init()->checkPaymentsReceivable();
|
||||||
|
|
||||||
|
$data['gateway'] = $this;
|
||||||
|
$this->payment_hash->data = array_merge((array) $this->payment_hash->data, ['amount' => $data['total']['amount_with_fee']]);
|
||||||
|
$this->payment_hash->save();
|
||||||
|
|
||||||
|
$data['client_id'] = config('ninja.paypal.client_id');
|
||||||
|
$data['token'] = $this->getClientToken();
|
||||||
|
$data['order_id'] = $this->createOrder($data);
|
||||||
|
$data['funding_source'] = $this->paypal_payment_method;
|
||||||
|
$data['gateway_type_id'] = $this->gateway_type_id;
|
||||||
|
$data['merchantId'] = $this->company_gateway->getConfigField('merchantId');
|
||||||
|
|
||||||
|
// nlog($data['merchantId']);
|
||||||
|
|
||||||
|
return render('gateways.paypal.ppcp.pay', $data);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getClientToken(): string
|
||||||
|
{
|
||||||
|
|
||||||
|
$r = $this->gatewayRequest('/v1/identity/generate-token', 'post', ['body' => '']);
|
||||||
|
|
||||||
|
if($r->successful())
|
||||||
|
return $r->json()['client_token'];
|
||||||
|
|
||||||
|
throw new PaymentFailed('Unable to gain client token from Paypal. Check your configuration', 401);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processPaymentResponse($request)
|
||||||
|
{
|
||||||
|
nlog($request->all());
|
||||||
|
|
||||||
|
$request['gateway_response'] = str_replace("Error: ", "", $request['gateway_response']);
|
||||||
|
$response = json_decode($request['gateway_response'], true);
|
||||||
|
|
||||||
|
nlog($response);
|
||||||
|
|
||||||
|
if(isset($response['status']) && $response['status'] == 'COMPLETED' && isset($response['purchase_units'])) {
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'payment_type' => $this->getPaymentMethod($request->gateway_type_id),
|
||||||
|
'amount' => $response['purchase_units'][0]['amount']['value'],
|
||||||
|
'transaction_reference' => $response['purchase_units'][0]['payments']['captures'][0]['id'],
|
||||||
|
'gateway_type_id' => GatewayType::PAYPAL,
|
||||||
|
];
|
||||||
|
|
||||||
|
$payment = $this->createPayment($data, \App\Models\Payment::STATUS_COMPLETED);
|
||||||
|
|
||||||
|
SystemLogger::dispatch(
|
||||||
|
['response' => $response, 'data' => $data],
|
||||||
|
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||||
|
SystemLog::EVENT_GATEWAY_SUCCESS,
|
||||||
|
SystemLog::TYPE_PAYPAL,
|
||||||
|
$this->client,
|
||||||
|
$this->client->company,
|
||||||
|
);
|
||||||
|
|
||||||
|
return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if(isset($response['headers']) ?? false)
|
||||||
|
unset($response['headers']);
|
||||||
|
|
||||||
|
SystemLogger::dispatch(
|
||||||
|
['response' => $response],
|
||||||
|
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||||
|
SystemLog::EVENT_GATEWAY_FAILURE,
|
||||||
|
SystemLog::TYPE_PAYPAL,
|
||||||
|
$this->client,
|
||||||
|
$this->client->company,
|
||||||
|
);
|
||||||
|
|
||||||
|
$message = $response['body']['details'][0]['description'] ?? 'Payment failed. Please try again.';
|
||||||
|
|
||||||
|
throw new PaymentFailed($message, 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function paymentSource(): array
|
||||||
|
{
|
||||||
|
/** we only need to support paypal as payment source until as we are only using hosted payment buttons */
|
||||||
|
return $this->injectPayPalPaymentSource();
|
||||||
|
|
||||||
|
// return match($this->paypal_payment_method) {
|
||||||
|
// 'paypal' => $this->injectPayPalPaymentSource(),
|
||||||
|
// 'card' => $this->injectCardPaymentSource(),
|
||||||
|
// 'venmo' => $this->injectVenmoPaymentSource(),
|
||||||
|
// };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function injectVenmoPaymentSource(): array
|
||||||
|
{
|
||||||
|
|
||||||
|
return [
|
||||||
|
"venmo" => [
|
||||||
|
"email_address" => $this->client->present()->email(),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function injectCardPaymentSource(): array
|
||||||
|
{
|
||||||
|
|
||||||
|
return [
|
||||||
|
"card" => [
|
||||||
|
|
||||||
|
"name" => $this->client->present()->name(),
|
||||||
|
"email_address" => $this->client->present()->email(),
|
||||||
|
"billing_address" => $this->getBillingAddress(),
|
||||||
|
"experience_context"=> [
|
||||||
|
"user_action" => "PAY_NOW"
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function injectPayPalPaymentSource(): array
|
||||||
|
{
|
||||||
|
|
||||||
|
return [
|
||||||
|
"paypal" => [
|
||||||
|
|
||||||
|
"name" => [
|
||||||
|
"given_name" => $this->client->present()->first_name(),
|
||||||
|
"surname" => $this->client->present()->last_name(),
|
||||||
|
],
|
||||||
|
"email_address" => $this->client->present()->email(),
|
||||||
|
"address" => $this->getBillingAddress(),
|
||||||
|
"experience_context"=> [
|
||||||
|
"user_action" => "PAY_NOW"
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createOrder(array $data): string
|
||||||
|
{
|
||||||
|
|
||||||
|
$_invoice = collect($this->payment_hash->data->invoices)->first();
|
||||||
|
|
||||||
|
$invoice = Invoice::withTrashed()->find($this->decodePrimaryKey($_invoice->invoice_id));
|
||||||
|
|
||||||
|
$description = collect($invoice->line_items)->map(function ($item){
|
||||||
|
return $item->notes;
|
||||||
|
})->implode("\n");
|
||||||
|
|
||||||
|
$order = [
|
||||||
|
|
||||||
|
"intent" => "CAPTURE",
|
||||||
|
"payment_source" => $this->paymentSource(),
|
||||||
|
"purchase_units" => [
|
||||||
|
[
|
||||||
|
"description" =>ctrans('texts.invoice_number').'# '.$invoice->number,
|
||||||
|
"invoice_id" => $invoice->number,
|
||||||
|
"payee" => [
|
||||||
|
"merchant_id" => $this->company_gateway->getConfigField('merchantId'),
|
||||||
|
],
|
||||||
|
"payment_instruction" => [
|
||||||
|
"disbursement_mode" => "INSTANT",
|
||||||
|
],
|
||||||
|
$this->getShippingAddress(),
|
||||||
|
"amount" => [
|
||||||
|
"value" => (string)$data['amount_with_fee'],
|
||||||
|
"currency_code"=> $this->client->currency()->code,
|
||||||
|
"breakdown" => [
|
||||||
|
"item_total" => [
|
||||||
|
"currency_code" => $this->client->currency()->code,
|
||||||
|
"value" => (string)$data['amount_with_fee']
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"items"=> [
|
||||||
|
[
|
||||||
|
"name" => ctrans('texts.invoice_number').'# '.$invoice->number,
|
||||||
|
"description" => substr($description, 0, 127),
|
||||||
|
"quantity" => "1",
|
||||||
|
"unit_amount" => [
|
||||||
|
"currency_code" => $this->client->currency()->code,
|
||||||
|
"value" => (string)$data['amount_with_fee']
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
if($shipping = $this->getShippingAddress()){
|
||||||
|
$order['purchase_units'][0] = $shipping;
|
||||||
|
}
|
||||||
|
|
||||||
|
$r = $this->gatewayRequest('/v2/checkout/orders', 'post', $order);
|
||||||
|
|
||||||
|
nlog($r->json());
|
||||||
|
|
||||||
|
return $r->json()['id'];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getBillingAddress(): array
|
||||||
|
{
|
||||||
|
return
|
||||||
|
[
|
||||||
|
"address_line_1" => $this->client->address1,
|
||||||
|
"address_line_2" => $this->client->address2,
|
||||||
|
"admin_area_2" => $this->client->city,
|
||||||
|
"admin_area_1" => $this->client->state,
|
||||||
|
"postal_code" => $this->client->postal_code,
|
||||||
|
"country_code" => $this->client->country->iso_3166_2,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getShippingAddress(): ?array
|
||||||
|
{
|
||||||
|
return $this->company_gateway->require_shipping_address ?
|
||||||
|
[
|
||||||
|
"shipping" => [
|
||||||
|
"address" =>
|
||||||
|
[
|
||||||
|
"address_line_1" => $this->client->shipping_address1,
|
||||||
|
"address_line_2" => $this->client->shipping_address2,
|
||||||
|
"admin_area_2" => $this->client->shipping_city,
|
||||||
|
"admin_area_1" => $this->client->shipping_state,
|
||||||
|
"postal_code" => $this->client->shipping_postal_code,
|
||||||
|
"country_code" => $this->client->present()->shipping_country_code(),
|
||||||
|
],
|
||||||
|
]
|
||||||
|
]
|
||||||
|
: null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function gatewayRequest(string $uri, string $verb, array $data, ?array $headers = [])
|
||||||
|
{
|
||||||
|
$this->init();
|
||||||
|
|
||||||
|
$r = Http::withToken($this->access_token)
|
||||||
|
->withHeaders($this->getHeaders($headers))
|
||||||
|
->{$verb}("{$this->api_endpoint_url}{$uri}", $data);
|
||||||
|
|
||||||
|
if($r->successful()) {
|
||||||
|
return $r;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new PaymentFailed("Gateway failure - {$r->body()}", 401);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getHeaders(array $headers = []): array
|
||||||
|
{
|
||||||
|
return array_merge([
|
||||||
|
'Accept' => 'application/json',
|
||||||
|
'Content-type' => 'application/json',
|
||||||
|
'Accept-Language' => 'en_US',
|
||||||
|
'PayPal-Partner-Attribution-Id' => 'invoiceninja_SP_PPCP',
|
||||||
|
'PayPal-Request-Id' => Str::uuid()->toString(),
|
||||||
|
], $headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function feeCalc($invoice, $invoice_total)
|
||||||
|
{
|
||||||
|
// $invoice->service()->removeUnpaidGatewayFees();
|
||||||
|
// $invoice = $invoice->fresh();
|
||||||
|
|
||||||
|
// $balance = floatval($invoice->balance);
|
||||||
|
|
||||||
|
// $_updated_invoice = $invoice->service()->addGatewayFee($this->company_gateway, GatewayType::PAYPAL, $invoice_total)->save();
|
||||||
|
|
||||||
|
// if (floatval($_updated_invoice->balance) > $balance) {
|
||||||
|
// $fee = floatval($_updated_invoice->balance) - $balance;
|
||||||
|
|
||||||
|
// $this->payment_hash->fee_total = $fee;
|
||||||
|
// $this->payment_hash->save();
|
||||||
|
|
||||||
|
// return $fee;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -140,13 +140,13 @@ class StripePaymentDriver extends BaseDriver
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the gateway types.
|
* Returns the gateway types.
|
||||||
*/
|
*/
|
||||||
public function gatewayTypes(): array
|
public function gatewayTypes(): array
|
||||||
{
|
{
|
||||||
$types = [
|
$types = [
|
||||||
// GatewayType::CRYPTO,
|
|
||||||
GatewayType::CREDIT_CARD,
|
GatewayType::CREDIT_CARD,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -263,13 +263,245 @@ use App\Observers\PaymentObserver;
|
|||||||
use App\Observers\ProductObserver;
|
use App\Observers\ProductObserver;
|
||||||
use App\Observers\ProjectObserver;
|
use App\Observers\ProjectObserver;
|
||||||
use App\Observers\ProposalObserver;
|
use App\Observers\ProposalObserver;
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
use App\Events\Quote\QuoteWasViewed;
|
||||||
|
use App\Events\Task\TaskWasArchived;
|
||||||
|
use App\Events\Task\TaskWasRestored;
|
||||||
|
use App\Events\User\UserWasArchived;
|
||||||
|
use App\Events\User\UserWasRestored;
|
||||||
|
use App\Events\Quote\QuoteWasCreated;
|
||||||
|
use App\Events\Quote\QuoteWasDeleted;
|
||||||
|
use App\Events\Quote\QuoteWasEmailed;
|
||||||
|
use App\Events\Quote\QuoteWasUpdated;
|
||||||
|
use App\Events\Account\AccountCreated;
|
||||||
|
use App\Events\Credit\CreditWasViewed;
|
||||||
|
use App\Events\Invoice\InvoiceWasPaid;
|
||||||
|
use App\Events\Quote\QuoteWasApproved;
|
||||||
|
use App\Events\Quote\QuoteWasArchived;
|
||||||
|
use App\Events\Quote\QuoteWasRestored;
|
||||||
|
use App\Listeners\LogResponseReceived;
|
||||||
|
use App\Events\Client\ClientWasCreated;
|
||||||
|
use App\Events\Client\ClientWasDeleted;
|
||||||
|
use App\Events\Client\ClientWasUpdated;
|
||||||
|
use App\Events\Contact\ContactLoggedIn;
|
||||||
|
use App\Events\Credit\CreditWasCreated;
|
||||||
|
use App\Events\Credit\CreditWasDeleted;
|
||||||
|
use App\Events\Credit\CreditWasEmailed;
|
||||||
|
use App\Events\Credit\CreditWasUpdated;
|
||||||
|
use App\Events\Design\DesignWasDeleted;
|
||||||
|
use App\Events\Design\DesignWasUpdated;
|
||||||
|
use App\Events\Vendor\VendorWasCreated;
|
||||||
|
use App\Events\Vendor\VendorWasDeleted;
|
||||||
|
use App\Events\Vendor\VendorWasUpdated;
|
||||||
|
use App\Observers\CompanyTokenObserver;
|
||||||
|
use App\Observers\SubscriptionObserver;
|
||||||
|
use Illuminate\Mail\Events\MessageSent;
|
||||||
|
use App\Events\Client\ClientWasArchived;
|
||||||
|
use App\Events\Client\ClientWasRestored;
|
||||||
|
use App\Events\Credit\CreditWasArchived;
|
||||||
|
use App\Events\Credit\CreditWasRestored;
|
||||||
|
use App\Events\Design\DesignWasArchived;
|
||||||
|
use App\Events\Design\DesignWasRestored;
|
||||||
|
use App\Events\Invoice\InvoiceWasViewed;
|
||||||
|
use App\Events\Misc\InvitationWasViewed;
|
||||||
|
use App\Events\Payment\PaymentWasVoided;
|
||||||
|
use App\Events\Vendor\VendorWasArchived;
|
||||||
|
use App\Events\Vendor\VendorWasRestored;
|
||||||
|
use App\Listeners\Mail\MailSentListener;
|
||||||
|
use App\Observers\ClientContactObserver;
|
||||||
|
>>>>>>> paypal_ppcp
|
||||||
use App\Observers\PurchaseOrderObserver;
|
use App\Observers\PurchaseOrderObserver;
|
||||||
use App\Observers\QuoteObserver;
|
use App\Observers\QuoteObserver;
|
||||||
use App\Observers\SubscriptionObserver;
|
use App\Observers\SubscriptionObserver;
|
||||||
use App\Observers\TaskObserver;
|
use App\Observers\TaskObserver;
|
||||||
use App\Observers\UserObserver;
|
use App\Observers\UserObserver;
|
||||||
use App\Observers\VendorContactObserver;
|
use App\Observers\VendorContactObserver;
|
||||||
|
<<<<<<< HEAD
|
||||||
use App\Observers\VendorObserver;
|
use App\Observers\VendorObserver;
|
||||||
|
=======
|
||||||
|
use App\Events\Expense\ExpenseWasCreated;
|
||||||
|
use App\Events\Expense\ExpenseWasDeleted;
|
||||||
|
use App\Events\Expense\ExpenseWasUpdated;
|
||||||
|
use App\Events\Invoice\InvoiceWasCreated;
|
||||||
|
use App\Events\Invoice\InvoiceWasDeleted;
|
||||||
|
use App\Events\Invoice\InvoiceWasEmailed;
|
||||||
|
use App\Events\Invoice\InvoiceWasUpdated;
|
||||||
|
use App\Events\Payment\PaymentWasCreated;
|
||||||
|
use App\Events\Payment\PaymentWasDeleted;
|
||||||
|
use App\Events\Payment\PaymentWasEmailed;
|
||||||
|
use App\Events\Payment\PaymentWasUpdated;
|
||||||
|
use App\Observers\CompanyGatewayObserver;
|
||||||
|
use App\Events\Credit\CreditWasMarkedSent;
|
||||||
|
use App\Events\Expense\ExpenseWasArchived;
|
||||||
|
use App\Events\Expense\ExpenseWasRestored;
|
||||||
|
use App\Events\Invoice\InvoiceWasArchived;
|
||||||
|
use App\Events\Invoice\InvoiceWasRestored;
|
||||||
|
use App\Events\Invoice\InvoiceWasReversed;
|
||||||
|
use App\Events\Payment\PaymentWasArchived;
|
||||||
|
use App\Events\Payment\PaymentWasRefunded;
|
||||||
|
use App\Events\Payment\PaymentWasRestored;
|
||||||
|
use Illuminate\Mail\Events\MessageSending;
|
||||||
|
use App\Events\Document\DocumentWasCreated;
|
||||||
|
use App\Events\Document\DocumentWasDeleted;
|
||||||
|
use App\Events\Document\DocumentWasUpdated;
|
||||||
|
use App\Events\Invoice\InvoiceWasCancelled;
|
||||||
|
use App\Listeners\Invoice\CreateInvoicePdf;
|
||||||
|
use App\Listeners\Quote\QuoteEmailActivity;
|
||||||
|
use App\Listeners\User\CreatedUserActivity;
|
||||||
|
use App\Listeners\User\DeletedUserActivity;
|
||||||
|
use App\Listeners\User\UpdatedUserActivity;
|
||||||
|
use App\Listeners\User\UpdateUserLastLogin;
|
||||||
|
use App\Events\Account\StripeConnectFailure;
|
||||||
|
use App\Events\Document\DocumentWasArchived;
|
||||||
|
use App\Events\Document\DocumentWasRestored;
|
||||||
|
use App\Events\Invoice\InvoiceWasMarkedSent;
|
||||||
|
use App\Events\Vendor\VendorContactLoggedIn;
|
||||||
|
use App\Listeners\Quote\QuoteViewedActivity;
|
||||||
|
use App\Listeners\LogRequestSending;
|
||||||
|
use App\Listeners\User\ArchivedUserActivity;
|
||||||
|
use App\Listeners\User\RestoredUserActivity;
|
||||||
|
use App\Listeners\Quote\QuoteApprovedWebhook;
|
||||||
|
use App\Listeners\Quote\QuoteDeletedActivity;
|
||||||
|
use App\Listeners\Credit\CreditViewedActivity;
|
||||||
|
use App\Listeners\Invoice\InvoicePaidActivity;
|
||||||
|
use App\Listeners\Payment\PaymentNotification;
|
||||||
|
use App\Listeners\Quote\QuoteApprovedActivity;
|
||||||
|
use App\Listeners\Quote\QuoteArchivedActivity;
|
||||||
|
use App\Listeners\Quote\QuoteRestoredActivity;
|
||||||
|
use App\Listeners\Quote\ReachWorkflowSettings;
|
||||||
|
use App\Events\Company\CompanyDocumentsDeleted;
|
||||||
|
use App\Listeners\Activity\CreatedTaskActivity;
|
||||||
|
use App\Listeners\Activity\TaskDeletedActivity;
|
||||||
|
use App\Listeners\Activity\TaskUpdatedActivity;
|
||||||
|
use App\Listeners\Invoice\InvoiceEmailActivity;
|
||||||
|
use App\Listeners\SendVerificationNotification;
|
||||||
|
use App\Events\Credit\CreditWasEmailedAndFailed;
|
||||||
|
use App\Listeners\Activity\CreatedQuoteActivity;
|
||||||
|
use App\Listeners\Activity\DeleteClientActivity;
|
||||||
|
use App\Listeners\Activity\DeleteCreditActivity;
|
||||||
|
use App\Listeners\Activity\QuoteUpdatedActivity;
|
||||||
|
use App\Listeners\Activity\TaskArchivedActivity;
|
||||||
|
use App\Listeners\Activity\TaskRestoredActivity;
|
||||||
|
use App\Listeners\Credit\CreditRestoredActivity;
|
||||||
|
use App\Listeners\Invoice\CreateInvoiceActivity;
|
||||||
|
use App\Listeners\Invoice\InvoiceViewedActivity;
|
||||||
|
use App\Listeners\Invoice\UpdateInvoiceActivity;
|
||||||
|
use App\Listeners\Misc\InvitationViewedListener;
|
||||||
|
use App\Events\Invoice\InvoiceReminderWasEmailed;
|
||||||
|
use App\Listeners\Activity\ClientUpdatedActivity;
|
||||||
|
use App\Listeners\Activity\CreatedClientActivity;
|
||||||
|
use App\Listeners\Activity\CreatedCreditActivity;
|
||||||
|
use App\Listeners\Activity\CreatedVendorActivity;
|
||||||
|
use App\Listeners\Activity\PaymentVoidedActivity;
|
||||||
|
use App\Listeners\Activity\RestoreClientActivity;
|
||||||
|
use App\Listeners\Activity\UpdatedCreditActivity;
|
||||||
|
use App\Listeners\Activity\VendorDeletedActivity;
|
||||||
|
use App\Listeners\Activity\VendorUpdatedActivity;
|
||||||
|
use App\Listeners\Contact\UpdateContactLastLogin;
|
||||||
|
use App\Listeners\Invoice\InvoiceDeletedActivity;
|
||||||
|
use App\Listeners\Payment\PaymentBalanceActivity;
|
||||||
|
use App\Listeners\Payment\PaymentEmailedActivity;
|
||||||
|
use App\Listeners\Quote\QuoteCreatedNotification;
|
||||||
|
use App\Listeners\Quote\QuoteEmailedNotification;
|
||||||
|
use Illuminate\Http\Client\Events\RequestSending;
|
||||||
|
use App\Events\Invoice\InvoiceWasEmailedAndFailed;
|
||||||
|
use App\Events\Payment\PaymentWasEmailedAndFailed;
|
||||||
|
use App\Listeners\Activity\ArchivedClientActivity;
|
||||||
|
use App\Listeners\Activity\CreatedExpenseActivity;
|
||||||
|
use App\Listeners\Activity\CreditArchivedActivity;
|
||||||
|
use App\Listeners\Activity\ExpenseDeletedActivity;
|
||||||
|
use App\Listeners\Activity\ExpenseUpdatedActivity;
|
||||||
|
use App\Listeners\Activity\PaymentCreatedActivity;
|
||||||
|
use App\Listeners\Activity\PaymentDeletedActivity;
|
||||||
|
use App\Listeners\Activity\PaymentUpdatedActivity;
|
||||||
|
use App\Listeners\Activity\VendorArchivedActivity;
|
||||||
|
use App\Listeners\Activity\VendorRestoredActivity;
|
||||||
|
use App\Listeners\Document\DeleteCompanyDocuments;
|
||||||
|
use App\Listeners\Invoice\InvoiceArchivedActivity;
|
||||||
|
use App\Listeners\Invoice\InvoiceRestoredActivity;
|
||||||
|
use App\Listeners\Invoice\InvoiceReversedActivity;
|
||||||
|
use App\Listeners\Payment\PaymentRestoredActivity;
|
||||||
|
use App\Listeners\Quote\QuoteApprovedNotification;
|
||||||
|
use SocialiteProviders\Apple\AppleExtendSocialite;
|
||||||
|
use SocialiteProviders\Manager\SocialiteWasCalled;
|
||||||
|
use App\Events\Subscription\SubscriptionWasCreated;
|
||||||
|
use App\Events\Subscription\SubscriptionWasDeleted;
|
||||||
|
use App\Events\Subscription\SubscriptionWasUpdated;
|
||||||
|
use App\Listeners\Activity\ExpenseArchivedActivity;
|
||||||
|
use App\Listeners\Activity\ExpenseRestoredActivity;
|
||||||
|
use App\Listeners\Activity\PaymentArchivedActivity;
|
||||||
|
use App\Listeners\Activity\PaymentRefundedActivity;
|
||||||
|
use App\Listeners\Credit\CreditCreatedNotification;
|
||||||
|
use App\Listeners\Credit\CreditEmailedNotification;
|
||||||
|
use App\Listeners\Invoice\InvoiceCancelledActivity;
|
||||||
|
use Illuminate\Http\Client\Events\ResponseReceived;
|
||||||
|
use App\Events\PurchaseOrder\PurchaseOrderWasViewed;
|
||||||
|
use App\Events\Subscription\SubscriptionWasArchived;
|
||||||
|
use App\Events\Subscription\SubscriptionWasRestored;
|
||||||
|
use App\Events\PurchaseOrder\PurchaseOrderWasCreated;
|
||||||
|
use App\Events\PurchaseOrder\PurchaseOrderWasDeleted;
|
||||||
|
use App\Events\PurchaseOrder\PurchaseOrderWasEmailed;
|
||||||
|
use App\Events\PurchaseOrder\PurchaseOrderWasUpdated;
|
||||||
|
use App\Listeners\Invoice\InvoiceCreatedNotification;
|
||||||
|
use App\Listeners\Invoice\InvoiceEmailedNotification;
|
||||||
|
use App\Listeners\Invoice\InvoiceEmailFailedActivity;
|
||||||
|
use App\Events\PurchaseOrder\PurchaseOrderWasAccepted;
|
||||||
|
use App\Events\PurchaseOrder\PurchaseOrderWasArchived;
|
||||||
|
use App\Events\PurchaseOrder\PurchaseOrderWasRestored;
|
||||||
|
use App\Listeners\Payment\PaymentEmailFailureActivity;
|
||||||
|
use App\Listeners\Vendor\UpdateVendorContactLastLogin;
|
||||||
|
use App\Events\RecurringQuote\RecurringQuoteWasCreated;
|
||||||
|
use App\Events\RecurringQuote\RecurringQuoteWasDeleted;
|
||||||
|
use App\Events\RecurringQuote\RecurringQuoteWasUpdated;
|
||||||
|
use App\Listeners\Account\StripeConnectFailureListener;
|
||||||
|
use App\Listeners\Activity\CreatedSubscriptionActivity;
|
||||||
|
use App\Listeners\Activity\SubscriptionDeletedActivity;
|
||||||
|
use App\Listeners\Activity\SubscriptionUpdatedActivity;
|
||||||
|
use App\Listeners\Invoice\InvoiceReminderEmailActivity;
|
||||||
|
use App\Events\RecurringQuote\RecurringQuoteWasArchived;
|
||||||
|
use App\Events\RecurringQuote\RecurringQuoteWasRestored;
|
||||||
|
use App\Listeners\Activity\SubscriptionArchivedActivity;
|
||||||
|
use App\Listeners\Activity\SubscriptionRestoredActivity;
|
||||||
|
use App\Listeners\Invoice\InvoiceFailedEmailNotification;
|
||||||
|
use SocialiteProviders\Microsoft\MicrosoftExtendSocialite;
|
||||||
|
use App\Events\RecurringExpense\RecurringExpenseWasCreated;
|
||||||
|
use App\Events\RecurringExpense\RecurringExpenseWasDeleted;
|
||||||
|
use App\Events\RecurringExpense\RecurringExpenseWasUpdated;
|
||||||
|
use App\Events\RecurringInvoice\RecurringInvoiceWasCreated;
|
||||||
|
use App\Events\RecurringInvoice\RecurringInvoiceWasDeleted;
|
||||||
|
use App\Events\RecurringInvoice\RecurringInvoiceWasUpdated;
|
||||||
|
use App\Listeners\PurchaseOrder\PurchaseOrderEmailActivity;
|
||||||
|
use App\Events\RecurringExpense\RecurringExpenseWasArchived;
|
||||||
|
use App\Events\RecurringExpense\RecurringExpenseWasRestored;
|
||||||
|
use App\Events\RecurringInvoice\RecurringInvoiceWasArchived;
|
||||||
|
use App\Events\RecurringInvoice\RecurringInvoiceWasRestored;
|
||||||
|
use App\Listeners\PurchaseOrder\CreatePurchaseOrderActivity;
|
||||||
|
use App\Listeners\PurchaseOrder\PurchaseOrderViewedActivity;
|
||||||
|
use App\Listeners\PurchaseOrder\UpdatePurchaseOrderActivity;
|
||||||
|
use App\Listeners\PurchaseOrder\PurchaseOrderCreatedListener;
|
||||||
|
use App\Listeners\PurchaseOrder\PurchaseOrderDeletedActivity;
|
||||||
|
use App\Listeners\PurchaseOrder\PurchaseOrderAcceptedActivity;
|
||||||
|
use App\Listeners\PurchaseOrder\PurchaseOrderAcceptedListener;
|
||||||
|
use App\Listeners\PurchaseOrder\PurchaseOrderArchivedActivity;
|
||||||
|
use App\Listeners\PurchaseOrder\PurchaseOrderRestoredActivity;
|
||||||
|
use App\Listeners\RecurringQuote\CreateRecurringQuoteActivity;
|
||||||
|
use App\Listeners\RecurringQuote\UpdateRecurringQuoteActivity;
|
||||||
|
use App\Listeners\RecurringQuote\RecurringQuoteDeletedActivity;
|
||||||
|
use App\Listeners\RecurringQuote\RecurringQuoteArchivedActivity;
|
||||||
|
use App\Listeners\RecurringQuote\RecurringQuoteRestoredActivity;
|
||||||
|
use App\Listeners\PurchaseOrder\PurchaseOrderEmailedNotification;
|
||||||
|
use App\Listeners\RecurringInvoice\CreateRecurringInvoiceActivity;
|
||||||
|
use App\Listeners\RecurringInvoice\UpdateRecurringInvoiceActivity;
|
||||||
|
use App\Listeners\RecurringExpense\CreatedRecurringExpenseActivity;
|
||||||
|
use App\Listeners\RecurringExpense\RecurringExpenseDeletedActivity;
|
||||||
|
use App\Listeners\RecurringExpense\RecurringExpenseUpdatedActivity;
|
||||||
|
use App\Listeners\RecurringInvoice\RecurringInvoiceDeletedActivity;
|
||||||
|
use App\Listeners\RecurringExpense\RecurringExpenseArchivedActivity;
|
||||||
|
use App\Listeners\RecurringExpense\RecurringExpenseRestoredActivity;
|
||||||
|
use App\Listeners\RecurringInvoice\RecurringInvoiceArchivedActivity;
|
||||||
|
use App\Listeners\RecurringInvoice\RecurringInvoiceRestoredActivity;
|
||||||
|
>>>>>>> paypal_ppcp
|
||||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||||
use Illuminate\Mail\Events\MessageSending;
|
use Illuminate\Mail\Events\MessageSending;
|
||||||
use Illuminate\Mail\Events\MessageSent;
|
use Illuminate\Mail\Events\MessageSent;
|
||||||
@ -281,6 +513,13 @@ class EventServiceProvider extends ServiceProvider
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected $listen = [
|
protected $listen = [
|
||||||
|
|
||||||
|
RequestSending::class => [
|
||||||
|
LogRequestSending::class,
|
||||||
|
],
|
||||||
|
ResponseReceived::class => [
|
||||||
|
LogResponseReceived::class,
|
||||||
|
],
|
||||||
AccountCreated::class => [
|
AccountCreated::class => [
|
||||||
],
|
],
|
||||||
MessageSending::class => [
|
MessageSending::class => [
|
||||||
|
@ -86,6 +86,7 @@ return [
|
|||||||
'password' => 'password',
|
'password' => 'password',
|
||||||
'stripe' => env('STRIPE_KEYS', ''),
|
'stripe' => env('STRIPE_KEYS', ''),
|
||||||
'paypal' => env('PAYPAL_KEYS', ''),
|
'paypal' => env('PAYPAL_KEYS', ''),
|
||||||
|
'ppcp' => env('PPCP_KEYS', ''),
|
||||||
'paypal_rest' => env('PAYPAL_REST_KEYS', ''),
|
'paypal_rest' => env('PAYPAL_REST_KEYS', ''),
|
||||||
'authorize' => env('AUTHORIZE_KEYS', ''),
|
'authorize' => env('AUTHORIZE_KEYS', ''),
|
||||||
'checkout' => env('CHECKOUT_KEYS', ''),
|
'checkout' => env('CHECKOUT_KEYS', ''),
|
||||||
@ -223,4 +224,8 @@ return [
|
|||||||
'client_id' => env('SHOPIFY_CLIENT_ID', null),
|
'client_id' => env('SHOPIFY_CLIENT_ID', null),
|
||||||
'client_secret' => env('SHOPIFY_CLIENT_SECRET', null),
|
'client_secret' => env('SHOPIFY_CLIENT_SECRET', null),
|
||||||
],
|
],
|
||||||
|
'paypal' => [
|
||||||
|
'secret' => env('PAYPAL_SECRET', null),
|
||||||
|
'client_id' => env('PAYPAL_CLIENT_ID', null),
|
||||||
|
]
|
||||||
];
|
];
|
||||||
|
49
database/migrations/2023_10_15_204204_add_paypal_ppcp.php
Normal file
49
database/migrations/2023_10_15_204204_add_paypal_ppcp.php
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Utils\Ninja;
|
||||||
|
use App\Models\Gateway;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
|
||||||
|
if(!Gateway::find(61) && Ninja::isHosted())
|
||||||
|
{
|
||||||
|
|
||||||
|
$fields = new \stdClass;
|
||||||
|
$fields->clientId = "";
|
||||||
|
$fields->secret = "";
|
||||||
|
$fields->testMode = false;
|
||||||
|
|
||||||
|
$paypal = new Gateway;
|
||||||
|
$paypal->id = 61;
|
||||||
|
$paypal->name = 'PayPal Platform';
|
||||||
|
$paypal->key = '80af24a6a691230bbec33e930ab40666';
|
||||||
|
$paypal->provider = 'PayPal_PPCP';
|
||||||
|
$paypal->is_offsite = false;
|
||||||
|
$paypal->fields = \json_encode($fields);
|
||||||
|
$paypal->visible = 1;
|
||||||
|
$paypal->site_url = 'https://www.paypal.com/';
|
||||||
|
$paypal->save();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Gateway::whereIn('id', [60, 15, 49])->update(['visible' => 0]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
};
|
@ -84,6 +84,7 @@ class PaymentLibrariesSeeder extends Seeder
|
|||||||
['id' => 58, 'name' => 'Razorpay', 'provider' => 'Razorpay', 'is_offsite' => false, 'sort_order' => 21, 'key' => 'hxd6gwg3ekb9tb3v9lptgx1mqyg69zu9', 'fields' => '{"apiKey":"","apiSecret":""}'],
|
['id' => 58, 'name' => 'Razorpay', 'provider' => 'Razorpay', 'is_offsite' => false, 'sort_order' => 21, 'key' => 'hxd6gwg3ekb9tb3v9lptgx1mqyg69zu9', 'fields' => '{"apiKey":"","apiSecret":""}'],
|
||||||
['id' => 59, 'name' => 'Forte', 'provider' => 'Forte', 'is_offsite' => false, 'sort_order' => 21, 'key' => 'kivcvjexxvdiyqtj3mju5d6yhpeht2xs', 'fields' => '{"testMode":false,"apiLoginId":"","apiAccessId":"","secureKey":"","authOrganizationId":"","organizationId":"","locationId":""}'],
|
['id' => 59, 'name' => 'Forte', 'provider' => 'Forte', 'is_offsite' => false, 'sort_order' => 21, 'key' => 'kivcvjexxvdiyqtj3mju5d6yhpeht2xs', 'fields' => '{"testMode":false,"apiLoginId":"","apiAccessId":"","secureKey":"","authOrganizationId":"","organizationId":"","locationId":""}'],
|
||||||
['id' => 60, 'name' => 'PayPal REST', 'provider' => 'PayPal_Rest', 'key' => '80af24a6a691230bbec33e930ab40665', 'fields' => '{"clientId":"","secret":"","signature":"","testMode":false}'],
|
['id' => 60, 'name' => 'PayPal REST', 'provider' => 'PayPal_Rest', 'key' => '80af24a6a691230bbec33e930ab40665', 'fields' => '{"clientId":"","secret":"","signature":"","testMode":false}'],
|
||||||
|
['id' => 61, 'name' => 'PayPal Platform', 'provider' => 'PayPal_PPCP', 'key' => '80af24a6a691230bbec33e930ab40666', 'fields' => '{"testMode":false}'],
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($gateways as $gateway) {
|
foreach ($gateways as $gateway) {
|
||||||
@ -103,9 +104,8 @@ class PaymentLibrariesSeeder extends Seeder
|
|||||||
Gateway::whereIn('id', [1,3,7,11,15,20,39,46,55,50,57,52,58,59,60])->update(['visible' => 1]);
|
Gateway::whereIn('id', [1,3,7,11,15,20,39,46,55,50,57,52,58,59,60])->update(['visible' => 1]);
|
||||||
|
|
||||||
if (Ninja::isHosted()) {
|
if (Ninja::isHosted()) {
|
||||||
Gateway::whereIn('id', [20])->update(['visible' => 0]);
|
Gateway::whereIn('id', [20,49])->update(['visible' => 0]);
|
||||||
Gateway::whereIn('id', [56])->update(['visible' => 1]);
|
Gateway::whereIn('id', [56,61])->update(['visible' => 1]);
|
||||||
Gateway::whereIn('id', [49])->update(['visible' => 1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Gateway::all()->each(function ($gateway) {
|
Gateway::all()->each(function ($gateway) {
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' => 'PayPal'])
|
||||||
|
|
||||||
|
@section('gateway_head')
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
type="text/css"
|
||||||
|
href="https://www.paypalobjects.com/webstatic/en_US/developer/docs/css/cardfields.css"
|
||||||
|
/>
|
||||||
|
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('gateway_content')
|
||||||
|
<form action="{{ route('client.payments.response') }}" method="post" id="server_response">
|
||||||
|
@csrf
|
||||||
|
<input type="hidden" name="payment_hash" value="{{ $payment_hash }}">
|
||||||
|
<input type="hidden" name="company_gateway_id" value="{{ $gateway->company_gateway->id }}">
|
||||||
|
<input type="hidden" name="gateway_type_id" id="gateway_type_id" value="{{ $gateway_type_id }}">
|
||||||
|
<input type="hidden" name="gateway_response" id="gateway_response">
|
||||||
|
<input type="hidden" name="amount_with_fee" id="amount_with_fee" value="{{ $total['amount_with_fee'] }}"/>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="alert alert-failure mb-4" hidden id="errors"></div>
|
||||||
|
|
||||||
|
<div id="paypal-button-container" class="paypal-button-container"></div>
|
||||||
|
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('gateway_footer')
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@push('footer')
|
||||||
|
|
||||||
|
<script src="https://www.paypal.com/sdk/js?client-id={!! $client_id !!}&merchant-id={!! $merchantId !!}&components=buttons,funding-eligibility&intent=capture" data-partner-attribution-id="invoiceninja_SP_PPCP"></script>
|
||||||
|
<div id="paypal-button-container"></div>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
//&buyer-country=US¤cy=USD&enable-funding=venmo
|
||||||
|
const fundingSource = "{!! $funding_source !!}";
|
||||||
|
const testMode = {{ $gateway->company_gateway->getConfigField('testMode') }};
|
||||||
|
const clientId = "{{ $client_id }}";
|
||||||
|
const sandbox = { sandbox: clientId };
|
||||||
|
const production = { production: clientId };
|
||||||
|
const orderId = "{!! $order_id !!}";
|
||||||
|
|
||||||
|
paypal.Buttons({
|
||||||
|
env: testMode ? 'sandbox' : 'production',
|
||||||
|
fundingSource: fundingSource,
|
||||||
|
client: testMode ? sandbox : production,
|
||||||
|
createOrder: function(data, actions) {
|
||||||
|
return orderId;
|
||||||
|
},
|
||||||
|
onApprove: function(data, actions) {
|
||||||
|
return actions.order.capture().then(function(details) {
|
||||||
|
document.getElementById("gateway_response").value =JSON.stringify( details );
|
||||||
|
document.getElementById("server_response").submit();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onCancel: function() {
|
||||||
|
window.location.href = "/client/invoices/";
|
||||||
|
},
|
||||||
|
onError: function(error) {
|
||||||
|
document.getElementById("gateway_response").value = error;
|
||||||
|
document.getElementById("server_response").submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
}).render('#paypal-button-container');
|
||||||
|
</script>
|
||||||
|
|
||||||
|
@endpush
|
Loading…
x
Reference in New Issue
Block a user