From 6d3a2890f1aa5339c26f6b38f8e68a900b438b91 Mon Sep 17 00:00:00 2001 From: aemaddin Date: Mon, 17 Feb 2025 18:23:23 +0200 Subject: [PATCH] - [X] secure post url --- ...9_05_03_000001_create_customer_columns.php | 15 +- ...5_03_000002_create_subscriptions_table.php | 3 +- ...000003_create_subscription_items_table.php | 3 +- src/Cashier.php | 4 +- src/Concerns/ManagesCustomer.php | 146 +++++++++--------- src/Concerns/ManagesInvoices.php | 22 +-- src/Concerns/ManagesPaymentMethods.php | 4 +- src/Concerns/PerformsCharges.php | 16 +- src/Console/PublishCommand.php | 2 +- src/Contracts/Billable.php | 7 +- src/Events/TapChargeHandled.php | 2 +- src/Events/TapReceiptSeen.php | 3 +- src/Events/WebhookHandled.php | 2 +- src/Events/WebhookReceived.php | 2 +- src/Exceptions/CustomerAlreadyCreated.php | 2 +- src/Exceptions/IncompletePayment.php | 10 +- src/Http/Controllers/PaymentController.php | 3 +- src/Http/Controllers/ReceiptController.php | 2 - src/Http/Controllers/WebhookController.php | 34 ++-- src/Http/Requests/TapWebhookRequest.php | 12 +- src/Payment.php | 6 +- src/Providers/CashierServiceProvider.php | 88 +++++------ src/Traits/Downloadable.php | 52 +++---- src/Traits/ManagesAppDetails.php | 26 ++-- src/Traits/ManagesSupportOptions.php | 2 +- stubs/CashierServiceProvider.stub | 14 +- tests/Feature/ChargesTest.php | 2 +- tests/Feature/FeatureTestCase.php | 57 +++---- tests/Fixtures/User.php | 2 +- tests/TestCase.php | 6 +- tests/Unit/CustomerTest.php | 1 - 31 files changed, 274 insertions(+), 276 deletions(-) diff --git a/database/migrations/2019_05_03_000001_create_customer_columns.php b/database/migrations/2019_05_03_000001_create_customer_columns.php index ae4f7ce..de7c1b6 100644 --- a/database/migrations/2019_05_03_000001_create_customer_columns.php +++ b/database/migrations/2019_05_03_000001_create_customer_columns.php @@ -4,35 +4,34 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class extends Migration { /** * Run the migrations. */ public function up(): void { Schema::table('users', function (Blueprint $table) { - if (!Schema::hasColumn('users', 'first_name')) { + if (! Schema::hasColumn('users', 'first_name')) { $table->string('first_name')->nullable(); } - if (!Schema::hasColumn('users', 'last_name')) { + if (! Schema::hasColumn('users', 'last_name')) { $table->string('last_name')->nullable(); } - if (!Schema::hasColumn('users', 'phone')) { + if (! Schema::hasColumn('users', 'phone')) { $table->string('phone')->nullable(); } - if (!Schema::hasColumn('users', 'phone_code')) { + if (! Schema::hasColumn('users', 'phone_code')) { $table->string('phone_code')->nullable(); } - if (!Schema::hasColumn('users', 'email')) { + if (! Schema::hasColumn('users', 'email')) { $table->string('email')->nullable(); } - if (!Schema::hasColumn('users', 'tap_id')) { + if (! Schema::hasColumn('users', 'tap_id')) { $table->string('tap_id')->nullable()->index(); $table->string('card_brand')->nullable(); $table->string('card_last_four', 4)->nullable(); diff --git a/database/migrations/2019_05_03_000002_create_subscriptions_table.php b/database/migrations/2019_05_03_000002_create_subscriptions_table.php index e63d119..c664776 100644 --- a/database/migrations/2019_05_03_000002_create_subscriptions_table.php +++ b/database/migrations/2019_05_03_000002_create_subscriptions_table.php @@ -4,8 +4,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class extends Migration { /** * Run the migrations. */ diff --git a/database/migrations/2019_05_03_000003_create_subscription_items_table.php b/database/migrations/2019_05_03_000003_create_subscription_items_table.php index eb859f2..584e02d 100644 --- a/database/migrations/2019_05_03_000003_create_subscription_items_table.php +++ b/database/migrations/2019_05_03_000003_create_subscription_items_table.php @@ -4,8 +4,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class extends Migration { /** * Run the migrations. */ diff --git a/src/Cashier.php b/src/Cashier.php index 46abc04..de4b62b 100644 --- a/src/Cashier.php +++ b/src/Cashier.php @@ -2,6 +2,7 @@ namespace Asciisd\Cashier; +use Asciisd\Cashier\Contracts\Billable; use Asciisd\Cashier\Traits\ManagesAppDetails; use Asciisd\Cashier\Traits\ManagesSupportOptions; use Money\Currencies\ISOCurrencies; @@ -9,7 +10,6 @@ use Money\Formatter\IntlMoneyFormatter; use Money\Money; use NumberFormatter; -use Asciisd\Cashier\Contracts\Billable; class Cashier { @@ -55,7 +55,7 @@ class Cashier public static function tapOptions(array $options = []): array { return array_merge([ - 'api_key' => config('cashier.secret'), + 'api_key' => config('cashier.secret'), 'tap_version' => static::TAP_VERSION, ], $options); } diff --git a/src/Concerns/ManagesCustomer.php b/src/Concerns/ManagesCustomer.php index 4a4bd28..fe2b526 100644 --- a/src/Concerns/ManagesCustomer.php +++ b/src/Concerns/ManagesCustomer.php @@ -28,7 +28,60 @@ public function tapId(): ?string */ public function hasTapId(): bool { - return !is_null($this->tap_id); + return ! is_null($this->tap_id); + } + + /** + * Update the underlying Tap customer information for the model. + * + * @param array $options + * @return array|TapCustomer|TapObject + */ + public function updateTapCustomer(array $options = []): TapObject|array|TapCustomer + { + return TapCustomer::update( + $this->tap_id, $options, $this->tapOptions() + ); + } + + /** + * Get the default Tap API options for the current Billable model. + * + * @param array $options + * @return array + */ + public function tapOptions(array $options = []): array + { + return Cashier::tapOptions($options); + } + + /** + * Get the Tap customer instance for the current user or create one. + * + * @param array $options + * @return TapCustomer + * @throws InvalidCustomer + */ + public function createOrGetTapCustomer(array $options = []): TapCustomer + { + if ($this->tap_id) { + return $this->asTapCustomer(); + } + + return $this->createAsTapCustomer($options); + } + + /** + * Get the Tap customer for the model. + * + * @return TapCustomer + * @throws InvalidCustomer + */ + public function asTapCustomer(): TapCustomer + { + $this->assertCustomerExists(); + + return TapCustomer::retrieve($this->tap_id, $this->tapOptions()); } /** @@ -39,7 +92,7 @@ public function hasTapId(): bool */ protected function assertCustomerExists(): void { - if (!$this->tap_id) { + if (! $this->tap_id) { throw InvalidCustomer::nonCustomer($this); } } @@ -47,7 +100,7 @@ protected function assertCustomerExists(): void /** * Create a Tap customer for the given model. * - * @param array $options + * @param array $options * @return TapCustomer * @throws InvalidCustomer */ @@ -73,46 +126,34 @@ public function createAsTapCustomer(array $options = []): TapCustomer return $customer; } - /** - * Update the underlying Tap customer information for the model. - * - * @param array $options - * @return array|TapCustomer|TapObject - */ - public function updateTapCustomer(array $options = []): TapObject|array|TapCustomer + public function tapCustomerFields(): array { - return TapCustomer::update( - $this->tap_id, $options, $this->tapOptions() - ); + return [ + 'first_name' => $this->tapFirstName(), + 'last_name' => $this->tapLastName(), + 'email' => $this->tapEmail(), + 'phone' => $this->tapPhone() + ]; } /** - * Get the Tap customer instance for the current user or create one. + * Get the first name used to create the customer in Tap. * - * @param array $options - * @return TapCustomer - * @throws InvalidCustomer + * @return string */ - public function createOrGetTapCustomer(array $options = []): TapCustomer + public function tapFirstName(): string { - if ($this->tap_id) { - return $this->asTapCustomer(); - } - - return $this->createAsTapCustomer($options); + return $this->first_name; } /** - * Get the Tap customer for the model. + * Get the last name used to create the customer in Tap. * - * @return TapCustomer - * @throws InvalidCustomer + * @return string */ - public function asTapCustomer(): TapCustomer + public function tapLastName(): string { - $this->assertCustomerExists(); - - return TapCustomer::retrieve($this->tap_id, $this->tapOptions()); + return $this->last_name; } /** @@ -134,34 +175,14 @@ public function tapPhone(): array { return [ 'country_code' => $this->phone_code, - 'number' => $this->phone + 'number' => $this->phone ]; } - /** - * Get the first name used to create the customer in Tap. - * - * @return string - */ - public function tapFirstName(): string - { - return $this->first_name; - } - - /** - * Get the last name used to create the customer in Tap. - * - * @return string - */ - public function tapLastName(): string - { - return $this->last_name; - } - /** * Apply a coupon to the billable entity. * - * @param string $coupon + * @param string $coupon * @return void * @throws InvalidCustomer */ @@ -185,25 +206,4 @@ public function preferredCurrency(): string { return config('cashier.currency'); } - - /** - * Get the default Tap API options for the current Billable model. - * - * @param array $options - * @return array - */ - public function tapOptions(array $options = []): array - { - return Cashier::tapOptions($options); - } - - public function tapCustomerFields(): array - { - return [ - 'first_name' => $this->tapFirstName(), - 'last_name' => $this->tapLastName(), - 'email' => $this->tapEmail(), - 'phone' => $this->tapPhone() - ]; - } } diff --git a/src/Concerns/ManagesInvoices.php b/src/Concerns/ManagesInvoices.php index d1f09e1..2f850be 100644 --- a/src/Concerns/ManagesInvoices.php +++ b/src/Concerns/ManagesInvoices.php @@ -18,26 +18,26 @@ public static function tapInvoices($limit = 25): TapObject|array public function createTapInvoice($amount, $trading_account, $currency = 'KWD', $options = []) { return Invoice::create(array_merge([ - "due" => now()->getPreciseTimestamp(3), - "expiry" => now()->addDays(10)->getPreciseTimestamp(3), + "due" => now()->getPreciseTimestamp(3), + "expiry" => now()->addDays(10)->getPreciseTimestamp(3), "customer" => [ "id" => $this->tap_id, ], - "order" => [ - "amount" => $amount, + "order" => [ + "amount" => $amount, "currency" => $currency, - "items" => [ + "items" => [ [ - "amount" => $amount, - "currency" => $currency, + "amount" => $amount, + "currency" => $currency, "description" => "Deposit on account #".$trading_account, - "name" => "Deposit", - "quantity" => 1, + "name" => "Deposit", + "quantity" => 1, ], ], ], - "post" => ['url' => url('/tap/webhook')], - "redirect" => ['url' => url(config('cashier.redirect_url'))], + "post" => ['url' => url('/tap/webhook', secure: true)], + "redirect" => ['url' => url(config('cashier.redirect_url'), secure: true)], ], $options), Cashier::tapOptions()); } diff --git a/src/Concerns/ManagesPaymentMethods.php b/src/Concerns/ManagesPaymentMethods.php index 1c7a420..f5cbb7e 100644 --- a/src/Concerns/ManagesPaymentMethods.php +++ b/src/Concerns/ManagesPaymentMethods.php @@ -15,7 +15,7 @@ trait ManagesPaymentMethods */ public function hasPaymentMethod(): bool { - return (bool) $this->card_brand; + return (bool)$this->card_brand; } /** @@ -23,7 +23,7 @@ public function hasPaymentMethod(): bool */ public function defaultPaymentMethod(): ?string { - if (!$this->hasTapId()) { + if (! $this->hasTapId()) { return null; } diff --git a/src/Concerns/PerformsCharges.php b/src/Concerns/PerformsCharges.php index 8cb3769..c8435d4 100644 --- a/src/Concerns/PerformsCharges.php +++ b/src/Concerns/PerformsCharges.php @@ -18,9 +18,9 @@ trait PerformsCharges * * allowed payment methods is ['src_kw.knet', 'src_all', 'src_card'] * - * @param int $amount - * @param string $paymentMethod - * @param array $options + * @param int $amount + * @param string $paymentMethod + * @param array $options * @return Payment * * @throws PaymentActionRequired @@ -36,16 +36,16 @@ public function charge(int $amount, string $paymentMethod, array $options = []): $options['amount'] = $amount; $options['source'] = ['id' => $paymentMethod]; - if (!$this->hasTapId()) { + if (! $this->hasTapId()) { $this->createAsTapCustomer(); } $options['reference'] = ['transaction' => rand()]; $options['customer'] = ['id' => $this->tap_id]; - $options['redirect'] = ['url' => url(config('cashier.redirect_url'))]; + $options['redirect'] = ['url' => url(config('cashier.redirect_url'), secure: true)]; if (config('cashier.webhook.secret')) { - $options['post'] = ['url' => url('/tap/webhook', secure: false)]; + $options['post'] = ['url' => url('/tap/webhook', secure: true)]; } $payment = new Payment( @@ -60,8 +60,8 @@ public function charge(int $amount, string $paymentMethod, array $options = []): /** * Refund a customer for a charge. * - * @param string $charge - * @param array $options + * @param string $charge + * @param array $options * @return array|Customer|Refund|TapObject */ public function refund(string $charge, array $options = []): TapObject|array|Customer|Refund diff --git a/src/Console/PublishCommand.php b/src/Console/PublishCommand.php index b9ac258..0bbe67a 100644 --- a/src/Console/PublishCommand.php +++ b/src/Console/PublishCommand.php @@ -28,7 +28,7 @@ class PublishCommand extends Command public function handle() { $this->call('vendor:publish', [ - '--tag' => 'cashier-assets', + '--tag' => 'cashier-assets', '--force' => true, ]); } diff --git a/src/Contracts/Billable.php b/src/Contracts/Billable.php index 1105d98..8e597e4 100644 --- a/src/Contracts/Billable.php +++ b/src/Contracts/Billable.php @@ -5,11 +5,16 @@ interface Billable { public function tapOptions(array $options = []): array; + public function tapCustomerFields(): array; public function tapId(): ?string; + public function tapEmail(): string; + public function tapPhone(): array; + public function tapFirstName(): string; + public function tapLastName(): string; -} \ No newline at end of file +} diff --git a/src/Events/TapChargeHandled.php b/src/Events/TapChargeHandled.php index 002fb25..2d703e6 100644 --- a/src/Events/TapChargeHandled.php +++ b/src/Events/TapChargeHandled.php @@ -18,7 +18,7 @@ class TapChargeHandled /** * Create a new event instance. * - * @param TapWebhookRequest $payload + * @param TapWebhookRequest $payload * @return void */ public function __construct(TapWebhookRequest $payload) diff --git a/src/Events/TapReceiptSeen.php b/src/Events/TapReceiptSeen.php index 18c5ad9..d1db1ef 100644 --- a/src/Events/TapReceiptSeen.php +++ b/src/Events/TapReceiptSeen.php @@ -5,7 +5,6 @@ use Asciisd\Cashier\Payment; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; -use Tap\Charge; class TapReceiptSeen { @@ -19,7 +18,7 @@ class TapReceiptSeen /** * Create a new event instance. * - * @param Payment $payment + * @param Payment $payment * @return void */ public function __construct(Payment $payment) diff --git a/src/Events/WebhookHandled.php b/src/Events/WebhookHandled.php index dcbba34..59b76e0 100644 --- a/src/Events/WebhookHandled.php +++ b/src/Events/WebhookHandled.php @@ -18,7 +18,7 @@ class WebhookHandled /** * Create a new event instance. * - * @param TapWebhookRequest $payload + * @param TapWebhookRequest $payload * @return void */ public function __construct(TapWebhookRequest $payload) diff --git a/src/Events/WebhookReceived.php b/src/Events/WebhookReceived.php index 06c4f02..9fd8b8e 100644 --- a/src/Events/WebhookReceived.php +++ b/src/Events/WebhookReceived.php @@ -20,7 +20,7 @@ class WebhookReceived /** * Create a new event instance. * - * @param TapWebhookRequest $payload + * @param TapWebhookRequest $payload * @return void */ public function __construct(TapWebhookRequest $payload) diff --git a/src/Exceptions/CustomerAlreadyCreated.php b/src/Exceptions/CustomerAlreadyCreated.php index bf9fcdb..89e8cda 100644 --- a/src/Exceptions/CustomerAlreadyCreated.php +++ b/src/Exceptions/CustomerAlreadyCreated.php @@ -10,7 +10,7 @@ class CustomerAlreadyCreated extends Exception /** * Create a new CustomerAlreadyCreated instance. * - * @param Model $owner + * @param Model $owner * @return static */ public static function exists($owner) diff --git a/src/Exceptions/IncompletePayment.php b/src/Exceptions/IncompletePayment.php index 26b49fa..aad7243 100644 --- a/src/Exceptions/IncompletePayment.php +++ b/src/Exceptions/IncompletePayment.php @@ -2,8 +2,8 @@ namespace Asciisd\Cashier\Exceptions; -use Exception; use Asciisd\Cashier\Payment; +use Exception; use Throwable; class IncompletePayment extends Exception @@ -16,10 +16,10 @@ class IncompletePayment extends Exception /** * Create a new IncompletePayment instance. * - * @param Payment $payment - * @param string $message - * @param int $code - * @param Throwable|null $previous + * @param Payment $payment + * @param string $message + * @param int $code + * @param Throwable|null $previous * @return void */ public function __construct(Payment $payment, $message = '', $code = 0, Throwable $previous = null) diff --git a/src/Http/Controllers/PaymentController.php b/src/Http/Controllers/PaymentController.php index 9d3e6fb..d36166a 100644 --- a/src/Http/Controllers/PaymentController.php +++ b/src/Http/Controllers/PaymentController.php @@ -7,7 +7,6 @@ use Asciisd\Cashier\Cashier; use Asciisd\Cashier\Payment; use Illuminate\Http\Request; -use Illuminate\View\View; use Tap\Charge; class PaymentController @@ -18,7 +17,7 @@ class PaymentController public function show(Request $request) { return view('cashier::receipt', [ - 'payment' => new Payment( + 'payment' => new Payment( Charge::retrieve($request->tap_id, Cashier::tapOptions()) ), 'redirect' => request('redirect'), diff --git a/src/Http/Controllers/ReceiptController.php b/src/Http/Controllers/ReceiptController.php index 8b82b57..62832b7 100644 --- a/src/Http/Controllers/ReceiptController.php +++ b/src/Http/Controllers/ReceiptController.php @@ -6,8 +6,6 @@ use Asciisd\Cashier\Events\TapReceiptSeen; use Asciisd\Cashier\Http\Requests\ReceiptRequest; use Asciisd\Cashier\Payment; -use Illuminate\Validation\UnauthorizedException; -use Illuminate\View\View; use Tap\Charge; class ReceiptController diff --git a/src/Http/Controllers/WebhookController.php b/src/Http/Controllers/WebhookController.php index dbea33e..84dbd68 100644 --- a/src/Http/Controllers/WebhookController.php +++ b/src/Http/Controllers/WebhookController.php @@ -53,12 +53,29 @@ public function handleWebhook(TapWebhookRequest $request) return $this->missingMethod(); } + /** + * Handle calls to missing methods on the controller. + */ + protected function missingMethod($parameters = []) + { + logger('Missing Method', $parameters); + return new Response; + } + protected function handleCharge(TapWebhookRequest $request) { TapChargeHandled::dispatch($request); return $this->successMethod(); } + /** + * Handle successful calls on the controller. + */ + protected function successMethod($parameters = []) + { + return new Response('Webhook Handled', 200); + } + /** * Handle payment action required for invoice. */ @@ -88,21 +105,4 @@ protected function getUserByTapId($tapId) { return Cashier::findBillable($tapId); } - - /** - * Handle successful calls on the controller. - */ - protected function successMethod($parameters = []) - { - return new Response('Webhook Handled', 200); - } - - /** - * Handle calls to missing methods on the controller. - */ - protected function missingMethod($parameters = []) - { - logger('Missing Method', $parameters); - return new Response; - } } diff --git a/src/Http/Requests/TapWebhookRequest.php b/src/Http/Requests/TapWebhookRequest.php index b24be4f..5b459ea 100644 --- a/src/Http/Requests/TapWebhookRequest.php +++ b/src/Http/Requests/TapWebhookRequest.php @@ -37,12 +37,12 @@ public function rules(): array logger('TapWebhookRequest | rules', request()->all()); return [ - 'id' => 'required', - 'amount' => 'required', - 'currency' => 'required', - 'reference.gateway' => 'required', - 'reference.payment' => 'required', - 'status' => 'required', + 'id' => 'required', + 'amount' => 'required', + 'currency' => 'required', + 'reference.gateway' => 'required', + 'reference.payment' => 'required', + 'status' => 'required', 'transaction.created' => 'required', ]; } diff --git a/src/Payment.php b/src/Payment.php index 6614188..8e9d13f 100644 --- a/src/Payment.php +++ b/src/Payment.php @@ -67,7 +67,7 @@ public function requiresAction(): bool */ public function actionUrl(): string { - return $this->charge->transaction->url ?? url('/'); + return $this->charge->transaction->url ?? url('/', secure: true); } /** @@ -154,7 +154,7 @@ public function validate(): void /** * Get a Carbon date for the invoice. * - * @param null $timezone + * @param null $timezone * @return Carbon */ public function date($timezone = null): Carbon @@ -187,7 +187,7 @@ public function owner(): ?Billable /** * Dynamically get values from the Tap Charge. * - * @param string $key + * @param string $key * @return mixed */ public function __get(string $key) diff --git a/src/Providers/CashierServiceProvider.php b/src/Providers/CashierServiceProvider.php index 244478f..2d70655 100644 --- a/src/Providers/CashierServiceProvider.php +++ b/src/Providers/CashierServiceProvider.php @@ -33,43 +33,6 @@ public function boot(): void ); } - /** - * Register the application services. - */ - public function register(): void - { - $this->configure(); - $this->bindLogger(); - $this->registerServices(); - $this->registerCommands(); - - if (!class_exists('Cashier')) { - class_alias('Asciisd\Cashier\Cashier', 'Cashier'); - } - } - - /** - * Set up the configuration for Cashier. - */ - protected function configure(): void - { - $this->mergeConfigFrom( - __DIR__.'/../../config/cashier.php', 'cashier' - ); - } - - /** - * Bind the Stripe logger interface to the Cashier logger. - */ - protected function bindLogger(): void - { - $this->app->bind(LoggerInterface::class, function ($app) { - return new Logger( - $app->make('log')->channel(config('cashier.logger')) - ); - }); - } - /** * Register the Tap logger. * @throws BindingResolutionException @@ -88,9 +51,9 @@ protected function registerRoutes(): void { if (Cashier::$registersRoutes) { Route::group([ - 'prefix' => config('cashier.path'), + 'prefix' => config('cashier.path'), 'namespace' => 'Asciisd\Cashier\Http\Controllers', - 'as' => 'cashier.', + 'as' => 'cashier.', ], function () { $this->loadRoutesFrom(__DIR__.'/../../routes/web.php'); }); @@ -144,6 +107,48 @@ protected function registerPublishing(): void } } + /** + * Register the application services. + */ + public function register(): void + { + $this->configure(); + $this->bindLogger(); + $this->registerServices(); + $this->registerCommands(); + + if (! class_exists('Cashier')) { + class_alias('Asciisd\Cashier\Cashier', 'Cashier'); + } + } + + /** + * Set up the configuration for Cashier. + */ + protected function configure(): void + { + $this->mergeConfigFrom( + __DIR__.'/../../config/cashier.php', 'cashier' + ); + } + + /** + * Bind the Stripe logger interface to the Cashier logger. + */ + protected function bindLogger(): void + { + $this->app->bind(LoggerInterface::class, function ($app) { + return new Logger( + $app->make('log')->channel(config('cashier.logger')) + ); + }); + } + + public function registerServices() + { + // + } + /** * Register the Horizon Artisan commands. */ @@ -156,9 +161,4 @@ protected function registerCommands(): void ]); } } - - public function registerServices() - { - // - } } diff --git a/src/Traits/Downloadable.php b/src/Traits/Downloadable.php index 7677625..cad1c34 100644 --- a/src/Traits/Downloadable.php +++ b/src/Traits/Downloadable.php @@ -11,14 +11,27 @@ trait Downloadable { /** - * Get the View instance for the invoice. + * Create an invoice download response. */ - public function view(array $data): \Illuminate\Contracts\View\View + public function download(array $data): Response { - return View::make('cashier::pdf_receipt', array_merge($data, [ - 'invoice' => $this, - 'owner' => $this->owner() - ])); + $filename = $data['product'].'_'.$this->date()->month.'_'.$this->date()->year; + + return $this->downloadAs($filename, $data); + } + + /** + * Create an invoice download response with a specific filename. + */ + public function downloadAs(string $filename, array $data): Response + { + return new Response($this->pdf($data), 200, [ + 'Content-Description' => 'File Transfer', + 'Content-Disposition' => 'attachment; filename="'.$filename.'.pdf"', + 'Content-Transfer-Encoding' => 'binary', + 'Content-Type' => 'application/pdf', + 'X-Vapor-Base64-Encode' => 'True', + ]); } /** @@ -26,7 +39,7 @@ public function view(array $data): \Illuminate\Contracts\View\View */ public function pdf(array $data): string { - if (!defined('DOMPDF_ENABLE_AUTOLOAD')) { + if (! defined('DOMPDF_ENABLE_AUTOLOAD')) { define('DOMPDF_ENABLE_AUTOLOAD', false); } @@ -39,26 +52,13 @@ public function pdf(array $data): string } /** - * Create an invoice download response. - */ - public function download(array $data): Response - { - $filename = $data['product'].'_'.$this->date()->month.'_'.$this->date()->year; - - return $this->downloadAs($filename, $data); - } - - /** - * Create an invoice download response with a specific filename. + * Get the View instance for the invoice. */ - public function downloadAs(string $filename, array $data): Response + public function view(array $data): \Illuminate\Contracts\View\View { - return new Response($this->pdf($data), 200, [ - 'Content-Description' => 'File Transfer', - 'Content-Disposition' => 'attachment; filename="'.$filename.'.pdf"', - 'Content-Transfer-Encoding' => 'binary', - 'Content-Type' => 'application/pdf', - 'X-Vapor-Base64-Encode' => 'True', - ]); + return View::make('cashier::pdf_receipt', array_merge($data, [ + 'invoice' => $this, + 'owner' => $this->owner() + ])); } } diff --git a/src/Traits/ManagesAppDetails.php b/src/Traits/ManagesAppDetails.php index a081fc8..e61da61 100644 --- a/src/Traits/ManagesAppDetails.php +++ b/src/Traits/ManagesAppDetails.php @@ -31,28 +31,28 @@ public static function product(): string } /** - * Get the invoice meta information, such as product, etc. + * Get the invoice data payload for the given billable entity. */ - public static function generateInvoicesWith(): array + public static function invoiceDataFor(mixed $billable): array { return array_merge([ - 'vendor' => '', - 'product' => '', - 'street' => '', - 'location' => '', - 'phone' => '', - ], static::$details); + 'vendor' => 'Vendor', + 'product' => 'Product' + ], static::generateInvoicesWith()); } /** - * Get the invoice data payload for the given billable entity. + * Get the invoice meta information, such as product, etc. */ - public static function invoiceDataFor(mixed $billable): array + public static function generateInvoicesWith(): array { return array_merge([ - 'vendor' => 'Vendor', - 'product' => 'Product' - ], static::generateInvoicesWith()); + 'vendor' => '', + 'product' => '', + 'street' => '', + 'location' => '', + 'phone' => '', + ], static::$details); } /** diff --git a/src/Traits/ManagesSupportOptions.php b/src/Traits/ManagesSupportOptions.php index 934d2b8..261dc3f 100644 --- a/src/Traits/ManagesSupportOptions.php +++ b/src/Traits/ManagesSupportOptions.php @@ -16,7 +16,7 @@ trait ManagesSupportOptions */ public static function hasSupportAddress(): bool { - return !is_null(static::$sendsSupportEmailsTo); + return ! is_null(static::$sendsSupportEmailsTo); } /** diff --git a/stubs/CashierServiceProvider.stub b/stubs/CashierServiceProvider.stub index 94019d6..2a1f153 100644 --- a/stubs/CashierServiceProvider.stub +++ b/stubs/CashierServiceProvider.stub @@ -11,13 +11,13 @@ class CashierServiceProvider extends ServiceProvider * Your application and company details. */ protected array $details = [ - 'vendor' => 'Your Company', - 'product' => 'Your Product', - 'street' => 'PO Box 111', - 'location' => 'Your Town, NY 12345', - 'phone' => '555-555-5555', - 'email' => 'email@example.com', - 'url' => 'https://asciisd.com', + 'vendor' => 'Your Company', + 'product' => 'Your Product', + 'street' => 'PO Box 111', + 'location' => 'Your Town, NY 12345', + 'phone' => '555-555-5555', + 'email' => 'email@example.com', + 'url' => 'https://asciisd.com', 'primary_color' => '#F04D23' ]; diff --git a/tests/Feature/ChargesTest.php b/tests/Feature/ChargesTest.php index 6674f9b..8407495 100644 --- a/tests/Feature/ChargesTest.php +++ b/tests/Feature/ChargesTest.php @@ -30,7 +30,7 @@ public function test_charging_may_require_an_extra_action() try { $user->charge(100, 'src_card'); - $this->fail('Expected exception ' . PaymentActionRequired::class . ' was not thrown.'); + $this->fail('Expected exception '.PaymentActionRequired::class.' was not thrown.'); } catch (PaymentActionRequired $e) { // Assert that the payment needs an extra action. $this->assertTrue($e->payment->requiresAction()); diff --git a/tests/Feature/FeatureTestCase.php b/tests/Feature/FeatureTestCase.php index c58f87b..655e7b3 100644 --- a/tests/Feature/FeatureTestCase.php +++ b/tests/Feature/FeatureTestCase.php @@ -8,6 +8,7 @@ use Orchestra\Testbench\Concerns\WithLaravelMigrations; use Tap\ApiResource; use Tap\Card; +use Tap\Customer; use Tap\Exception\InvalidRequestException; use Tap\Tap; use Tap\TapObject; @@ -23,35 +24,23 @@ abstract class FeatureTestCase extends TestCase protected static string $tapPrefix = 'cashier-test-'; protected static array $test_card = [ - 'card' => [ - 'number' => '5111111111111118', + 'card' => [ + 'number' => '5111111111111118', 'exp_month' => '01', - 'exp_year' => '39', - 'cvc' => '100', - 'name' => 'Amr Ahmed Asciisd', - 'address' => [ + 'exp_year' => '39', + 'cvc' => '100', + 'name' => 'Amr Ahmed Asciisd', + 'address' => [ 'country' => 'Kuwait', - 'line1' => 'Salmiya, 21', - 'city' => 'Kuwait city', - 'street' => 'Salim', - 'avenue' => 'Gulf', + 'line1' => 'Salmiya, 21', + 'city' => 'Kuwait city', + 'street' => 'Salim', + 'avenue' => 'Gulf', ], ], 'client_ip' => '192.168.1.20' ]; - protected function setUp(): void - { - if (!getenv('TAP_API_KEY')) { - $this->markTestSkipped('Tap API key not set.'); - } - - parent::setUp(); - - // Delay consecutive tests to prevent Tap rate limiting issues. - sleep(2); - } - public static function setUpBeforeClass(): void { parent::setUpBeforeClass(); @@ -68,16 +57,28 @@ protected static function deleteTapResource(ApiResource $resource) } } + protected function setUp(): void + { + if (! getenv('TAP_API_KEY')) { + $this->markTestSkipped('Tap API key not set.'); + } + + parent::setUp(); + + // Delay consecutive tests to prevent Tap rate limiting issues. + sleep(2); + } + protected function createCustomer($description = 'amr', array $options = []): User { return User::create(array_merge([ - 'email' => "{$description}@cashier-test.com", + 'email' => "{$description}@cashier-test.com", 'first_name' => 'Amr', - 'last_name' => 'Ahmed', - 'name' => 'Amr Ahmed', - 'phone' => '010123456789', + 'last_name' => 'Ahmed', + 'name' => 'Amr Ahmed', + 'phone' => '010123456789', 'phone_code' => '002', - 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', + 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', ], $options)); } @@ -102,7 +103,7 @@ protected function createCard($customer_id): TapObject /** * create token from test card * - * @return array|\Tap\Customer|TapObject + * @return array|Customer|TapObject */ protected function createToken() { diff --git a/tests/Fixtures/User.php b/tests/Fixtures/User.php index 9e08dc4..cc67345 100644 --- a/tests/Fixtures/User.php +++ b/tests/Fixtures/User.php @@ -2,9 +2,9 @@ namespace Asciisd\Cashier\Tests\Fixtures; +use Asciisd\Cashier\Billable; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; -use Asciisd\Cashier\Billable; class User extends Authenticatable implements \Asciisd\Cashier\Contracts\Billable { diff --git a/tests/TestCase.php b/tests/TestCase.php index d53bd75..07aad4f 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -2,11 +2,11 @@ namespace Asciisd\Cashier\Tests; +use Asciisd\Cashier\Cashier; use Asciisd\Cashier\Providers\CashierServiceProvider; +use Asciisd\Cashier\Tests\Fixtures\User; use Illuminate\Support\Str; use InvalidArgumentException; -use Asciisd\Cashier\Cashier; -use Asciisd\Cashier\Tests\Fixtures\User; use Orchestra\Testbench\Concerns\WithWorkbench; use Orchestra\Testbench\TestCase as OrchestraTestCase; @@ -25,7 +25,7 @@ protected function getEnvironmentSetUp($app) { $apiKey = config('cashier.secret'); - if ($apiKey && !Str::startsWith($apiKey, 'sk_test_')) { + if ($apiKey && ! Str::startsWith($apiKey, 'sk_test_')) { throw new InvalidArgumentException('Tests may not be run with a production Tap key.'); } diff --git a/tests/Unit/CustomerTest.php b/tests/Unit/CustomerTest.php index 58e036a..24136ea 100644 --- a/tests/Unit/CustomerTest.php +++ b/tests/Unit/CustomerTest.php @@ -2,7 +2,6 @@ namespace Asciisd\Cashier\Tests\Unit; -use Carbon\Carbon; use Asciisd\Cashier\Exceptions\InvalidCustomer; use Asciisd\Cashier\Tests\Fixtures\User; use PHPUnit\Framework\TestCase;