## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require nikolag/laravel-square
Publish the config file:
php artisan vendor:publish --provider="Nikolag\Square\SquareServiceProvider"
Configure .env with your Square credentials:
SQUARE_ENVIRONMENT=sandbox # or 'production'
SQUARE_ACCESS_TOKEN=your_access_token_here
SQUARE_LOCATION_ID=your_location_id
First Use Case: Create a customer and charge them in a single flow:
use Nikolag\Square\Traits\CustomerTrait;
use Nikolag\Square\Traits\PaymentTrait;
class CheckoutController extends Controller
{
use CustomerTrait, PaymentTrait;
public function checkout(Request $request)
{
// Create a customer
$customer = $this->createCustomer([
'given_name' => 'John',
'family_name' => 'Doe',
'email_address' => 'john@example.com',
'phone_number' => '+1234567890',
]);
// Charge the customer
$payment = $this->createPayment([
'idempotency_key' => 'unique_key',
'source_id' => $customer->id,
'amount_money' => [
'amount' => 1000, // $10.00
'currency' => 'USD',
],
'note' => 'Order #12345',
]);
return response()->json($payment);
}
}
Key Files:
config/square.php: Central configuration for API endpoints, timeouts, and defaults.app/Providers/SquareServiceProvider.php: Service binding and boot logic.vendor/nikolag/laravel-square/src/Traits/: Traits for common operations (e.g., CustomerTrait, PaymentTrait).Customer Management:
createCustomer() or updateCustomer() with an array of attributes.
$customer = $this->createCustomer([
'given_name' => 'Jane',
'family_name' => 'Smith',
'email_address' => 'jane@example.com',
'address' => [
'address_line_1' => '123 Main St',
'locality' => 'San Francisco',
'administrative_district_level_1' => 'CA',
'postal_code' => '94105',
'country' => 'US',
],
]);
$customer = $this->getCustomerById($customerId);
// or
$customer = $this->getCustomerByEmail('jane@example.com');
$customers = $this->listCustomers(['limit' => 10]);
Payments and Orders:
$payment = $this->createPayment([
'idempotency_key' => Str::uuid()->toString(),
'source_id' => $customer->id,
'amount_money' => ['amount' => 5000, 'currency' => 'USD'],
'note' => 'Subscription fee',
]);
$order = $this->createOrder([
'idempotency_key' => Str::uuid()->toString(),
'line_items' => [
[
'quantity' => '1',
'base_price_money' => ['amount' => 2000, 'currency' => 'USD'],
'catalog_object_id' => 'item_123',
],
],
'customer_id' => $customer->id,
]);
$this->capturePayment($payment->id, ['amount_money' => ['amount' => 5000, 'currency' => 'USD']]);
// or
$this->refundPayment($payment->id, ['reason' => 'Customer request']);
Webhooks:
routes/web.php:
Route::post('/square/webhook', 'SquareWebhookController@handleWebhook');
SquareWebhookController:
public function handleWebhook(Request $request)
{
$event = $request->json()->all();
$this->processWebhook($event); // Use the provided trait method
}
Service Container Binding:
Bind the Square client to the container in AppServiceProvider for dependency injection:
public function register()
{
$this->app->bind(\Nikolag\Square\Square::class, function ($app) {
return new \Nikolag\Square\Square(
config('square.access_token'),
config('square.environment'),
config('square.location_id')
);
});
}
Then inject Square into controllers/services:
public function __construct(\Nikolag\Square\Square $square)
{
$this->square = $square;
}
Error Handling: Wrap Square API calls in try-catch blocks to handle exceptions:
try {
$payment = $this->square->createPayment($paymentData);
} catch (\Nikolag\Square\Exceptions\SquareException $e) {
Log::error('Square payment failed: ' . $e->getMessage());
return response()->json(['error' => 'Payment processing failed'], 500);
}
Testing:
Use the sandbox environment for testing. Mock the Square client in unit tests:
$mock = Mockery::mock(\Nikolag\Square\Square::class);
$mock->shouldReceive('createCustomer')->once()->andReturn($customer);
$this->app->instance(\Nikolag\Square\Square::class, $mock);
Idempotency Keys:
idempotency_key for payments/orders to avoid duplicate charges.Str::uuid()->toString() or a similar method.409 Conflict error.Currency and Amount:
$10.00 as 10 instead of 1000 will fail silently or return incorrect results.Webhook Verification:
Square-Signature header. Verify it using the verifyWebhookSignature method:
$isValid = $this->verifyWebhookSignature(
$request->header('Square-Signature'),
$request->getContent(),
config('square.webhook_secret')
);
Rate Limits:
Customer Email Uniqueness:
getCustomerByEmail() before creating a new customer to avoid conflicts.Enable Debug Mode:
Set debug to true in config/square.php to log raw API responses:
'debug' => env('SQUARE_DEBUG', false),
Logs will appear in storage/logs/square.log.
Common Errors:
401 Unauthorized: Invalid or expired access token. Regenerate the token in the Square Developer Dashboard.400 Bad Request: Invalid payload. Validate data against Square’s API reference.429 Too Many Requests: Hit rate limits. Implement retries with delays.Testing in Sandbox:
4111 1111 1111 1111 (success) and 4000 0000 0000 0002 (decline).namespace App\Traits;
use Nikolag\Square\Square
How can I help you explore Laravel packages today?