Is is because the field does not have a default value?
Error message when submitting PayPal payment
Hi,
I created a user dashboard (for the customer), an admin dashboard (can also sell), and a vendor (can also sell) dashboard. When submitting the PayPal payment (via my sandbox account) I'm getting the error: SQLSTATE[HY000]: General error: 1364 Field 'seller' doesn't have a default value.
Grateful for your guidance on this issue.
This is the PaymentController:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\GeneralSetting;
use App\Models\Order;
use App\Models\OrderProduct;
use App\Models\PaypalSetting;
use App\Models\Product;
use App\Models\Transaction;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
use Srmklive\PayPal\Services\PayPal as PayPalClient;
class PaymentController extends Controller
{
public function index()
{
// Check if the user has selected a shipping address
if (!Session::has('address')) {
return redirect()->route('user.checkout');
}
return view('frontend.index');
}
public function storeOrder($paymentMethod, $paymentStatus, $transactionId, $paidAmount, $paidCurrencyName)
{
$setting = GeneralSetting::first();
// Create a new Order
$order = new Order();
$order->invoice_id = rand(1, 999999); // Generate a random invoice ID
$order->user_id = Auth::user()->id;
$order->sub_total = getCartTotal(); // Assuming getCartTotal() returns cart subtotal
$order->amount = getFinalPayableAmount(); // Assuming this includes tax, shipping, etc.
$order->currency_name = $setting->currency_name;
$order->currency_icon = $setting->currency_icon;
$order->product_qty = \Cart::content()->count();
$order->payment_method = $paymentMethod;
$order->payment_status = $paymentStatus;
$order->order_address = json_encode(Session::get('address')); // Store the address as JSON
$order->order_status = 'pending'; // Order initially pending
$order->save();
// Store the order products (without updating product quantity)
foreach (\Cart::content() as $item) {
$product = Product::find($item->id);
$orderProduct = new OrderProduct();
$orderProduct->order_id = $order->id;
$orderProduct->product_id = $product->id;
$orderProduct->vendor_id = $product->vendor_id;
$orderProduct->product_name = $product->name;
$orderProduct->variants = json_encode($item->options->variants);
$orderProduct->variant_total = $item->options->variants_total;
$orderProduct->unit_price = $item->price;
$orderProduct->qty = $item->qty;
$orderProduct->save();
}
// Store the transaction details
$transaction = new Transaction();
$transaction->order_id = $order->id;
$transaction->transaction_id = $transactionId;
$transaction->payment_method = $paymentMethod;
$transaction->amount = getFinalPayableAmount(); // Amount in platform's currency
$transaction->amount_real_currency = $paidAmount; // Amount paid in PayPal's currency
$transaction->amount_real_currency_name = $paidCurrencyName; // Currency name
$transaction->save();
}
public function clearSession()
{
\Cart::destroy(); // Clear the shopping cart
Session::forget('address'); // Remove the address from the session
}
public function paypalConfig()
{
$paypalSetting = PaypalSetting::first();
$config = [
'mode' => $paypalSetting->mode === 1 ? 'live' : 'sandbox', // Check if live or sandbox
'sandbox' => [
'client_id' => $paypalSetting->client_id,
'client_secret' => $paypalSetting->secret_key,
'app_id' => '',
],
'live' => [
'client_id' => $paypalSetting->client_id,
'client_secret' => $paypalSetting->secret_key,
'app_id' => '',
],
'payment_action' => 'Sale',
'currency' => $paypalSetting->currency_name, // Ensure the correct currency is set
'notify_url' => '',
'locale' => 'en_US',
'validate_ssl' => true,
];
return $config;
}
public function payWithPaypal()
{
// Configure PayPal API settings
$config = $this->paypalConfig();
$paypalSetting = PaypalSetting::first();
// Initialize the PayPal client
$provider = new PayPalClient($config);
$provider->getAccessToken();
// Calculate the payable amount with the currency rate
$total = getFinalPayableAmount(); // Total amount from the cart including tax, shipping, etc.
$payableAmount = round($total * $paypalSetting->currency_rate, 2);
$response = $provider->createOrder([
"intent" => "CAPTURE",
"application_context" => [
"return_url" => route('user.paypal.success'),
"cancel_url" => route('user.paypal.cancel'),
],
"purchase_units" => [
[
"amount" => [
"currency_code" => $config['currency'],
"value" => $payableAmount
]
]
]
]);
// Handle the response from PayPal
if (isset($response['id']) && $response['id'] != null) {
foreach ($response['links'] as $link) {
if ($link['rel'] === 'approve') {
return redirect()->away($link['href']); // Redirect user to PayPal
}
}
} else {
// Log error and redirect to cancel page
\Log::error('PayPal API Error: ', $response);
return redirect()->route('user.paypal.cancel');
}
}
public function paypalSuccess(Request $request)
{
// Handle PayPal success after payment
$config = $this->paypalConfig();
$provider = new PayPalClient($config);
$provider->getAccessToken();
$response = $provider->capturePaymentOrder($request->token);
if (isset($response['status']) && $response['status'] == 'COMPLETED') {
// Calculate the final amount
$paypalSetting = PaypalSetting::first();
$total = getFinalPayableAmount(); // Total amount from cart
$paidAmount = round($total * $paypalSetting->currency_rate, 2);
// Store the order and transaction details
$this->storeOrder('paypal', 1, $response['id'], $paidAmount, $paypalSetting->currency_name);
// Clear the cart and session
$this->clearSession();
// Redirect to thank you page
return redirect()->route('user.vielen-dank');
}
// If payment fails, redirect to cancel page
return redirect()->route('user.paypal.cancel');
}
public function paypalCancel()
{
// Handle PayPal cancellation
toastr('Something went wrong, please try again later!', 'error', 'Error');
return redirect()->route('user.payment');
}
public function vielenDank()
{
// Render the thank you page
return view('frontend.vielen-dank');
}
}
This is the CheckoutController:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\UserAddress;
use App\Models\VendorAddress;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
class CheckOutController extends Controller
{
public function checkout()
{
$userId = Auth::user()->id;
$userAddresses = UserAddress::where('user_id', $userId)->get();
$vendorAddresses = VendorAddress::where('user_id', $userId)->get();
$addresses = $userAddresses->merge($vendorAddresses);
return view('frontend.checkout', compact('addresses'));
}
public function checkOutFormSubmit(Request $request)
{
$request->validate([
'shipping_address_id' => ['required', 'integer'],
'address_type' => ['required', 'string', 'in:user,vendor'] // New field to determine the type of address
]);
if ($request->address_type === 'user') {
$address = UserAddress::findOrFail($request->shipping_address_id)->toArray();
} else {
$address = VendorAddress::findOrFail($request->shipping_address_id)->toArray();
}
if ($address) {
Session::put('address', $address);
}
return response(['status' => 'success', 'redirect_url' => route('user.payment')]);
}
}
This is the checkout.blade.php:
@extends('frontend.master')
@section('title', 'Bestellung')
@section('content')
<!-- ======= Page Heading ======= -->
<div class="page-heading-warenkorb">
<h2>Bestellung</h2>
</div>
<!-- ======= Checkout ======= -->
<div class="checkout">
<div class="bestellung-wrapper">
<h2>Shipping Details</h2>
<form action="{{ route('checkout.submit') }}" method="POST">
@csrf
<!-- ======= Address ======= -->
@foreach ($addresses as $address)
<div class="address-row">
<div class="checkout-single-address">
<div class="form-check">
<input class="form-check-input shipping-address" data-id="{{ $address->id }}" type="radio"
name="address_id" id="address_{{ $address->id }}">
<label class="form-check-label" for="address_{{ $address->id }}">
Select Address
</label>
</div>
<ul>
<li><span>Name:</span> {{ $address->name }} </li>
<li><span>Address:</span> {{ $address->address }} </li>
<li><span>City:</span> {{ $address->city }} </li>
<li><span>Zip Code:</span> {{ $address->zip }}</li>
<li><span>Country:</span> {{ $address->country }}</li>
</ul>
</div>
</div>
@endforeach
<!-- PayPal Button -->
<a class="payment-button" href="{{ route('user.paypal.payment') }}">Mit PayPal bezahlen</a>
<!-- Back to Cart Link -->
<a href="{{ route('cart') }}" class="back-to-cart">
<i class="bi bi-arrow-left"></i> Zurück zum Warenkorb
</a>
</form>
</div>
<!-- ======= Summary ======= -->
<div class="checkout-summary">
<div class="summary-total-items">
<span class="total-items">Warenkorb-Summe</span>
</div>
<div class="summary-subtotal">
<div class="subtotal-title">Zwischensumme</div>
<div class="subtotal-value final-value" id="basket-subtotal">
€ {{ getCartTotal() }}
</div>
<div class="versand-land">Versand nur innerhalb Österreich möglich</div>
</div>
<div class="summary-total">
<div class="total-title">Gesamtsumme</div>
<div class="tax">Einschließlich € 17,00 MwSt. 20 % AT</div>
<div class="total-value final-value" id="basket-total">€ {{ getCartTotalWithTax() }}</div>
<div class="terms">
<input type="checkbox" id="termsCheckbox">
<label for="termsCheckbox">Ich habe die AGBs gelesen und verstanden</label>
</div>
</div>
</div>
</div>
@endsection
This is the CartController:
<?php
namespace App\Http\Controllers;
use App\Models\Product;
use Illuminate\Http\Request;
use Gloudemans\Shoppingcart\Facades\Cart;
class CartController extends Controller
{
public function cart()
{
$product = Product::all();
return view('frontend.cart', compact('product'));
}
public function total()
{
$product = Product::all();
return view('frontend.cart', compact('product'));
}
public function toArray()
{
return [
'rowId' => $this->rowId,
'id' => $this->id,
'name' => $this->name,
'qty' => $this->qty,
'price' => $this->price,
'options' => $this->options->toArray(),
'tax' => $this->tax,
'subtotal' => $this->subtotal
];
}
// This is for adding a product to the cart
public function addToCart($productId)
{
$product = Product::findOrFail($productId);
Cart::add([
'id' => $product->id,
'name' => $product->product_name,
'qty' => 1,
'price' => $product->price,
'weight' => 0,
'options' => [
'thumb_image' => $product->thumb_image
]
]);
return redirect()->back()->with('success', 'Produkt liegt in den Warenkorb!');
}
// This is for incrementing a product in the cart
public function qtyIncrement($id)
{
$product = Cart::get($id);
$updateQty = $product->qty + 1;
Cart::update($id, $updateQty);
return redirect()->back()->with('success', 'Product incremented successful!');
}
// This is for decrementing a product in the cart
public function qtyDecrement($id)
{
$product = Cart::get($id);
$updateQty = $product->qty - 1;
if ($updateQty > 0) {
Cart::update($id, $updateQty);
}
return redirect()->back()->with('success', 'Product decremented successfully!');
}
public function updateProductQty(Request $request)
{
$productId = Cart::get($request->rowId)->id;
$product = Product::findOrFail($productId);
// check product quantity
if ($product->qty === 0) {
return response(['status' => 'error', 'message' => 'Product stock out']);
} elseif ($product->qty < $request->qty) {
return response(['status' => 'error', 'message' => 'Quantity not available in our stock']);
}
Cart::update($request->rowId, $request->quantity);
$productTotal = $this->getProductTotal($request->rowId);
return response(['status' => 'success', 'message' => 'Product Quantity Updated!', 'product_total' => $productTotal]);
}
/** get product total */
public function getProductTotal($rowId)
{
$product = Cart::get($rowId);
$total = ($product->price + $product->options->variants_total) * $product->qty;
return $total;
}
/** get cart total amount */
public function cartTotal()
{
$total = 0;
foreach (Cart::content() as $product) {
$total += $this->getProductTotal($product->rowId);
}
return $total;
}
public function cartTotalWithTax()
{
$total = 0;
foreach (Cart::content() as $product) {
$total += $this->getProductTotal($product->rowId);
}
$total = $total + Cart::tax();
return $total;
}
public function cartTax()
{
return Cart::tax();
}
/** clear all cart products */
public function clearCart()
{
Cart::destroy();
return response(['status' => 'success', 'message' => 'Cart cleared successfully']);
}
/** Remove product form cart */
public function removeProduct($rowId)
{
Cart::remove($rowId);
toastr('Product removed succesfully!', 'success', 'Success');
return redirect()->back();
}
/** Get cart count */
public function getCartCount()
{
return Cart::content()->count();
}
/** Get all cart products */
public function getCartProducts()
{
return Cart::content();
}
/** Romve product form sidebar cart */
public function removeSidebarProduct(Request $request)
{
Cart::remove($request->rowId);
return response(['status' => 'success', 'message' => 'Product removed successfully!']);
}
}
This is the cart.blade.php:
@extends('frontend.master')
@section('title', 'Warenkorb')
@section('content')
<meta name="csrf-token" content="{{ csrf_token() }}" />
<!-- ======= Page Heading ======= -->
<div class="page-heading-warenkorb">
<h2>Warenkorb</h2>
</div>
<!-- ======= Warenkorb ======= -->
<div class="warenkorb">
<div class="basket-wrapper">
@foreach (Cart::content() as $item)
<div class="basket-product">
<span class="total-items">Product</span>
<div class="item">
<div class="product-image">
@if (!empty($item->options->thumb_image) && file_exists(public_path($item->options->thumb_image)))
@else
<img src= "{{ asset($item->options->thumb_image) }}" class="product-frame" />
@endif
<div class="product-details">
<h1>{{ $item->name }}</h1>
<p>Product-No. - {{ $item->id }}</p>
<div class="price">€ {{ number_format($item->price, 2) }}</div>
<a href="{{ route('remove-product', $item->rowId) }}" class="cart-button">Remove article</a>
</div>
</div>
</div>
</div>
@endforeach
</div>
<!-- ======= Summary ======= -->
<div class="summary">
<div class="summary-total-items">
<span class="total-items">Warenkorb-Summe</span>
</div>
<div class="summary-subtotal">
<div class="subtotal-title">Zwischensumme</div>
<div class="subtotal-value final-value" id="sub_total">
€ {{ getCartTotal() }}
</div>
</div>
<div class="summary-total">
<div class="total-title">Gesamtsumme</div>
<div class="tax" id="cart_tax">Einschließlich € {{ getCartTax() }} MwSt. 20 % AT</div>
<div class="total-value final-value" id="sub_total_with_tax">€ {{ getCartTotalWithTax() }}
</div>
</div>
<div class="summary-checkout">
<form action="{{ route('checkout') }}" method="POST">
@csrf
<button type="submit" class="checkout-button">Weiter zur Kasse</button>
</form>
</div>
</div>
</div>
@endsection
@section('scripts')
<script>
$(document).ready(function() {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
// incriment product quantity
$('.product-increment').on('click', function() {
let input = $(this).siblings('.product-qty');
let quantity = parseInt(input.val()) + 1;
let rowId = input.data('rowid');
input.val(quantity);
$.ajax({
url: "{{ route('cart.update-quantity') }}",
method: 'POST',
data: {
rowId: rowId,
quantity: quantity
},
success: function(data) {
if (data.status === 'success') {
let productId = '#' + rowId;
let totalAmount = "€ " + data.product_total
$(productId).text(totalAmount)
renderCartSubTotal()
renderCartSubTotalWithTax()
renderCartTax()
// calculateCouponDescount()
toastr.success(data.message)
} else if (data.status === 'error') {
toastr.error(data.message)
}
},
error: function(data) {
}
})
})
// decrement product quantity
$('.product-decrement').on('click', function() {
let input = $(this).siblings('.product-qty');
let quantity = parseInt(input.val()) - 1;
let rowId = input.data('rowid');
if (quantity < 1) {
quantity = 1;
}
input.val(quantity);
$.ajax({
url: "{{ route('cart.update-quantity') }}",
method: 'POST',
data: {
rowId: rowId,
quantity: quantity
},
success: function(data) {
if (data.status === 'success') {
let productId = '#' + rowId;
let totalAmount = "€ " + data.product_total
$(productId).text(totalAmount)
renderCartSubTotal()
renderCartSubTotalWithTax()
renderCartTax()
// calculateCouponDescount()
toastr.success(data.message)
} else if (data.status === 'error') {
toastr.error(data.message)
}
},
error: function(data) {
}
})
})
// clear cart
$('.clear_cart').on('click', function(e) {
e.preventDefault();
Swal.fire({
title: 'Are you sure?',
text: "This action will clear your cart!",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, clear it!'
}).then((result) => {
if (result.isConfirmed) {
$.ajax({
type: 'get',
url: "{{ route('clear.cart') }}",
success: function(data) {
if (data.status === 'success') {
window.location.reload();
}
},
error: function(xhr, status, error) {
console.log(error);
}
})
}
})
})
// get subtotal of cart and put it on dom
function renderCartSubTotal() {
$.ajax({
method: 'GET',
url: "{{ route('cart.sidebar-product-total') }}",
success: function(data) {
$('#sub_total').text("€ " + data);
},
error: function(data) {
console.log(data);
}
})
}
// get total with tax of cart and put it on dom
function renderCartSubTotalWithTax() {
$.ajax({
method: 'GET',
url: "{{ route('cart.sidebar-product-total-with-tax') }}",
success: function(data) {
$('#sub_total_with_tax').text("€ " + data);
},
error: function(data) {
console.log(data);
}
})
}
// get tax of cart and put it on dom
function renderCartTax() {
$.ajax({
method: 'GET',
url: "{{ route('cart.calculate-tax') }}",
success: function(data) {
$('#cart_tax').text("Einschließlich € " + data + " MwSt. 20 % AT");
},
error: function(data) {
console.log(data);
}
})
}
// calculate discount amount
function calculateCouponDescount() {
$.ajax({
method: 'GET',
url: "",
success: function(data) {
if (data.status === 'success') {
$('#discount').text(data.discount);
$('#cart_total').text(data.cart_total);
}
},
error: function(data) {
console.log(data);
}
})
}
})
</script>
@endsection
This is the order_products migration file:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('order_products', function (Blueprint $table) {
$table->id();
$table->integer('order_id');
$table->integer('product_id');
$table->integer('vendor_id');
$table->string('product_name');
$table->text('variants');
$table->integer('variant_total')->nullable();
$table->string('unit_price');
$table->integer('qty');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('order_products');
}
};
This is the order_table migration file:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('orders', function (Blueprint $table) {
$table->id();
$table->string('invoice_id');
$table->integer('user_id');
$table->text('seller');
$table->text('customer');
$table->double('sub_total');
$table->double('amount');
$table->string('currency_name');
$table->string('currency_icon');
$table->integer('product_qty');
$table->string('payment_method');
$table->integer('payment_status');
$table->text('order_address');
$table->string('order_status');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('orders');
}
};
This is the transactions migration file:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('transactions', function (Blueprint $table) {
$table->id();
$table->integer('order_id');
$table->string('transaction_id');
$table->string('payment_method');
$table->double('amount');
$table->double('amount_real_currency');
$table->string('amount_real_currency_name');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('transactions');
}
};
This is the OrderProduct model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class OrderProduct extends Model
{
use HasFactory;
// Relationship between OrderProduct and Vendor
public function vendor()
{
return $this->belongsTo(Vendor::class);
}
public function product()
{
return $this->belongsTo(Product::class);
}
public function order()
{
return $this->belongsTo(Order::class);
}
}
This is the Order model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
use HasFactory;
public function user()
{
return $this->belongsTo(User::class);
}
public function getCustomerNameAttribute()
{
return $this->user ? $this->user->name : 'Unknown'; // Assuming the User model has a 'name' field
}
public function transaction()
{
return $this->hasOne(Transaction::class);
}
}
This is the transaction model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Transaction extends Model
{
use HasFactory;
public function order()
{
return $this->belongsTo(Order::class);
}
}
Please or to participate in this conversation.