How to get transaction id after successful subscription - laravel

I am working on a platform offering services. When creating a new subscription, a new transaction for the first billing is created. How can I access the transactions id?
I have a form with Braintree's Drop-in UI and my backend looks currently like this:
if (!auth()->user()->subscribed('main')) {
$subscription = auth()->user()->newSubscription('main', 'membership-monthly')->create($request->payment_method_nonce, []);
dd($subscription);
}
This successfully creates a new subscription!
Now I want to access this subscription's first billing transaction's id.
How can I achieve this?

Probably, you should provide a second parameter to create function,
try this:
if (!auth()->user()->subscribed('main')) {
$payload = array();
$subscription = auth()
->user()
->newSubscription('main', 'membership-monthly')
->create($request->payment_method_nonce, $payload);
dd($subscription);
dd($payload);
}

From the Laravel Cashier documentation the database schema looks like this:
Schema::create('subscriptions', function ($table) {
$table->increments('id');
$table->unsignedInteger('user_id');
$table->string('name');
$table->string('braintree_id');
$table->string('braintree_plan');
$table->integer('quantity');
$table->timestamp('trial_ends_at')->nullable();
$table->timestamp('ends_at')->nullable();
$table->timestamps();
});
I would assume to get the subscription in your case would be similar to $subscription->braintree_id

If you have an relation between subscription and transactions you need access so :
foreach($subscription->transactions() as $transaction){
//here you access yo transactions id
dd($transaction);
}
I hope that i could help you

Related

How to Hide Required Parameters Laravel Route

So I have a booking system. Basically it has this route
localhost:8080/itpr/booking/details/{$bookingId}
Where $bookingId = is the id in the booking_table.
My question, is there a way to hide the $bookingId from my routes from the the user? I don't want other users to be able to access to other booking transaction just by changing the $bookingId in the URL.
The easiest way to achieve this is by submiting your post request via AJAX. But if you are not comfortable using ajax request. You can create a policy that allows only the owner of those booking to make change: see code below.
php artisan make:policy BookingPolicy --model=Booking
Register the policy in your AuthServiceProvider: use App\Policies\BookingPolicy;
protected $policies = [
Booking::class => BookingPolicy::class,
];
Now inside your BookingPolicy then define policy for any method that you want to restrict users from. For example let make sure onl the authenticated user(owner) can update his booking. In this scenario we are assuming that you have user_id column in your Booking table and you have relationship between these 2 tables
public function update(?User $user, Booking $booking)
{
return $user->id === $booking->user_id;
}
Now in your BookingController you can call implement the authorizing actions(can or cant)
public function update(Request $request, $id) {
if ($user->can('update', $booking)) {
// Executes the "create" method on the relevant policy...
}
}
Hopefully this will help :)
have you considered using $table->uuid('id'); for PK? So that the users are not going to guess other bookings easily.
Add a check in your route if the booking ID is one that belongs to the user trying to access the ID. If not, redirect.
Otherwise, provide a dashboard like route showing the user bookings. then make an asynchronous call on the click using your userID/bookingID send that data to a template with a route that is something like your booking/details
Please Check Laravel Policy and define rules to check if the booking id is associated with the current user or not and . which can help you to secure the booking detail from unauthorized user.

way to insert a new record, with cashier subscription?

I am searching the web today to see if I can somehow be able to add a new record to some tables whenever the user memberships renew.
let's say we have an app have (users, notifications, subscriptions ) tabes.
when he subscribe the first time, I can add a new record in notification table within the same controller, but what if I want every time he renews his subscription a new instance can be added in the notification table?
Eloquent Model Event
is the way to go, I believe.
Or if the logic is really simple, you can define it in your model class.
/**
* The "booting" method of the model.
*
* #param Builder
*/
protected static function boot()
{
parent::boot();
static::updated(function (Subscription $subscription) {
// your subscription logic here...
});
}

Impementing global app settings for Laravel API?

I wish to implement a few global app settings, e.g. App name, first day of the week, and other feature flags. The end goal is to have these be fetched and edited by administrators through the API.
What might be the most convenient way of doing this? I've experimented with using a Settings model to store key-value pairs, but this doesn't make sense to me since the desired settings should be hard coded and won't change, and seeding the Settings table doesn't sound ideal. Thanks in advance!
You can access App name from Laravel provided config function.
$appName = config('app.name');
// This value is retrieved from .env file of APP_NAME=
If you have to store multiple values related with the week, you can create a new config file week.php
//config/week.php
return [
...
'first_day_of_the_week' => 0
];
In order to retrieve the first_day_of_the_week, you can use the same function config
$firstDayOfTheWeek = config('week.first_day_of_the_week')
Similar to other essential flags, you can create a new config file.
You can later cache your config variables using the following command.
php artisan config:cache
You can also create a Helper class inside any preferred location inside the laravel project. I keep my helper class inside App\Helpers.
<?php
namespace App\Helpers;
use Carbon\Carbon;
class DateHelpers
{
public const DATE_RANGE_SEPARATOR = ' to ';
public static function getTodayFormat($format = 'Y-m-d')
{
$today = Carbon::now();
$todayDate = Carbon::parse($today->format($format));
return $todayDate;
}
....
}
If you need to retrieve the method value in the Laravel project, you can access by
$getTodayDateFormat = App\Helpers\DateHelpers::getTodayFormat();
EDIT 1:
Based on the question description. You need to create one row in the settings table.
//create_settings_table.php Migration File
public function up()
{
// Create table for storing roles
Schema::create('settings', function (Blueprint $table) {
$table->increments('id');
$table->string('app_name')->default("My App Name");
$table->unsignedInteger('first_day_of_the_week')->default(1);
....
$table->timestamps();
});
}
You only need one row of the settings table to retrieve/update the default value.
//Retrieving the first day
$first_day_of_the_week = App\Setting::first()->first_day_of_the_week;
//Updating the first day
...
$first_day_of_the_week = request('first_day_of_the_week');
App\Setting::first()->update([
'first_day_of_the_week' => $first_day_of_the_week
]);

Laravel cashier `$user->subscribed()` returning true when no subscription exists

My code is simple:
if($user->subscribed('main')){
$user->subscription('main')->cancel();
}
I get this response:
Stripe \ Error \ InvalidRequest
No such subscription: sub_EQTvxKjit2Ak6i
The subscription was in fact previously cancelled, so it shouldn't be giving a true response.
I tried returning $user->subscribed('main') and it came back as true.
This user has other subscriptions, but 'main' is not active.
Am I missing something?
Update Cashier v13.4
You can first sync the database entry with Stripe using:
optional($user->subscription('main'))->syncStripeStatus();
Then call
if ($user->subscribed('main')) { ... }
$user->subscribed() only checks the database for subscription status--it doesn't query the Stripe API at all. But when you try to cancel that subscription, then it queries the API.
So that could produce an error like this if your database is out of sync with your data in Stripe. Maybe your database has subscription from Stripe test mode, but you're querying the Stripe production API? Or vice versa?
If you read Billable trait then you will find this function there
public function subscribed($subscription = 'default', $plan = null)
{
$subscription = $this->subscription($subscription);
if (is_null($subscription)) {
return false;
}
if (is_null($plan)) {
return $subscription->valid();
}
return $subscription->valid() &&
$subscription->stripe_plan === $plan;
}
This function only checks subscription record exists in subscriptions table or not.
According to above function if subscription does not exist then it will return false.
Make sure you are not doing any mistake.

Destroy model instance with all dependances in Laravel

I have two models with one-to-many connection. Let it be, for example, User ans UserComment models. When I'm calling User::destroy method, I also want to destroy each UserComment instance with user_id field equal to id of destroyed User. I may simply overload User::destroy method, but I wonder if there is better ways to achieve this.
Yes, the best way (or more efficient) is to do it through migrations. Let's have a little example with User and UserComment. Leave user migration as is. For UserComment do:
Schema::create('usercomments', function(Blueprint $table){
$table->integer('user_id')->unsigned();
....
$table->foreign('user_id', 'fk_user_id')
->references('id')
->on('users')
->onDelete('cascade')
->onUpdate('cascade'); //not needed in your case.
});
Ok, I haven't used this for a long time, so you may check the syntax online. But that's the gist of it.
When you delete a user, all his comments will be delete as well automatically, by your DB.
Goodluck mate!
I would use the database for this (as suggested above by EddyTheDove), but IF you don't want to use the database for this... you can add something to the deleting event of the User model.
EXAMPLE:
protected static function boot() {
parent::boot();
static::deleting(function($user) {
$user->user_comments()->delete();
});
}

Resources