Understanding Payment Class
When you created your first payment method, you built this CustomStripePayment
class. Now let's dive deeper into how each part works:
<?php
namespace Webkul\CustomStripePayment\Payment;
use Webkul\Payment\Payment\Payment;
class CustomStripePayment extends Payment
{
/**
* Payment method code - must match payment-methods.php key.
*/
protected $code = 'custom_stripe_payment';
/**
* Get redirect URL for payment processing.
*
* Note: You need to create this route in your Routes/web.php file
* or return null if you don't need a redirect.
*/
public function getRedirectUrl()
{
// return route('custom_stripe_payment.process');
return null; // No redirect needed for this basic example
}
/**
* Get additional details for frontend display.
*/
public function getAdditionalDetails()
{
return [
'title' => $this->getConfigData('title'),
'description' => $this->getConfigData('description'),
'requires_card_details' => true,
];
}
/**
* Get payment method configuration data.
*/
public function getConfigData($field)
{
return core()->getConfigData('sales.payment_methods.custom_stripe_payment.' . $field);
}
}
Understanding Key Methods
Let's break down each method in your CustomStripePayment
class and understand what they do and when they're used.
Payment Method Code
The $code
property is the foundation of your payment method - it connects all the pieces together.
protected $code = 'custom_stripe_payment';
When Do You Need This Property?
Usually, you don't need to explicitly set this property because if your codes are properly set, then config data can get properly. However, if codes are not in convention then you might need this property to override the default behavior.
Purpose: This is the unique identifier that ties everything together:
- Must match the key in
payment-methods.php
- Used in configuration paths
- References your payment method throughout Bagisto
Redirect URL Handling
This method controls the payment flow - whether customers stay on your site or get redirected elsewhere.
public function getRedirectUrl()
{
return null; // No redirect needed for this basic example
}
Basic Example Note
In this example, we return null
to keep things simple. At this stage, orders will be placed directly without external redirects. However, in real-life scenarios, you might need to redirect customers to external payment gateways for actual payment processing.
Purpose: Determines where to redirect customers for payment processing:
- Return
null
for inline payment forms - Return a route for external payment pages
- Used for gateways that require external redirects
When to use redirects:
- PayPal Checkout
- Bank transfer instructions page
- External payment gateway forms
Frontend Display Information
This method provides all the data your payment method needs to display correctly on the checkout page.
public function getAdditionalDetails()
{
return [
'title' => $this->getConfigData('title'),
'description' => $this->getConfigData('description'),
'requires_card_details' => true,
];
}
Purpose: Provides frontend with payment method information:
title
: Display name from admin configurationdescription
: Payment method descriptionrequires_card_details
: Tells frontend to show card form- Custom properties for your specific needs
Configuration Data Access
This method handles how your payment class retrieves configuration values from the admin panel.
public function getConfigData($field)
{
return core()->getConfigData('sales.payment_methods.custom_stripe_payment.' . $field);
}
When Do You Need This Method?
Usually, you don't need this method because if your payment method code is properly set, then config data can get properly. However, if not in convention then you might need this method to override the default behavior.
Purpose: Retrieves admin configuration values:
- Builds the full configuration path
- Accesses values set in admin panel
- Returns the configured value for the specified field
Best Practices for Payment Classes
Here are some essential practices to follow when building robust payment methods:
Implementation Note
The methods shown in this section are demonstration examples for best practices. In real-world applications, you need to implement these methods according to your specific payment gateway requirements and business logic. Use these examples as reference guides and adapt them to your particular use case.
Error Handling
Always implement comprehensive error handling in your payment methods:
/**
* Handle payment errors gracefully.
*/
protected function handlePaymentError(\Exception $e)
{
// log the error for debugging
\Log::error('Payment error in ' . $this->code, [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
// return user-friendly error message
return [
'success' => false,
'error' => 'Payment processing failed. Please try again or contact support.',
];
}
Security Considerations
Always validate and sanitize data before processing payments to protect your application and customers.
/**
* Validate payment data before processing.
*/
protected function validatePaymentData($data)
{
$validator = validator($data, [
'amount' => 'required|numeric|min:0.01',
'currency' => 'required|string|size:3',
'customer_email' => 'required|email',
]);
if ($validator->fails()) {
throw new \InvalidArgumentException($validator->errors()->first());
}
return true;
}
Logging and Debugging
Proper logging helps you track payment activities and troubleshoot issues without exposing sensitive information.
/**
* Log payment activities for debugging and audit.
*/
protected function logPaymentActivity($action, $data = [])
{
// remove sensitive data before logging
$sanitizedData = array_diff_key($data, [
'api_key' => '',
'secret_key' => '',
'card_number' => '',
'cvv' => '',
]);
\Log::info("Payment {$action} for {$this->code}", $sanitizedData);
}
Comprehensive Error Handling
Different payment scenarios require different error handling approaches. Here's how to handle various types of payment errors gracefully:
/**
* Handle different types of payment errors.
*/
protected function handlePaymentError(\Exception $e)
{
if ($e instanceof CardException) {
// card was declined
$errorMessage = $e->getError()->message;
\Log::warning('Stripe card declined', [
'error_code' => $e->getError()->code,
'error_type' => $e->getError()->type,
'message' => $errorMessage,
]);
return [
'success' => false,
'error' => $errorMessage,
'retry_allowed' => true,
];
} elseif ($e instanceof \Stripe\Exception\RateLimitException) {
// rate limit exceeded
\Log::error('Stripe rate limit exceeded');
return [
'success' => false,
'error' => 'Service temporarily unavailable. Please try again in a moment.',
'retry_allowed' => true,
];
} elseif ($e instanceof \Stripe\Exception\InvalidRequestException) {
// invalid request
\Log::error('Stripe invalid request', ['message' => $e->getMessage()]);
return [
'success' => false,
'error' => 'Payment configuration error. Please contact support.',
'retry_allowed' => false,
];
} else {
// generic error
\Log::error('Stripe payment error', [
'message' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
return [
'success' => false,
'error' => 'Payment processing failed. Please try again.',
'retry_allowed' => true,
];
}
}
Continue Your Journey
📖 Understanding Payment Configuration ← Learn about the configuration system that powers your payment method.
📖 Back to Creating Your First Payment Method ← Review how we built this payment method step by step.
📖 Back to Getting Started ← Return to the main payment method development guide.