victorybiz / laravel-crypto-payment-gateway

GoUrl.io Crypto Payment Gateway for Laravel
MIT License
54 stars 22 forks source link

Action Victorybiz\LaravelCryptoPaymentGateway\Http\Controllers\CryptoPaymentController not defined. #4

Closed freedmann24 closed 2 years ago

freedmann24 commented 2 years ago

$payment_url = LaravelCryptoPaymentGateway::startPaymentSession([ 'amount' => 0.0000001, // OR 'amount' when sending BTC value 'orderID' => 1, 'userID' => Auth::user()->id, 'redirect' => url()->full(), ]);

Error Action Victorybiz\LaravelCryptoPaymentGateway\Http\Controllers\CryptoPaymentController not defined.

victorybiz commented 2 years ago

Please see https://github.com/victorybiz/laravel-crypto-payment-gateway#the-callback Ensure to define your Callback Controller, Callback Route and IPN (Instant Payment Notification).

Update the published config/laravel-crypto-payment-gateway.php and set value for hook_ipn key to hook IPN (Instant Payment Notification) function to the static class method defined.

// config/laravel-crypto-payment-gateway.php

/**
 * Hook IPN (Instant payment notification) to the following static class method.
 * In this static class method, you can  add your custom logic and give value to the user once your confirmed payment box status.
 * You can also add payment notification logic. 
 * This can be a static class method defined anywhere in your application.
 * This can also be static method/action defined in controller class but route must not be defined for the action.
 * 
 * The Static Method Definition in your class:
 * @param \Victorybiz\LaravelCryptoPaymentGateway\Models\CryptoPaymentModel $cryptoPaymentModel
 * @param array $payment_details
 * @param string $box_status
 * @return bool
 * public static function ipn($cryptoPaymentModel, $payment_details, $box_status)
 * {
 *  // Add your custom logic here.
 *  return true;
 * }
 * 
 * Example: [\Victorybiz\LaravelCryptoPaymentGateway\Http\Controllers\CryptoPaymentController::class, 'ipn']
 */
'hook_ipn' => [\App\Http\Controllers\Payment\PaymentController, 'ipn'],
freedmann24 commented 2 years ago

yes, I've made all steps on clean Laravel 9 and still have this error

victorybiz commented 2 years ago

Check your routes/web.php if you defined the routes to the controller in the error.

// routes/web.php

// You can protect the 'payments.crypto.pay' route with `auth` middleware to allow access by only authenticated user
Route::match(['get', 'post'], '/payments/crypto/pay', Victorybiz\LaravelCryptoPaymentGateway\Http\Controllers\CryptoPaymentController::class)
                ->name('payments.crypto.pay');

// You you need to create your own callback controller and define the route below
// The callback route should be a publicly accessible route with no auth
// However, you may also exclude the route from CSRF Protection by adding their URIs to the $except property of the VerifyCsrfToken middleware.
Route::post('/payments/crypto/callback', [App\Http\Controllers\Payment\PaymentController::class, 'callback'])
                ->withoutMiddleware(['web', 'auth']);
freedmann24 commented 2 years ago

thanks a lot! that helped!

isaacongoma commented 2 years ago

Hi @victorybiz I still get this error despite having set my routes.

victorybiz commented 2 years ago

@isaacongoma Can you please share the content of your routes where it was declared and the hook_ipn in your config?

isaacongoma commented 2 years ago

`Route::group(['prefix' => 'payment'], function(){

Route::any('/{gateway}/pay', [PaymentController::class,'payment_initialize']);    

// stripe
Route::any('/stripe/create-session', [StripePaymentController::class,'create_checkout_session'])->name('stripe.get_token');
Route::get('/stripe/success', [StripePaymentController::class,'success'])->name('stripe.success');
Route::get('/stripe/cancel', [StripePaymentController::class,'cancel'])->name('stripe.cancel');

// paypal
Route::get('/paypal/success', [PaypalPaymentController::class,'success'])->name('paypal.success');
Route::get('/paypal/cancel', [PaypalPaymentController::class,'cancel'])->name('paypal.cancel');

//sslcommerz
Route::any('/sslcommerz/success', [SSLCommerzPaymentController::class,'success'])->name('sslcommerz.success');
Route::any('/sslcommerz/fail', [SSLCommerzPaymentController::class,'fail'])->name('sslcommerz.fail');
Route::any('/sslcommerz/cancel', [SSLCommerzPaymentController::class,'cancel'])->name('sslcommerz.cancel');

//paystack
Route::any('/paystack/callback', [PaystackPaymentController::class,'return'])->name('paystack.return');

//paytm
Route::any('/paytm/callback', [PaytmPaymentController::class,'callback'])->name('paytm.callback');

//flutterwave
Route::any('/flutterwave/callback', [FlutterwavePaymentController::class,'callback'])->name('flutterwave.callback');

// razorpay
Route::post('razorpay/payment', [RazorpayPaymentController::class,'payment'])->name('razorpay.payment');

// mpesa
Route::any('/validate', [MpesaController::class, 'validation']);
Route::any('/confirm', [MpesaController::class, 'confirmation']);
Route::any('/results', [MpesaController::class, 'results']);
Route::any('/register', [MpesaController::class, 'register']);
Route::any('/timeout', [MpesaController::class, 'timeout']);
Route::any('/reconcile', [MpesaController::class, 'reconcile']);

// crypto
Route::any('/crypto/pay', CryptoPaymentController::class)->name('payments.crypto.pay');                
Route::any('/crypto/callback', [CryptoPaymentController::class, 'callback']);

});`

isaacongoma commented 2 years ago

` 'hook_ipn' => [App\Http\Controllers\Payment\CryptoPaymentController::class, 'ipn'],

/**
 * Default coin
 */
'default_coin' => 'bitcoin',`
isaacongoma commented 2 years ago

Hi @victorybiz I have shared the snip of the code

isaacongoma commented 2 years ago

The callback url is working fine but am having a problem once I hit https://thinkorganic.co.ke/payment/crypto/pay

isaacongoma commented 2 years ago

PaymentController.php

`class PaymentController extends Controller {

public function payment_initialize(Request $request, $gateway){

    session()->put('redirect_to', $request->redirect_to);
    session()->put('amount', $request->amount);
    session()->put('payment_method', $request->payment_method);
    session()->put('payment_type', $request->payment_type);
    session()->put('user_id', $request->user_id);
    session()->put('order_code', $request->order_code);
    session()->put('seller_package_id', $request->seller_package_id ?? null);

    if($gateway == 'paypal'){
        return ( new PaypalPaymentController )->index();
    }
    elseif ($gateway == 'stripe') {
        return ( new StripePaymentController )->index();
    }
    elseif ($gateway == 'sslcommerz') {
        return ( new SSLCommerzPaymentController )->index();
    }
    elseif ($gateway == 'paystack') {
        return ( new PaystackPaymentController )->index($request);
    }
    elseif ($gateway == 'flutterwave') {
        return ( new FlutterwavePaymentController )->index();
    }
    elseif ($gateway == 'paytm') {
        return ( new PaytmPaymentController )->index();
    }
    elseif ($gateway == 'razorpay') {
        return ( new RazorpayPaymentController )->index();
    }
    elseif ($gateway == 'mpesa') {
        return ( new MpesaController )->index();
    }
    elseif ($gateway == 'crypto') {
        return (new CryptoPaymentController)->index($request);
    }

}`
isaacongoma commented 2 years ago

Hello @victorybiz

victorybiz commented 2 years ago

@isaacongoma Sorry for the late response, I have been busy with work. For seamless configuration, define the following route with the route map to the CryptoPaymentController.

// routes/web.php

// You can protect the 'payments.crypto.pay' route with `auth` middleware to allow access by only authenticated user
Route::match(['get', 'post'], '/payments/crypto/pay', Victorybiz\LaravelCryptoPaymentGateway\Http\Controllers\CryptoPaymentController::class)
                ->name('payments.crypto.pay');

You will need to post data via ajax with data like the following to the above route to generate the payment link;

data: {
    amountUSD: 20.50,
    userID: 1,
    orderID: 101,
    redirect: 'https://domain.com/redirect-url',
  },

Alternatively you can also generate the payment link from your controller or anywhere in your app by call LaravelCryptoPaymentGateway::startPaymentSession($paymentData) e.g

// This could be in a controller method or livewire component method
use Victorybiz\LaravelCryptoPaymentGateway\LaravelCryptoPaymentGateway;

$payment_url = LaravelCryptoPaymentGateway::startPaymentSession([
    'amountUSD' => $validatedData['amount'], // OR 'amount' when sending BTC value
    'orderID' => $product->id,
    'userID' => Auth::user()->id,
    'redirect' => url()->full(),
]);
// redirect to the payment page
redirect()->to($payment_url);

Then you can have your own call back like below.

// You need to create your own callback controller and define the route below
// The callback route should be a publicly accessible route with no auth
// However, you may also exclude the route from CSRF Protection by adding their URIs to the $except property of the VerifyCsrfToken middleware.
Route::post('/payments/crypto/callback', [App\Http\Controllers\Payment\PaymentController::class, 'callback'])
                ->withoutMiddleware(['web', 'auth']);

Take a minute or two to go through the README step by step, you will get it set up without any issues.

isaacongoma commented 2 years ago

Thanks so much for your support

AmarAwni commented 2 years ago

Please see https://github.com/victorybiz/laravel-crypto-payment-gateway#the-callback Ensure to define your Callback Controller, Callback Route and IPN (Instant Payment Notification).

Update the published config/laravel-crypto-payment-gateway.php and set value for hook_ipn key to hook IPN (Instant Payment Notification) function to the static class method defined.

// config/laravel-crypto-payment-gateway.php

/**
 * Hook IPN (Instant payment notification) to the following static class method.
 * In this static class method, you can  add your custom logic and give value to the user once your confirmed payment box status.
 * You can also add payment notification logic. 
 * This can be a static class method defined anywhere in your application.
 * This can also be static method/action defined in controller class but route must not be defined for the action.
 * 
 * The Static Method Definition in your class:
 * @param \Victorybiz\LaravelCryptoPaymentGateway\Models\CryptoPaymentModel $cryptoPaymentModel
 * @param array $payment_details
 * @param string $box_status
 * @return bool
 * public static function ipn($cryptoPaymentModel, $payment_details, $box_status)
 * {
 *  // Add your custom logic here.
 *  return true;
 * }
 * 
 * Example: [\Victorybiz\LaravelCryptoPaymentGateway\Http\Controllers\CryptoPaymentController::class, 'ipn']
 */
'hook_ipn' => [\App\Http\Controllers\Payment\PaymentController, 'ipn'],

/* 'hook_ipn' => [\App\Http\Controllers\Payment\PaymentController::class, 'ipn'], /

BDDComputing commented 1 month ago

I'm getting the same issue using Vanguard and Laravel 11.

Route

 // Route for handling GET requests for payment
Route::get('/payments/crypto/pay', [\Victorybiz\LaravelCryptoPaymentGateway\Http\Controllers\CryptoPaymentController::class, 'paymentbox'])
    ->name('payments.crypto.pay');

Route::post('/payments/crypto/pay', [\Victorybiz\LaravelCryptoPaymentGateway\Http\Controllers\CryptoPaymentController::class, 'paymentbox'])
    ->name('payments.crypto.pay');

Route::post('/payments/crypto/callback', [Vanguard\Http\Controllers\Web\PaymentController::class, 'callback'])
    ->withoutMiddleware(['web', 'auth']);

PaymentController :

<?php

namespace Vanguard\Http\Controllers\Web;

use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Hash;
use Vanguard\Http\Controllers\Controller;
use Vanguard\QrCode;
use Auth;

use Illuminate\Http\Request;
use Victorybiz\LaravelCryptoPaymentGateway\LaravelCryptoPaymentGateway;
class PaymentController extends Controller
{

    /**
     * Cryptobox IPN Example
     * 
     * @param \Victorybiz\LaravelCryptoPaymentGateway\Models\CryptoPaymentModel $cryptoPaymentModel
     * @param array $payment_details
     * @param string $box_status
     * @return bool
     */
    public static function ipn($cryptoPaymentModel, $payment_details, $box_status)
    {            
        if ($cryptoPaymentModel) {  
            /*
            // ADD YOUR CODE HERE
            // ------------------
            // For example, you have a model `UserOrder`, you can create new Bitcoin payment record to this model
            $userOrder = UserOrder::where('payment_id', $cryptoPaymentModel->paymentID)->first();
            if (!$userOrder) 
            {
                UserOrder::create([
                    'payment_id' => $cryptoPaymentModel->paymentID,
                    'user_id'    => $payment_details["user"],
                    'order_id'   => $payment_details["order"],
                    'amount'     => floatval($payment_details["amount"]),
                    'amountusd'  => floatval($payment_details["amountusd"]),
                    'coinlabel'  => $payment_details["coinlabel"],
                    'txconfirmed'  => $payment_details["confirmed"],
                    'status'     => $payment_details["status"],
                ]);
            }
            // ------------------

            // Received second IPN notification (optional) - Bitcoin payment confirmed (6+ transaction confirmations)
            if ($userOrder && $box_status == "cryptobox_updated")
            {
                $userOrder->txconfirmed = $payment_details["confirmed"];
                $userOrder->save();
            }
            // ------------------
            */

            // Onetime action when payment confirmed (6+ transaction confirmations)
            if (!$cryptoPaymentModel->processed && $payment_details["confirmed"])
            {
                // Add your custom logic here to give value to the user.

                // ------------------
                // set the status of the payment to processed
                // $cryptoPaymentModel->setStatusAsProcessed();

                // ------------------
                // Add logic to send notification of confirmed/processed payment to the user if any
            }

        }
        return true;
    }

    public function handlePayment(Request $request)
    {
        // Validate the input data
        $validatedData = $request->validate([
            'amount' => 'required|numeric|min:1',
        ]);

        // Start the payment session
        $payment_url = LaravelCryptoPaymentGateway::startPaymentSession([
            'amountUSD' => $validatedData['amount'],
            'orderID'   => uniqid(), // Unique order ID
            'userID'    => auth()->id(), // Current user ID
            'redirect'  => route('subscription.payment.callback'), // URL to redirect after payment
        ]);

        // Redirect to the payment page
        return redirect()->to($payment_url);
    }

    // Method to handle payment callback from GoUrl (after successful payment)
    public function paymentCallback(Request $request)
    {
        return LaravelCryptoPaymentGateway::callback();
    }

    // Method for GoUrl IPN callback (from GoUrl servers)
    public function callback(Request $request)
    {
        return LaravelCryptoPaymentGateway::callback();
    }

    // Method to handle payment cancellation
    public function paymentCancel()
    {
        return redirect()->route('subscriptions.index')->with('error', 'Payment was canceled.');
    }
}

config/laravel-crypto-payment-gateway.php : 'hook_ipn' => [\Victorybiz\LaravelCryptoPaymentGateway\Http\Controllers\CryptoPaymentController::class, 'ipn'],

Any idea on what i'm doing wrong here ?