├── .gitignore ├── LICENSE.md ├── README.md ├── composer.json ├── database └── migrations │ └── 2022_12_02_032758_create_nowpayments_logger_table.php ├── resources └── views │ └── dashboard.blade.php ├── routes └── routes.php ├── src ├── Currency.php ├── Facades │ └── Nowpayments.php ├── Http │ ├── Controllers │ │ └── DashboardController.php │ └── Middleware │ │ └── Authorize.php ├── IsNullException.php ├── Models │ └── Logger.php ├── Nowpayments.php └── NowpaymentsServiceProvider.php ├── utils ├── config │ └── nowpayments.php └── helpers │ └── nowpayments.php └── vendor ├── autoload.php └── composer ├── ClassLoader.php ├── LICENSE ├── autoload_classmap.php ├── autoload_files.php ├── autoload_namespaces.php ├── autoload_psr4.php ├── autoload_real.php └── autoload_static.php /.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrevailExcel/laravel-nowpayments/ae903e361a22cae3499b951b4b21e04059b59347/.gitignore -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Prevail Ejimadu 4 | 5 | > Permission is hereby granted, free of charge, to any person obtaining a copy 6 | > of this software and associated documentation files (the "Software"), to deal 7 | > in the Software without restriction, including without limitation the rights 8 | > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | > copies of the Software, and to permit persons to whom the Software is 10 | > furnished to do so, subject to the following conditions: 11 | > 12 | > The above copyright notice and this permission notice shall be included in 13 | > all copies or substantial portions of the Software. 14 | > 15 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | > THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # laravel-nowpayments 2 | 3 | [![Latest Stable Version](https://poser.pugx.org/prevailexcel/laravel-nowpayments/v/stable.svg)](https://packagist.org/packages/prevailexcel/laravel-nowpayments) 4 | [![License](https://poser.pugx.org/prevailexcel/laravel-nowpayments/license.svg)](LICENSE.md) 5 | 6 | > A Laravel Package for working with NOWPayments seamlessly 7 | ## 8 | > This package comes now with a default dashboard that show the list of all payments and also shows a log of endpoints that have been accessed from your application, fluent methods to handle payments easily and removes the bulk of the heavy work from you. 9 | ## Installation 10 | 11 | [PHP](https://php.net) 5.4+ or [HHVM](http://hhvm.com) 3.3+, and [Composer](https://getcomposer.org) are required. 12 | 13 | To get the latest version of Laravel NOWPayments, simply require it 14 | 15 | ```bash 16 | composer require prevailexcel/laravel-nowpayments 17 | ``` 18 | 19 | Or add the following line to the require block of your `composer.json` file. 20 | 21 | ``` 22 | "prevailexcel/laravel-nowpayments": "1.0.*" 23 | ``` 24 | 25 | You'll then need to run `composer install` or `composer update` to download it and have the autoloader updated. 26 | 27 | 28 | 29 | Once Laravel NOWPayments is installed, you need to register the service provider. Open up `config/app.php` and add the following to the `providers` key. 30 | 31 | ```php 32 | 'providers' => [ 33 | ... 34 | PrevailExcel\Nowpayments\NowpaymentsServiceProvider::class, 35 | ... 36 | ] 37 | ``` 38 | 39 | > If you use **Laravel >= 5.5** you can skip this step and go to [**`configuration`**](https://github.com/PrevailExcel/laravel-nowpayments#configuration) 40 | 41 | * `PrevailExcel\Nowpayments\NowpaymentsServiceProvider::class` 42 | 43 | Also, register the Facade like so: 44 | 45 | ```php 46 | 'aliases' => [ 47 | ... 48 | 'Nowpayments' => PrevailExcel\Nowpayments\Facades\Nowpayments::class, 49 | ... 50 | ] 51 | ``` 52 | 53 | ## Configuration 54 | 55 | You can publish the configuration file using this command: 56 | 57 | ```bash 58 | php artisan vendor:publish --provider="PrevailExcel\Nowpayments\NowpaymentsServiceProvider" 59 | ``` 60 | 61 | A configuration-file named `nowpayments.php` with some sensible defaults will be placed in your `config` directory: 62 | 63 | ```php 64 | env('NOWPAYMENTS_API_KEY'), 74 | 75 | /** 76 | * IPN Secret from NOWPayments Dashboard 77 | */ 78 | 'ipnSecret' => env('NOWPAYMENTS_IPN_SECRET'), 79 | 80 | /** 81 | * You enviroment can either be live or sandbox. 82 | * Make sure to add the appropriate API key after changing the enviroment in .env 83 | * 84 | */ 85 | 'env' => env('NOWPAYMENTS_ENV', 'sandbox'), 86 | 87 | /** 88 | * NOWPayments Live URL 89 | * 90 | */ 91 | 'liveUrl' => env('NOWPAYMENTS_LIVE_URL', "https://api.nowpayments.io/v1"), 92 | 93 | /** 94 | * NOWPayments Sandbox URL 95 | * 96 | */ 97 | 'sandboxUrl' => env('NOWPAYMENTS_SANDBOX_URL', "https://api-sandbox.nowpayments.io/v1"), 98 | 99 | /** 100 | * Your callback URL 101 | * 102 | */ 103 | 'callbackUrl' => env('NOWPAYMENTS_CALLBACK_URL'), 104 | 105 | /** 106 | * Your URL Path 107 | * 108 | */ 109 | 'path' => 'laravel-nowpayments', 110 | 111 | /** 112 | * You can add your custom middleware to access the dashboard here 113 | * 114 | */ 115 | 'middleware' => null, // "Authorise::class", 116 | 117 | /** 118 | * Your Nowpayment email here 119 | * 120 | */ 121 | 'email' => env('NOWPAYMENTS_EMAIL'), 122 | 123 | /** 124 | * Your Nowpayment password here 125 | * 126 | */ 127 | 'password' => env('NOWPAYMENTS_PASSWORD'), 128 | ]; 129 | ``` 130 | 131 | Remeber to run your migration to add one table to the database for logging with this command 132 | 133 | ```bash 134 | php artisan migrate 135 | ``` 136 | 137 | You can test the dashboard to see if your set up is ready by serving your application and going to /laravel-nowpayments 138 | 139 | ```bash 140 | 127.0.0.1:8000/laravel-nowpayments 141 | ``` 142 | You can change this default path/url by changing the 'path' from the config file at `nowpayments.php` in your `config` folder 143 | 144 | ```php 145 | 'laravel-nowpayments', 150 | 'path' => 'new-endpoint', 151 | ]; 152 | ``` 153 | 154 | ## General E-commerce Payment Flow 155 | 156 | ### 1 UI - Ask a customer to select item/items for purchase to determine the total sum 157 | ### 2 UI - Ask a customer to select payment currency 158 | ### 3 API - Call Nowpayments::createPayment() method; 159 | Pass the data from the User as an array. This method does the magic. First it gets the minimum payment amount for the currency pair, then it gets the estimate of the total amount in crypto and checks that it is larger than the minimum payment amount. 160 | 161 | If it's true, it sends the payload and gets the payment data that inclues the generated wallet address for the user. 162 | ### 4 UI - Ask a customer to send the payment to the generated deposit address. 163 | ### 5 UI - A customer sends coins, NOWPayments processes and exchanges them (if required), and settles the payment to your Outcome Wallet. 164 | ### 6 API - Check the payment status 165 | You can get the payment status either via NOWPayments IPN callbacks or manually using "nowpayments()->getPaymentStatus()" and display it to a customer so that they know when their payment has been processed. 166 | ### 7 Check the dashboard for a list of all your payments 167 | This package comes with a default Dashboard that show a list of all payments and also shows a log of endpoints thta have been accessed from your application. 168 | Additionally, you can see all of this information in your Account on NOWPayments website. 169 | 170 | 171 | ## Usage 172 | 173 | Open your .env file and add your api key, env, callback url like so: 174 | 175 | ```php 176 | NOWPAYMENTS_ENV="live" 177 | NOWPAYMENTS_API_KEY="*******-*******-*******-*******" 178 | NOWPAYMENTS_CALLBACK_URL="https://yourcallback.com" 179 | NOWPAYMENTS_EMAIL="hello@example.com" 180 | NOWPAYMENTS_PASSWORD="your password" 181 | ``` 182 | *If you are using a hosting service like heroku, ensure to add the above details to your configuration variables.* 183 | 184 | 185 | ```php 186 | // Laravel 5.1.17 and above 187 | Route::post('/pay', 'PaymentController@createCryptoPayment')->name('pay'); 188 | ``` 189 | 190 | OR 191 | 192 | ```php 193 | Route::post('/pay', [ 194 | 'uses' => 'PaymentController@createCryptoPayment', 195 | 'as' => 'pay' 196 | ]); 197 | ``` 198 | OR 199 | 200 | ```php 201 | // Laravel 8 & 9 202 | Route::post('/pay', [App\Http\Controllers\PaymentController::class, 'createCryptoPayment'])->name('pay'); 203 | ``` 204 | 205 | 206 | ```php 207 | request()->price_amount ?? 100, 230 | 'price_currency' => request()->price_currency ?? 'usd', 231 | 'order_id' => request()->order_id ?? uniqid(), // you can generate your order id as you wish 232 | 'pay_currency' => request()->pay_currency ?? 'btc', 233 | 'payout_currency' => request()->payout_currency ?? 'btc', 234 | ]; 235 | 236 | $paymentDetails = Nowpayments::createPayment($data); 237 | 238 | dd($paymentDetails); 239 | // Now you have the payment details, 240 | // you can then redirect or do whatever you want 241 | 242 | return Redirect::back()->with(['msg'=>"Payment created successfully", 'type'=>'success'], 'data'=>$paymentDetails); 243 | }catch(\Exception $e) { 244 | return Redirect::back()->withMessage(['msg'=>"There's an error in the data", 'type'=>'error']); 245 | } 246 | } 247 | } 248 | ``` 249 | 250 | Some fluent methods this package provides are listed here. 251 | ```php 252 | 253 | /** 254 | * This is the method to create a payment. You need to provide your data as an array. 255 | * @returns array 256 | */ 257 | Nowpayments::createPayment(); 258 | 259 | /** 260 | * Alternatively, use the helper. 261 | */ 262 | nowpayments()->createPayment(); 263 | 264 | 265 | /** 266 | * Gets the payment details of a particular transaction including the status with the paymentId 267 | * @returns array 268 | */ 269 | Nowpayments::getPaymentStatus(); 270 | 271 | /** 272 | * Alternatively, use the helper. 273 | */ 274 | nowpayments()->getPaymentStatus(); 275 | 276 | 277 | /** 278 | * Get all currenices 279 | * @returns array 280 | */ 281 | Nowpayments::getCurrencies() 282 | 283 | /** 284 | * Alternatively, use the helper. 285 | */ 286 | nowpayments()->getCurrencies(); 287 | 288 | 289 | /** 290 | * Get the minimum payment amount for a specific pair. 291 | */ 292 | Nowpayments::getMinimumPaymentAmount(); 293 | 294 | /** 295 | * Alternatively, use the helper. 296 | */ 297 | nowpayments()->getMinimumPaymentAmount(); 298 | 299 | 300 | /** 301 | * Creates invoice with url where user can complete the payment. 302 | * @returns array 303 | */ 304 | Nowpayments::createInvoice(); 305 | 306 | /** 307 | * Alternatively, use the helper. 308 | */ 309 | nowpayments()->createInvoice(); 310 | 311 | 312 | /** 313 | * This method allows you to obtain information about all the payment plans you’ve created. 314 | * @returns array 315 | */ 316 | Nowpayments::getPlans(); 317 | /** 318 | * Alternatively, use the helper. 319 | */ 320 | nowpayments()->getPlans(); 321 | 322 | 323 | /** 324 | * Get information about a particular recurring payment via its ID. 325 | * @returns array 326 | */ 327 | Nowpayments::getSubscription(); 328 | /** 329 | * Alternatively, use the helper. 330 | */ 331 | nowpayments()->getSubscription(); 332 | 333 | 334 | /** 335 | * This method allows you to send payment links to your customers via email. 336 | * @returns array 337 | */ 338 | Nowpayments::emailSubscription(); 339 | /** 340 | * Alternatively, use the helper. 341 | */ 342 | nowpayments()->emailSubscription(); 343 | 344 | 345 | /** 346 | * Completely removes a particular payment from the recurring payment plan. 347 | * @returns array 348 | */ 349 | Nowpayments::deleteSubscription(); 350 | /** 351 | * Alternatively, use the helper. 352 | */ 353 | nowpayments()->deleteSubscription(); 354 | 355 | 356 | /** 357 | * Returns the entire list of all transactions, created with certain API key. 358 | * @returns array 359 | */ 360 | Nowpayments::getListOfPayments(); 361 | 362 | /** 363 | * Alternatively, use the helper. 364 | */ 365 | nowpayments()->getListOfPayments(); 366 | 367 | 368 | /** 369 | * This method gets the estitmate price of an amount in different pairs 370 | * @return array 371 | */ 372 | Nowpayments::getEstimatePrice(); 373 | 374 | /** 375 | * Alternatively, use the helper. 376 | */ 377 | nowpayments()->getEstimatePrice(); 378 | 379 | ``` 380 | 381 | ## Todo 382 | 383 | * Add Comprehensive Tests 384 | * Add Support For Billing Endpoints 385 | * Add Support For Payout Endpoints 386 | 387 | ## Contributing 388 | 389 | Please feel free to fork this package and contribute by submitting a pull request to enhance the functionalities. 390 | 391 | ## How can I thank you? 392 | 393 | Why not star the github repo? I'd love the attention! Why not share the link for this repository on Twitter or HackerNews? Spread the word! 394 | 395 | Don't forget to [follow me on twitter](https://twitter.com/EjimaduPrevail)! 396 | Also check out my page on medium to catch articles and tutorials on Laravel [follow me on medium](https://medium.com/@prevailexcellent)! 397 | 398 | Thanks! 399 | Chimeremeze Prevail Ejimadu. 400 | 401 | ## License 402 | 403 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 404 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "prevailexcel/laravel-nowpayments", 3 | "description": "A Laravel Package for NOWPayments", 4 | "keywords": [ 5 | "php", 6 | "github", 7 | "laravel", 8 | "Open Source", 9 | "payments", 10 | "crypto", 11 | "subscription", 12 | "Nowpayments", 13 | "crypto payments", 14 | "laravel 6", 15 | "laravel 7", 16 | "laravel 8", 17 | "laravel 9" 18 | ], 19 | "license": "MIT", 20 | "minimum-stability": "stable", 21 | "autoload": { 22 | "files": [ 23 | "utils/helpers/nowpayments.php" 24 | ], 25 | "psr-4": { 26 | "PrevailExcel\\Nowpayments\\": "src/" 27 | } 28 | }, 29 | "authors": [ 30 | { 31 | "name": "PrevailExcel", 32 | "email": "prevailexcellent@gmail.com" 33 | } 34 | ], 35 | "require": { 36 | "guzzlehttp/guzzle": "^7.0.1" 37 | }, 38 | "extra": { 39 | "laravel": { 40 | "providers": [ 41 | "PrevailExcel\\Nowpayments\\NowpaymentsServiceProvider" 42 | ], 43 | "aliases": { 44 | "Nowpayments": "PrevailExcel\\Nowpayments\\Facades\\Nowpayments" 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /database/migrations/2022_12_02_032758_create_nowpayments_logger_table.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * For the full copyright and license information, please view the LICENSE 13 | * file that was distributed with this source code. 14 | */ 15 | 16 | class CreateNowpaymentsLoggerTable extends Migration 17 | { 18 | /** 19 | * Run the migrations. 20 | * 21 | * @return void 22 | */ 23 | public function up() 24 | { 25 | Schema::create('nowpayments_api_call_logger', function (Blueprint $table) { 26 | $table->id(); 27 | $table->string('endpoint'); 28 | $table->integer('count')->default(0); 29 | }); 30 | } 31 | 32 | /** 33 | * Reverse the migrations. 34 | * 35 | * @return void 36 | */ 37 | public function down() 38 | { 39 | Schema::dropIfExists('nowpayments_api_call_logger'); 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /resources/views/dashboard.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 17 | 18 | Laravel NOWPayment 19 | 20 | 21 | 22 | 23 | 24 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 84 | 85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
API Status: ON
94 |
95 |
96 |
97 | 98 |
99 |
100 |
101 |
Enviroment: {{ config('nowpayments.env') }}
103 |
104 |
105 |
106 | 107 |
108 |
109 |
110 |

Payment List

111 |
112 |
113 |
114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | @forelse($payments as $pay) 129 | 130 | 131 | 132 | 133 | 134 | 136 | 137 | 138 | 140 | 141 | @empty 142 |
No Payments initiated yet
143 | @endforelse 144 | 145 |
Payment IDOrder IDOriginal PriceAmount SentAmount ReceivedStatusAddressCreated at
{{ $pay['payment_id'] }}{{ $pay['order_id'] }}{{ $pay['price_amount'] }} {{ $pay['price_currency'] }}{{ $pay['pay_amount'] }} {{ $pay['pay_currency'] }}{{ $pay['outcome_amount'] }} {{ $pay['outcome_currency'] }} 135 | {{ $pay['payment_status'] }}{{ $pay['pay_address'] }}{{ Carbon\Carbon::parse($pay['created_at'])->format('d M Y, H:i A') }} 139 |
146 |
147 |
148 |
149 |
150 | 151 |
152 |
153 |
154 | API Log 155 |
156 |
    157 | @foreach ($logs as $log) 158 |
  • {{ $log->endpoint }} {{ $log->count }} 160 |
  • 161 | @endforeach 162 |
163 |
164 | 165 |
166 |
167 | What's New in Laravel NOWPayments 168 |
169 |
170 | Docs here on Github
172 | Version: v{{ $version }}
173 | Buy Me A Coffee 174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 | 183 | 189 | 190 | 191 | 192 | -------------------------------------------------------------------------------- /routes/routes.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * For the full copyright and license information, please view the LICENSE 13 | * file that was distributed with this source code. 14 | */ 15 | 16 | Route::group([ 17 | 'prefix' => config('nowpayments.path', 'laravel-nowpayments'), 18 | 'middleware' => config('nowpayments.middleware', [Authorize::class]), 19 | ], function () { 20 | Route::get('/', DashboardController::class)->name('nowpayments.dashboard'); 21 | }); 22 | -------------------------------------------------------------------------------- /src/Currency.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * For the full copyright and license information, please view the LICENSE 11 | * file that was distributed with this source code. 12 | */ 13 | 14 | class Currency 15 | { 16 | public const BTG = "btg"; 17 | public const ETH = "eth"; 18 | public const XMR = "xmr"; 19 | public const ZEC = "zec"; 20 | public const XVG = "xvg"; 21 | public const ADA = "ada"; 22 | public const LTC = "ltc"; 23 | public const BCH = "bch"; 24 | public const GTUM = "qtum"; 25 | public const DASH = "dash"; 26 | public const XLM = "xlm"; 27 | public const XRP = "xrp"; 28 | public const XEM = "xem"; 29 | public const DGB = "dgb"; 30 | public const LSK = "lsk"; 31 | public const DOGE = "doge"; 32 | public const TRX = "trx"; 33 | public const KMD = "kmd"; 34 | public const REP = "rep"; 35 | public const BAT = "bat"; 36 | public const ARK = "ark"; 37 | public const WAVES = "waves"; 38 | public const BNB = "bnb"; 39 | public const XZC = "xzc"; 40 | public const NANO = "nano"; 41 | public const TUSD = "tusd"; 42 | public const VET = "vet"; 43 | public const ZEB = "zen"; 44 | public const GRS = "grs"; 45 | public const FUN = "fun"; 46 | public const NEO = "neo"; 47 | public const GAS = "gas"; 48 | public const PAX = "pax"; 49 | public const USDC = "usdc"; 50 | public const ONT = "ont"; 51 | public const XTZ = "xtz"; 52 | public const LINK = "link"; 53 | public const RVN = "rvn"; 54 | public const BNBMAINNET = "bnbmainnet"; 55 | public const ZIL = "zil"; 56 | public const BCD = "bcd"; 57 | public const USDT = "usdt"; 58 | public const USDTERC20 = "usdterc20"; 59 | public const CRO = "cro"; 60 | public const DAI = "dai"; 61 | public const HT = "ht"; 62 | public const WABY = "wabi"; 63 | public const BUSD = "busd"; 64 | public const ALGO = "algo"; 65 | public const USDTTRC20 = "usdttrc20"; 66 | public const GT = "gt"; 67 | public const STPT = "stpt"; 68 | public const AVA = "ava"; 69 | public const SXP = "sxp"; 70 | public const UNI = "uni"; 71 | public const OKB = "okb"; 72 | public const BTC = "btc"; 73 | } -------------------------------------------------------------------------------- /src/Facades/Nowpayments.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * For the full copyright and license information, please view the LICENSE 13 | * file that was distributed with this source code. 14 | */ 15 | 16 | class Nowpayments extends Facade 17 | { 18 | /** 19 | * Get the registered name of the component 20 | * @return string 21 | */ 22 | protected static function getFacadeAccessor() 23 | { 24 | return 'laravel-nowpayments'; 25 | } 26 | 27 | final public const VERSION = '1.0.1'; 28 | 29 | } -------------------------------------------------------------------------------- /src/Http/Controllers/DashboardController.php: -------------------------------------------------------------------------------- 1 | 13 | * 14 | * For the full copyright and license information, please view the LICENSE 15 | * file that was distributed with this source code. 16 | */ 17 | 18 | class DashboardController 19 | { 20 | public function __invoke(Request $request) 21 | { 22 | $payments = Nowpayments::getListOfPayments("limit=200")['data']; 23 | $logs = Logger::get(); 24 | $version = Nowpayments::VERSION; 25 | return view('nowpayments::dashboard', compact('payments', 'logs', 'version')); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Http/Middleware/Authorize.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * For the full copyright and license information, please view the LICENSE 13 | * file that was distributed with this source code. 14 | */ 15 | 16 | class Authorize 17 | { 18 | /** 19 | * Authorize the current user. 20 | * 21 | * @param \Illuminate\Http\Request $request 22 | * @param \Closure $next 23 | * @return \Illuminate\Http\Response 24 | */ 25 | public function handle($request, $next) 26 | { 27 | return Gate::check('viewNowpaymentsDashboard', [$request->user()]) 28 | ? $next($request) 29 | : abort(403); 30 | } 31 | } -------------------------------------------------------------------------------- /src/IsNullException.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * For the full copyright and license information, please view the LICENSE 13 | * file that was distributed with this source code. 14 | */ 15 | 16 | class IsNullException extends Exception 17 | { 18 | 19 | } -------------------------------------------------------------------------------- /src/Models/Logger.php: -------------------------------------------------------------------------------- 1 | 12 | * 13 | * For the full copyright and license information, please view the LICENSE 14 | * file that was distributed with this source code. 15 | */ 16 | 17 | class Logger extends Model 18 | { 19 | use HasFactory; 20 | protected $fillable = [ 21 | 'endpoint', 'count' 22 | ]; 23 | protected $table = 'nowpayments_api_call_logger'; 24 | public $timestamps = false; 25 | } 26 | -------------------------------------------------------------------------------- /src/Nowpayments.php: -------------------------------------------------------------------------------- 1 | 14 | * 15 | * For the full copyright and license information, please view the LICENSE 16 | * file that was distributed with this source code. 17 | */ 18 | 19 | class Nowpayments 20 | { 21 | 22 | /** 23 | * Enviroment - local or production 24 | * @var string 25 | */ 26 | protected $env; 27 | 28 | /** 29 | * Issue API Key from your Nowpayments Dashboard 30 | * @var string 31 | */ 32 | protected $apiKey; 33 | 34 | /** 35 | * Instance of Client 36 | * @var Client 37 | */ 38 | protected $client; 39 | 40 | /** 41 | * Response from requests made to Nowpayments 42 | * @var mixed 43 | */ 44 | protected $response; 45 | 46 | /** 47 | * Nowpayments API base Url 48 | * @var string 49 | */ 50 | protected $baseUrl; 51 | 52 | /** 53 | * Your callback Url. You can set this in your .env or you can add 54 | * it to the $data in the methods that require that option. 55 | * @var string 56 | */ 57 | protected $callbackUrl; 58 | 59 | final public const VERSION = '1.0.1'; 60 | 61 | public function __construct() 62 | { 63 | $this->setEnv(); 64 | $this->setKey(); 65 | $this->setBaseUrl(); 66 | $this->setRequestOptions(); 67 | $this->checkStatus(); 68 | } 69 | 70 | /** 71 | * Get Base Url from NOWPayment config file 72 | */ 73 | public function setEnv() 74 | { 75 | $this->env = Config::get('nowpayments.env'); 76 | } 77 | 78 | /** 79 | * Get Base Url from NOWPayment config file 80 | */ 81 | public function setBaseUrl() 82 | { 83 | if ($this->env == "sandbox") 84 | $this->baseUrl = Config::get('nowpayments.sandboxUrl'); 85 | else 86 | $this->baseUrl = Config::get('nowpayments.liveUrl'); 87 | $this->callbackUrl = Config::get('nowpayments.callbackUrl'); 88 | } 89 | 90 | /** 91 | * Get api key from NOWPayment config file 92 | */ 93 | public function setKey() 94 | { 95 | $this->apiKey = Config::get('nowpayments.apiKey'); 96 | } 97 | 98 | /** 99 | * Set options for making the Client request 100 | */ 101 | private function setRequestOptions(string $jwt = null) 102 | { 103 | if (!$jwt) 104 | $headers = [ 105 | 'x-api-key' => $this->apiKey, 106 | 'Content-Type' => 'application/json', 107 | 'Accept' => 'application/json' 108 | ]; 109 | else 110 | $headers = [ 111 | 'x-api-key' => $this->apiKey, 112 | 'Authorization' => 'Bearer ' . $jwt, 113 | 'Content-Type' => 'application/json', 114 | 'Accept' => 'application/json' 115 | ]; 116 | $this->client = new Client( 117 | [ 118 | 'base_uri' => $this->baseUrl, 119 | 'headers' => $headers 120 | ] 121 | ); 122 | } 123 | 124 | /** 125 | * @param string $relativeUrl 126 | * @param string $method 127 | * @param array $body 128 | * @return Nowpayments 129 | * @throws IsNullException 130 | */ 131 | private function setHttpResponse($relativeUrl, $method, $body = []) 132 | { 133 | if (is_null($method)) { 134 | throw new IsNullException("Empty method not allowed"); 135 | } 136 | 137 | $this->response = $this->client->{strtolower($method)}( 138 | $this->baseUrl . $relativeUrl, 139 | ["body" => json_encode($body)] 140 | ); 141 | if (strlen(stristr($relativeUrl, "?", true)) > 1) 142 | $relativeUrl = stristr($relativeUrl, "?", true); 143 | if ($relativeUrl != '/status' && $relativeUrl != '/auth') 144 | Logger::updateOrCreate([ 145 | 'endpoint' => $relativeUrl 146 | ])->increment('count'); 147 | return $this; 148 | } 149 | 150 | /** 151 | * @return Boolean 152 | * @throws IsNullException 153 | */ 154 | public function checkStatus() 155 | { 156 | $this->setRequestOptions(); 157 | $status = $this->setHttpResponse("/status", 'GET', [])->getResponse(); 158 | 159 | if ($status['message'] != "OK") { 160 | throw new IsNullException("The API is currently not available"); 161 | } 162 | } 163 | 164 | /** 165 | * Get the whole response from a get operation 166 | * @return array 167 | */ 168 | private function getResponse() 169 | { 170 | return json_decode($this->response->getBody(), true); 171 | } 172 | 173 | /** 174 | * @return array 175 | * @throws isNullException 176 | */ 177 | public function getCurrencies(): array 178 | { 179 | $this->setRequestOptions(); 180 | return $this->setHttpResponse("/currencies", 'GET', [])->getResponse(); 181 | } 182 | 183 | /** 184 | * @param array $data 185 | * @return array 186 | * 187 | */ 188 | public function getEstimatePrice($data = null): array 189 | { 190 | if ($data == null) { 191 | $data = 192 | "amount=" . 100 . "&" . 193 | "currency_from=" . "usd" . "&" . 194 | "currency_to=" . "usdt"; 195 | } 196 | if(is_array($data)){ 197 | $data = http_build_query($data); 198 | } 199 | return $this->setHttpResponse('/estimate?' . $data, 'GET')->getResponse(); 200 | } 201 | 202 | /** 203 | * * This is the method to create a payment. You need to provide your data as a JSON-object payload. Next is a description of the required request fields: 204 | * price_amount (required) - the fiat equivalent of the price to be paid in crypto. If the pay_amount parameter is left empty, 205 | * our system will automatically convert this fiat price into its crypto equivalent. Please note that this does not enable fiat payments, only provides a fiat price for yours and the customer’s convenience and information. 206 | * price_currency (required) - the fiat currency in which the price_amount is specified (usd, eur, etc). 207 | * pay_amount (optional) - the amount that users have to pay for the order stated in crypto. You can either specify it yourself, or we will automatically convert the amount you indicated in price_amount. 208 | * pay_currency (required) - the crypto currency in which the pay_amount is specified (btc, eth, etc). 209 | * ipn_callback_url (optional) - url to receive callbacks, should contain "http" or "https", eg. "https://nowpayments.io" 210 | * order_id (optional) - inner store order ID, e.g. "RGDBP-21314" 211 | * order_description (optional) - inner store order description, e.g. "Apple Macbook Pro 2019 x 1" 212 | * purchase_id (optional) - id of purchase for which you want to create aother payment, only used for several payments for one order 213 | * payout_address (optional) - usually the funds will go to the address you specify in your Personal account. In case you want to receive funds on another address, you can specify it in this parameter. 214 | * payout_currency (optional) - currency of your external payout_address, required when payout_adress is specified. 215 | * payout_extra_id(optional) - extra id or memo or tag for external payout_address. 216 | * fixed_rate(optional) - boolean, can be true or false. Required for fixed-rate exchanges. 217 | * @param array $data 218 | * @return $this->getResponse() 219 | * 220 | */ 221 | 222 | public function createPayment($data = null): array 223 | { 224 | if ($data == null) { 225 | $data = [ 226 | 'price_amount' => request()->price_amount ?? 100, 227 | 'price_currency' => request()->price_currency ?? 'usd', 228 | 'pay_amount' => request()->pay_amount ?? null, 229 | 'pay_currency' => request()->pay_currency ?? Currency::BTC, 230 | 'ipn_callback_url' => request()->ipn_callback_url ?? $this->callbackUrl, 231 | 'order_id' => request()->order_id ?? uniqid(), 232 | 'order_description' => request()->order_description ?? null, 233 | 'purchase_id' => request()->purchase_id ?? null, 234 | 'payout_address' => request()->payout_address ?? 0, 235 | 'payout_currency' => request()->payout_currency ?? 0, 236 | 'payout_extra_id' => request()->payout_extra_id ?? null, 237 | 'fixed_rate' => request()->fixed_rate ?? true, 238 | "is_fee_paid_by_user" => false 239 | ]; 240 | } 241 | $dataForEstimate = 242 | "amount=" . $data['price_amount'] . "&" . 243 | "currency_from=" . $data['price_currency'] . "&" . 244 | "currency_to=" . $data['pay_currency']; 245 | 246 | if ($this->getEstimatePrice($dataForEstimate)['estimated_amount'] > $this->getMinimumPaymentAmount($data['pay_currency'], $data['payout_currency'])['min_amount']) 247 | return $this->setHttpResponse('/payment', 'POST', array_filter($data))->getResponse(); 248 | else 249 | return ['success' => false, 'message' => 'Estimated Price is less than the minimun price']; 250 | } 251 | 252 | /** 253 | * @param int $paymentId 254 | * @return array 255 | * 256 | */ 257 | public function getPaymentStatus($paymentId): array 258 | { 259 | return $this->setHttpResponse('/payment/' . $paymentId, 'GET')->getResponse(); 260 | } 261 | 262 | /** 263 | * Get the minimum payment amount for a specific pair. 264 | * You can provide both currencies in the pair or just currency_from, and we will calculate the minimum payment amount for currency_from and currency which you have specified as the outcome in the Store Settings. 265 | * In the case of several outcome wallets we will calculate the minimum amount in the same way we route your payment to a specific wallet. 266 | * @param $currency_from 267 | * @param $currency_to 268 | * @return array 269 | * 270 | */ 271 | public function getMinimumPaymentAmount($currency_from, $currency_to = null, $fiat_equivalent = null): array 272 | { 273 | if (!$currency_from) { 274 | $currency_from = Currency::USDT; 275 | } 276 | if (!$currency_to) { 277 | $currency_to = Currency::BTC; 278 | } 279 | if (!$fiat_equivalent) { 280 | $fiat_equivalent = "usd"; 281 | } 282 | 283 | return $this->setHttpResponse( 284 | '/min-amount?currency_from=' . $currency_from . 285 | "¤cy_to=" . $currency_to . 286 | "&fiat_equivalent=" . $fiat_equivalent, 287 | 'GET', 288 | )->getResponse(); 289 | } 290 | 291 | /** 292 | * 293 | * Returns the entire list of all transactions, created with certain API key. The list of optional parameters: 294 | * limit - number of records in one page. (possible values: from 1 to 500) 295 | * page - the page number you want to get (possible values: from 0 to page count - 1) 296 | * @param null|string $data 297 | * @return bool|array 298 | * 299 | */ 300 | public function getListOfPayments(string $data = null, string $jwt = null): array 301 | { 302 | if ($jwt == null) { 303 | $jwt = $this->getJwt(); 304 | } 305 | if ($data == null) { 306 | $data = "limit=10&page=0&sortBy=created_at&orderBy=asc&dateFrom=" . Carbon::now()->subMonth()->format('Y-m-d') . "&dateTo=" . 307 | Carbon::now()->format('Y-m-d'); 308 | } 309 | $this->setRequestOptions($jwt); 310 | return $this->setHttpResponse('/payment?' . $data, 'GET')->getResponse(); 311 | } 312 | 313 | /** 314 | * Creates invoice with url where you can complete the payment. Request fields: 315 | * 316 | * price_amount (required) - the amount that users have to pay for the order stated in fiat currency. In case you do not indicate the price in crypto, our system will automatically convert this fiat amount into its crypto equivalent. 317 | * price_currency (required) - the fiat currency in which the price_amount is specified (usd, eur, etc). 318 | * pay_currency (optional) - the crypto currency in which the pay_amount is specified (btc, eth, etc).If not specified, can be chosen on the invoice_url 319 | * ipn_callback_url (optional) - url to receive callbacks, should contain "http" or "https", eg. "https://nowpayments.io" 320 | * order_id (optional) - inner store order ID, e.g. "RGDBP-21314" 321 | * order_description (optional) - inner store order description, e.g. "Apple Macbook Pro 2019 x 1" 322 | * success_url(optional) - url where the customer will be redirected after successful payment. 323 | * cancel_url(optional) - url where the customer will be redirected after failed payment. 324 | * 325 | * @param array $data 326 | * @return array 327 | * 328 | */ 329 | public function createInvoice(array $data = null): array 330 | { 331 | if ($data == null) { 332 | $data = array_filter([ 333 | 'price_amount' => request()->price_amount ?? 100, 334 | 'price_currency' => request()->price_currency ?? 'usd', 335 | 'pay_amount' => request()->pay_amount ?? null, 336 | 'pay_currency' => request()->pay_currency ?? Currency::BTC, 337 | 'ipn_callback_url' => request()->ipn_callback_url ?? $this->callbackUrl, 338 | "success_url" => request()->success_url ?? $this->callbackUrl, 339 | "cancel_url" => request()->cancel_url ?? $this->callbackUrl, 340 | 'order_id' => request()->order_id ?? uniqid(), 341 | 'order_description' => request()->order_description ?? null, 342 | 'purchase_id' => request()->purchase_id ?? null, 343 | "is_fee_paid_by_user" => false 344 | ]); 345 | } 346 | 347 | return $this->setHttpResponse('/invoice', 'POST', array_filter($data))->getResponse(); 348 | } 349 | 350 | /** 351 | * Checks IPN received from Nowpayments IPN 352 | * @return bool 353 | */ 354 | public function verifyIPN(): bool 355 | { 356 | $receivedHmac = request()->header('x-nowpayments-sig'); 357 | if ($receivedHmac) { 358 | $requestData = collect(request()->all())->sortKeys(); // Utilize Collection for sorting 359 | $sortedRequestJson = json_encode($requestData, JSON_UNESCAPED_SLASHES); 360 | if ($requestData->isNotEmpty()) { 361 | $hmac = hash_hmac("sha512", $sortedRequestJson, trim(config('nowpayments.ipnSecret'))); 362 | return $hmac === $receivedHmac; 363 | } 364 | } 365 | return false; 366 | } 367 | 368 | 369 | /** 370 | * Logins in to your nowpayments account and gets the JWT. Request fields: 371 | * 372 | * email (optional) - Uses the details provided in the .env file, except overrided by providing another email here. 373 | * password (optional) - Uses the details provided in the .env file, except overrided by providing another password here 374 | * 375 | * @param string $email 376 | * @param string $password 377 | * @return string JWT 378 | * 379 | */ 380 | public function getJwt(string $email = null, string $password = null) 381 | { 382 | if (!$email) 383 | $email = config('nowpayments.email'); 384 | if (!$password) 385 | $password = config('nowpayments.password'); 386 | 387 | $data = array_filter([ 388 | 'email' => $email, 389 | 'password' => $password 390 | ]); 391 | return $this->setHttpResponse('/auth', 'POST', $data)->getResponse()['token']; 392 | } 393 | 394 | /** 395 | * This is the method to create a Recurring Payments plan. Every plan has its unique ID which is required for generating separate payments. 396 | * 397 | * "title": the name of your recurring payments plan, 398 | * "interval_day": recurring payments duration in days, 399 | * "amount" : amount of funds paid in fiat/crypto, 400 | * "currency" : crypto or fiat currency we support 401 | * @param array $data 402 | * @return array 403 | * 404 | */ 405 | public function createPlan(array $data = null): array 406 | { 407 | $jwt = $this->getJwt(); 408 | 409 | if ($data == null) { 410 | $data = array_filter([ 411 | "title" => request()->title ?? "Plan Title", 412 | "interval_day" => request()->interval ?? 1, 413 | "amount" => request()->amount ?? 0.5, 414 | "currency" => request()->currency ?? "usd" 415 | ]); 416 | } 417 | $this->setRequestOptions($jwt); 418 | return $this->setHttpResponse('/subscriptions/plans', 'POST', array_filter($data))->getResponse(); 419 | } 420 | 421 | /** 422 | * This method allows you to add necessary changes to a created plan. 423 | * They won’t affect users who have already paid; however, the changes will take effect when a new payment is to be made. 424 | * 425 | * "title": the name of your recurring payments plan, 426 | * "interval_day": recurring payments duration in days, 427 | * "amount" : amount of funds paid in fiat/crypto, 428 | * "currency" : crypto or fiat currency we support 429 | * @param array $data 430 | * @return array 431 | * 432 | */ 433 | public function updatePlan(string $plan_id = null, array $data = null): array 434 | { 435 | 436 | if ($plan_id == null) 437 | $plan_id = request()->plan_id; 438 | if ($data == null) 439 | $data = array_filter([ 440 | "title" => request()->title ?? "Plan Title", 441 | "interval_day" => request()->interval ?? 1, 442 | "amount" => request()->amount ?? 0.5, 443 | "currency" => request()->currency ?? "usd" 444 | ]); 445 | 446 | $jwt = $this->getJwt(); 447 | $this->setRequestOptions($jwt); 448 | return $this->setHttpResponse('/subscriptions/plans/' . $plan_id, 'PATCH', array_filter($data))->getResponse(); 449 | } 450 | 451 | /** 452 | * This method allows you to obtain information about your payment plan. 453 | * (you need to specify your payment plan id in the request). 454 | * "plan_id": the plan_id of your recurring payments plan, 455 | * 456 | * @param string $plan_id 457 | * @return array 458 | * 459 | */ 460 | public function getPlan(string $plan_id = null): array 461 | { 462 | if ($plan_id == null) 463 | $plan_id = request()->plan_id; 464 | 465 | return $this->setHttpResponse('/subscriptions/plans/' . $plan_id, 'GET', [])->getResponse(); 466 | } 467 | 468 | /** 469 | * This method allows you to obtain information about all the payment plans you’ve created. 470 | * "limit": the limit of plans you want to fetch, 471 | * 472 | * @param int $limit 473 | * @return array 474 | * 475 | */ 476 | public function getPlans(int $limit = null): array 477 | { 478 | if ($limit == null) 479 | $limit = request()->limit ?? 10; 480 | 481 | return $this->setHttpResponse('/subscriptions/plans/?limit=' . $limit, 'GET', [])->getResponse(); 482 | } 483 | 484 | /** 485 | * This method allows you to send payment links to your customers via email. 486 | * A day before the paid period ends, the customer receives a new letter with a new payment link. 487 | * 488 | * "subscription_plan_id": the ID of the payment plan your customer chooses, 489 | * "email": customer's email, 490 | * @param array $data 491 | * @return array 492 | * 493 | */ 494 | public function emailSubscription(array $data = null): array 495 | { 496 | 497 | if ($data == null) 498 | $data = array_filter([ 499 | "subscription_plan_id" => request()->plan_id, 500 | "email" => request()->email 501 | ]); 502 | 503 | $jwt = $this->getJwt(); 504 | $this->setRequestOptions($jwt); 505 | return $this->setHttpResponse('/subscriptions', 'POST', array_filter($data))->getResponse(); 506 | } 507 | 508 | /** 509 | * This method allows you to obtain information about all the Subscriptions you have. 510 | * 511 | * @return array 512 | * 513 | */ 514 | public function getSubscriptions(): array 515 | { 516 | return $this->setHttpResponse('/subscriptions', 'GET', [])->getResponse(); 517 | } 518 | 519 | /** 520 | * Get information about a particular recurring payment via its ID. 521 | * "subscription id": the id of recurring payments plan subscribed, 522 | * 523 | * @param string $sub_id 524 | * @return array 525 | * 526 | */ 527 | public function getSubscription(string $sub_id = null): array 528 | { 529 | if ($sub_id == null) 530 | $sub_id = request()->sub_id; 531 | 532 | return $this->setHttpResponse('/subscriptions/' . $sub_id, 'GET', [])->getResponse(); 533 | } 534 | 535 | /** 536 | * Completely removes a particular payment from the recurring payment plan. 537 | * You need to specify the payment plan id in the request. 538 | * "subscription id": the id of recurring payments plan subscribed, 539 | * 540 | * @param string $sub_id 541 | * @return array 542 | * 543 | */ 544 | public function deleteSubscription(string $sub_id = null): array 545 | { 546 | if ($sub_id == null) 547 | $sub_id = request()->sub_id; 548 | 549 | $jwt = $this->getJwt(); 550 | $this->setRequestOptions($jwt); 551 | return $this->setHttpResponse('/subscriptions/' . $sub_id, 'DELETE', [])->getResponse(); 552 | } 553 | } 554 | -------------------------------------------------------------------------------- /src/NowpaymentsServiceProvider.php: -------------------------------------------------------------------------------- 1 | 13 | * 14 | * For the full copyright and license information, please view the LICENSE 15 | * file that was distributed with this source code. 16 | */ 17 | 18 | class NowpaymentsServiceProvider extends ServiceProvider 19 | { 20 | 21 | /* 22 | * Indicates if loading of the provider is deferred. 23 | * 24 | * @var bool 25 | */ 26 | protected $defer = false; 27 | 28 | /** 29 | * Publishes all the config file this package needs to function 30 | */ 31 | public function boot() 32 | { 33 | $config = realpath(__DIR__.'/../utils/config/nowpayments.php'); 34 | 35 | $this->publishes([ 36 | $config => config_path('nowpayments.php') 37 | ]); 38 | $this->loadMigrationsFrom(__DIR__ . '/../database/migrations'); 39 | $this->mergeConfigFrom( 40 | __DIR__.'/../utils/config/nowpayments.php', 'nowpayments' 41 | ); 42 | if (File::exists(__DIR__ . '/../utils/helpers/nowpayments.php')) { 43 | require __DIR__ . '/../utils/helpers/nowpayments.php'; 44 | } 45 | $this->registerDashboard(); 46 | 47 | 48 | } 49 | 50 | /** 51 | * Register the application services. 52 | */ 53 | public function register() 54 | { 55 | $this->app->bind('laravel-nowpayments', function () { 56 | 57 | return new Nowpayments; 58 | 59 | }); 60 | } 61 | 62 | 63 | /** 64 | * Register the dashboard components. 65 | * 66 | * @return void 67 | */ 68 | protected function registerDashboard() 69 | { 70 | $this->loadRoutesFrom(__DIR__.'/../routes/routes.php'); 71 | $this->loadViewsFrom(__DIR__.'/../resources/views/', 'nowpayments'); 72 | $this->registerDashboardGate(); 73 | } 74 | 75 | /** 76 | * Register the dashboard gate. 77 | * 78 | * @return void 79 | */ 80 | protected function registerDashboardGate() 81 | { 82 | Gate::define('viewNowpaymentsDashboard', function ($user = null) { 83 | return $this->app->environment('local'); 84 | }); 85 | } 86 | 87 | 88 | /** 89 | * Get the services provided by the provider 90 | * @return array 91 | */ 92 | public function provides() 93 | { 94 | return ['laravel-nowpayments']; 95 | } 96 | } -------------------------------------------------------------------------------- /utils/config/nowpayments.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | 13 | return [ 14 | 15 | /** 16 | * API Key From NOWPayments Dashboard 17 | * 18 | */ 19 | 'apiKey' => env('NOWPAYMENTS_API_KEY'), 20 | 21 | /** 22 | * IPN Secret from NOWPayments Dashboard 23 | */ 24 | 'ipnSecret' => env('NOWPAYMENTS_IPN_SECRET'), 25 | 26 | /** 27 | * You enviroment can either be live or sandbox. 28 | * Make sure to add the appropriate API key after changing the enviroment in .env 29 | * 30 | */ 31 | 'env' => env('NOWPAYMENTS_ENV', 'sandbox'), 32 | 33 | /** 34 | * NOWPayments Live URL 35 | * 36 | */ 37 | 'liveUrl' => env('NOWPAYMENTS_LIVE_URL', "https://api.nowpayments.io/v1"), 38 | 39 | /** 40 | * NOWPayments Sandbox URL 41 | * 42 | */ 43 | 'sandboxUrl' => env('NOWPAYMENTS_SANDBOX_URL', "https://api-sandbox.nowpayments.io/v1"), 44 | 45 | /** 46 | * Your callback URL 47 | * 48 | */ 49 | 'callbackUrl' => env('NOWPAYMENTS_CALLBACK_URL'), 50 | 51 | /** 52 | * Your URL Path 53 | * 54 | */ 55 | 'path' => 'laravel-nowpayments', 56 | 57 | /** 58 | * You can add your custom middleware to access the dashboard here 59 | * 60 | */ 61 | 'middleware' => null, // "Authorise::class", 62 | 63 | /** 64 | * Your Nowpayment email here 65 | * 66 | */ 67 | 'email' => env('NOWPAYMENTS_EMAIL'), 68 | 69 | /** 70 | * Your Nowpayment password here 71 | * 72 | */ 73 | 'password' => env('NOWPAYMENTS_PASSWORD'), 74 | 75 | ]; -------------------------------------------------------------------------------- /utils/helpers/nowpayments.php: -------------------------------------------------------------------------------- 1 | make('laravel-nowpayments'); 8 | } 9 | } -------------------------------------------------------------------------------- /vendor/autoload.php: -------------------------------------------------------------------------------- 1 | 7 | * Jordi Boggiano 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | namespace Composer\Autoload; 14 | 15 | /** 16 | * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. 17 | * 18 | * $loader = new \Composer\Autoload\ClassLoader(); 19 | * 20 | * // register classes with namespaces 21 | * $loader->add('Symfony\Component', __DIR__.'/component'); 22 | * $loader->add('Symfony', __DIR__.'/framework'); 23 | * 24 | * // activate the autoloader 25 | * $loader->register(); 26 | * 27 | * // to enable searching the include path (eg. for PEAR packages) 28 | * $loader->setUseIncludePath(true); 29 | * 30 | * In this example, if you try to use a class in the Symfony\Component 31 | * namespace or one of its children (Symfony\Component\Console for instance), 32 | * the autoloader will first look for the class under the component/ 33 | * directory, and it will then fallback to the framework/ directory if not 34 | * found before giving up. 35 | * 36 | * This class is loosely based on the Symfony UniversalClassLoader. 37 | * 38 | * @author Fabien Potencier 39 | * @author Jordi Boggiano 40 | * @see https://www.php-fig.org/psr/psr-0/ 41 | * @see https://www.php-fig.org/psr/psr-4/ 42 | */ 43 | class ClassLoader 44 | { 45 | /** @var ?string */ 46 | private $vendorDir; 47 | 48 | // PSR-4 49 | /** 50 | * @var array[] 51 | * @psalm-var array> 52 | */ 53 | private $prefixLengthsPsr4 = array(); 54 | /** 55 | * @var array[] 56 | * @psalm-var array> 57 | */ 58 | private $prefixDirsPsr4 = array(); 59 | /** 60 | * @var array[] 61 | * @psalm-var array 62 | */ 63 | private $fallbackDirsPsr4 = array(); 64 | 65 | // PSR-0 66 | /** 67 | * @var array[] 68 | * @psalm-var array> 69 | */ 70 | private $prefixesPsr0 = array(); 71 | /** 72 | * @var array[] 73 | * @psalm-var array 74 | */ 75 | private $fallbackDirsPsr0 = array(); 76 | 77 | /** @var bool */ 78 | private $useIncludePath = false; 79 | 80 | /** 81 | * @var string[] 82 | * @psalm-var array 83 | */ 84 | private $classMap = array(); 85 | 86 | /** @var bool */ 87 | private $classMapAuthoritative = false; 88 | 89 | /** 90 | * @var bool[] 91 | * @psalm-var array 92 | */ 93 | private $missingClasses = array(); 94 | 95 | /** @var ?string */ 96 | private $apcuPrefix; 97 | 98 | /** 99 | * @var self[] 100 | */ 101 | private static $registeredLoaders = array(); 102 | 103 | /** 104 | * @param ?string $vendorDir 105 | */ 106 | public function __construct($vendorDir = null) 107 | { 108 | $this->vendorDir = $vendorDir; 109 | } 110 | 111 | /** 112 | * @return string[] 113 | */ 114 | public function getPrefixes() 115 | { 116 | if (!empty($this->prefixesPsr0)) { 117 | return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); 118 | } 119 | 120 | return array(); 121 | } 122 | 123 | /** 124 | * @return array[] 125 | * @psalm-return array> 126 | */ 127 | public function getPrefixesPsr4() 128 | { 129 | return $this->prefixDirsPsr4; 130 | } 131 | 132 | /** 133 | * @return array[] 134 | * @psalm-return array 135 | */ 136 | public function getFallbackDirs() 137 | { 138 | return $this->fallbackDirsPsr0; 139 | } 140 | 141 | /** 142 | * @return array[] 143 | * @psalm-return array 144 | */ 145 | public function getFallbackDirsPsr4() 146 | { 147 | return $this->fallbackDirsPsr4; 148 | } 149 | 150 | /** 151 | * @return string[] Array of classname => path 152 | * @psalm-return array 153 | */ 154 | public function getClassMap() 155 | { 156 | return $this->classMap; 157 | } 158 | 159 | /** 160 | * @param string[] $classMap Class to filename map 161 | * @psalm-param array $classMap 162 | * 163 | * @return void 164 | */ 165 | public function addClassMap(array $classMap) 166 | { 167 | if ($this->classMap) { 168 | $this->classMap = array_merge($this->classMap, $classMap); 169 | } else { 170 | $this->classMap = $classMap; 171 | } 172 | } 173 | 174 | /** 175 | * Registers a set of PSR-0 directories for a given prefix, either 176 | * appending or prepending to the ones previously set for this prefix. 177 | * 178 | * @param string $prefix The prefix 179 | * @param string[]|string $paths The PSR-0 root directories 180 | * @param bool $prepend Whether to prepend the directories 181 | * 182 | * @return void 183 | */ 184 | public function add($prefix, $paths, $prepend = false) 185 | { 186 | if (!$prefix) { 187 | if ($prepend) { 188 | $this->fallbackDirsPsr0 = array_merge( 189 | (array) $paths, 190 | $this->fallbackDirsPsr0 191 | ); 192 | } else { 193 | $this->fallbackDirsPsr0 = array_merge( 194 | $this->fallbackDirsPsr0, 195 | (array) $paths 196 | ); 197 | } 198 | 199 | return; 200 | } 201 | 202 | $first = $prefix[0]; 203 | if (!isset($this->prefixesPsr0[$first][$prefix])) { 204 | $this->prefixesPsr0[$first][$prefix] = (array) $paths; 205 | 206 | return; 207 | } 208 | if ($prepend) { 209 | $this->prefixesPsr0[$first][$prefix] = array_merge( 210 | (array) $paths, 211 | $this->prefixesPsr0[$first][$prefix] 212 | ); 213 | } else { 214 | $this->prefixesPsr0[$first][$prefix] = array_merge( 215 | $this->prefixesPsr0[$first][$prefix], 216 | (array) $paths 217 | ); 218 | } 219 | } 220 | 221 | /** 222 | * Registers a set of PSR-4 directories for a given namespace, either 223 | * appending or prepending to the ones previously set for this namespace. 224 | * 225 | * @param string $prefix The prefix/namespace, with trailing '\\' 226 | * @param string[]|string $paths The PSR-4 base directories 227 | * @param bool $prepend Whether to prepend the directories 228 | * 229 | * @throws \InvalidArgumentException 230 | * 231 | * @return void 232 | */ 233 | public function addPsr4($prefix, $paths, $prepend = false) 234 | { 235 | if (!$prefix) { 236 | // Register directories for the root namespace. 237 | if ($prepend) { 238 | $this->fallbackDirsPsr4 = array_merge( 239 | (array) $paths, 240 | $this->fallbackDirsPsr4 241 | ); 242 | } else { 243 | $this->fallbackDirsPsr4 = array_merge( 244 | $this->fallbackDirsPsr4, 245 | (array) $paths 246 | ); 247 | } 248 | } elseif (!isset($this->prefixDirsPsr4[$prefix])) { 249 | // Register directories for a new namespace. 250 | $length = strlen($prefix); 251 | if ('\\' !== $prefix[$length - 1]) { 252 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 253 | } 254 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 255 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 256 | } elseif ($prepend) { 257 | // Prepend directories for an already registered namespace. 258 | $this->prefixDirsPsr4[$prefix] = array_merge( 259 | (array) $paths, 260 | $this->prefixDirsPsr4[$prefix] 261 | ); 262 | } else { 263 | // Append directories for an already registered namespace. 264 | $this->prefixDirsPsr4[$prefix] = array_merge( 265 | $this->prefixDirsPsr4[$prefix], 266 | (array) $paths 267 | ); 268 | } 269 | } 270 | 271 | /** 272 | * Registers a set of PSR-0 directories for a given prefix, 273 | * replacing any others previously set for this prefix. 274 | * 275 | * @param string $prefix The prefix 276 | * @param string[]|string $paths The PSR-0 base directories 277 | * 278 | * @return void 279 | */ 280 | public function set($prefix, $paths) 281 | { 282 | if (!$prefix) { 283 | $this->fallbackDirsPsr0 = (array) $paths; 284 | } else { 285 | $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; 286 | } 287 | } 288 | 289 | /** 290 | * Registers a set of PSR-4 directories for a given namespace, 291 | * replacing any others previously set for this namespace. 292 | * 293 | * @param string $prefix The prefix/namespace, with trailing '\\' 294 | * @param string[]|string $paths The PSR-4 base directories 295 | * 296 | * @throws \InvalidArgumentException 297 | * 298 | * @return void 299 | */ 300 | public function setPsr4($prefix, $paths) 301 | { 302 | if (!$prefix) { 303 | $this->fallbackDirsPsr4 = (array) $paths; 304 | } else { 305 | $length = strlen($prefix); 306 | if ('\\' !== $prefix[$length - 1]) { 307 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 308 | } 309 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 310 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 311 | } 312 | } 313 | 314 | /** 315 | * Turns on searching the include path for class files. 316 | * 317 | * @param bool $useIncludePath 318 | * 319 | * @return void 320 | */ 321 | public function setUseIncludePath($useIncludePath) 322 | { 323 | $this->useIncludePath = $useIncludePath; 324 | } 325 | 326 | /** 327 | * Can be used to check if the autoloader uses the include path to check 328 | * for classes. 329 | * 330 | * @return bool 331 | */ 332 | public function getUseIncludePath() 333 | { 334 | return $this->useIncludePath; 335 | } 336 | 337 | /** 338 | * Turns off searching the prefix and fallback directories for classes 339 | * that have not been registered with the class map. 340 | * 341 | * @param bool $classMapAuthoritative 342 | * 343 | * @return void 344 | */ 345 | public function setClassMapAuthoritative($classMapAuthoritative) 346 | { 347 | $this->classMapAuthoritative = $classMapAuthoritative; 348 | } 349 | 350 | /** 351 | * Should class lookup fail if not found in the current class map? 352 | * 353 | * @return bool 354 | */ 355 | public function isClassMapAuthoritative() 356 | { 357 | return $this->classMapAuthoritative; 358 | } 359 | 360 | /** 361 | * APCu prefix to use to cache found/not-found classes, if the extension is enabled. 362 | * 363 | * @param string|null $apcuPrefix 364 | * 365 | * @return void 366 | */ 367 | public function setApcuPrefix($apcuPrefix) 368 | { 369 | $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; 370 | } 371 | 372 | /** 373 | * The APCu prefix in use, or null if APCu caching is not enabled. 374 | * 375 | * @return string|null 376 | */ 377 | public function getApcuPrefix() 378 | { 379 | return $this->apcuPrefix; 380 | } 381 | 382 | /** 383 | * Registers this instance as an autoloader. 384 | * 385 | * @param bool $prepend Whether to prepend the autoloader or not 386 | * 387 | * @return void 388 | */ 389 | public function register($prepend = false) 390 | { 391 | spl_autoload_register(array($this, 'loadClass'), true, $prepend); 392 | 393 | if (null === $this->vendorDir) { 394 | return; 395 | } 396 | 397 | if ($prepend) { 398 | self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; 399 | } else { 400 | unset(self::$registeredLoaders[$this->vendorDir]); 401 | self::$registeredLoaders[$this->vendorDir] = $this; 402 | } 403 | } 404 | 405 | /** 406 | * Unregisters this instance as an autoloader. 407 | * 408 | * @return void 409 | */ 410 | public function unregister() 411 | { 412 | spl_autoload_unregister(array($this, 'loadClass')); 413 | 414 | if (null !== $this->vendorDir) { 415 | unset(self::$registeredLoaders[$this->vendorDir]); 416 | } 417 | } 418 | 419 | /** 420 | * Loads the given class or interface. 421 | * 422 | * @param string $class The name of the class 423 | * @return true|null True if loaded, null otherwise 424 | */ 425 | public function loadClass($class) 426 | { 427 | if ($file = $this->findFile($class)) { 428 | includeFile($file); 429 | 430 | return true; 431 | } 432 | 433 | return null; 434 | } 435 | 436 | /** 437 | * Finds the path to the file where the class is defined. 438 | * 439 | * @param string $class The name of the class 440 | * 441 | * @return string|false The path if found, false otherwise 442 | */ 443 | public function findFile($class) 444 | { 445 | // class map lookup 446 | if (isset($this->classMap[$class])) { 447 | return $this->classMap[$class]; 448 | } 449 | if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { 450 | return false; 451 | } 452 | if (null !== $this->apcuPrefix) { 453 | $file = apcu_fetch($this->apcuPrefix.$class, $hit); 454 | if ($hit) { 455 | return $file; 456 | } 457 | } 458 | 459 | $file = $this->findFileWithExtension($class, '.php'); 460 | 461 | // Search for Hack files if we are running on HHVM 462 | if (false === $file && defined('HHVM_VERSION')) { 463 | $file = $this->findFileWithExtension($class, '.hh'); 464 | } 465 | 466 | if (null !== $this->apcuPrefix) { 467 | apcu_add($this->apcuPrefix.$class, $file); 468 | } 469 | 470 | if (false === $file) { 471 | // Remember that this class does not exist. 472 | $this->missingClasses[$class] = true; 473 | } 474 | 475 | return $file; 476 | } 477 | 478 | /** 479 | * Returns the currently registered loaders indexed by their corresponding vendor directories. 480 | * 481 | * @return self[] 482 | */ 483 | public static function getRegisteredLoaders() 484 | { 485 | return self::$registeredLoaders; 486 | } 487 | 488 | /** 489 | * @param string $class 490 | * @param string $ext 491 | * @return string|false 492 | */ 493 | private function findFileWithExtension($class, $ext) 494 | { 495 | // PSR-4 lookup 496 | $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; 497 | 498 | $first = $class[0]; 499 | if (isset($this->prefixLengthsPsr4[$first])) { 500 | $subPath = $class; 501 | while (false !== $lastPos = strrpos($subPath, '\\')) { 502 | $subPath = substr($subPath, 0, $lastPos); 503 | $search = $subPath . '\\'; 504 | if (isset($this->prefixDirsPsr4[$search])) { 505 | $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); 506 | foreach ($this->prefixDirsPsr4[$search] as $dir) { 507 | if (file_exists($file = $dir . $pathEnd)) { 508 | return $file; 509 | } 510 | } 511 | } 512 | } 513 | } 514 | 515 | // PSR-4 fallback dirs 516 | foreach ($this->fallbackDirsPsr4 as $dir) { 517 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { 518 | return $file; 519 | } 520 | } 521 | 522 | // PSR-0 lookup 523 | if (false !== $pos = strrpos($class, '\\')) { 524 | // namespaced class name 525 | $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) 526 | . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); 527 | } else { 528 | // PEAR-like class name 529 | $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; 530 | } 531 | 532 | if (isset($this->prefixesPsr0[$first])) { 533 | foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { 534 | if (0 === strpos($class, $prefix)) { 535 | foreach ($dirs as $dir) { 536 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 537 | return $file; 538 | } 539 | } 540 | } 541 | } 542 | } 543 | 544 | // PSR-0 fallback dirs 545 | foreach ($this->fallbackDirsPsr0 as $dir) { 546 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 547 | return $file; 548 | } 549 | } 550 | 551 | // PSR-0 include paths. 552 | if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { 553 | return $file; 554 | } 555 | 556 | return false; 557 | } 558 | } 559 | 560 | /** 561 | * Scope isolated include. 562 | * 563 | * Prevents access to $this/self from included files. 564 | * 565 | * @param string $file 566 | * @return void 567 | * @private 568 | */ 569 | function includeFile($file) 570 | { 571 | include $file; 572 | } 573 | -------------------------------------------------------------------------------- /vendor/composer/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) Nils Adermann, Jordi Boggiano 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is furnished 9 | to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | -------------------------------------------------------------------------------- /vendor/composer/autoload_classmap.php: -------------------------------------------------------------------------------- 1 | $vendorDir . '/composer/InstalledVersions.php', 10 | ); 11 | -------------------------------------------------------------------------------- /vendor/composer/autoload_files.php: -------------------------------------------------------------------------------- 1 | $baseDir . '/utils/helpers/nowpayments.php', 10 | ); 11 | -------------------------------------------------------------------------------- /vendor/composer/autoload_namespaces.php: -------------------------------------------------------------------------------- 1 | array($baseDir . '/src'), 10 | ); 11 | -------------------------------------------------------------------------------- /vendor/composer/autoload_real.php: -------------------------------------------------------------------------------- 1 | register(true); 33 | 34 | $includeFiles = \Composer\Autoload\ComposerStaticInitf2703251081e00d290418a10a15c4757::$files; 35 | foreach ($includeFiles as $fileIdentifier => $file) { 36 | composerRequiref2703251081e00d290418a10a15c4757($fileIdentifier, $file); 37 | } 38 | 39 | return $loader; 40 | } 41 | } 42 | 43 | /** 44 | * @param string $fileIdentifier 45 | * @param string $file 46 | * @return void 47 | */ 48 | function composerRequiref2703251081e00d290418a10a15c4757($fileIdentifier, $file) 49 | { 50 | if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { 51 | $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; 52 | 53 | require $file; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /vendor/composer/autoload_static.php: -------------------------------------------------------------------------------- 1 | __DIR__ . '/../..' . '/utils/helpers/nowpayments.php', 11 | ); 12 | 13 | public static $prefixLengthsPsr4 = array ( 14 | 'P' => 15 | array ( 16 | 'PrevailExcel\\Nowpayments\\' => 25, 17 | ), 18 | ); 19 | 20 | public static $prefixDirsPsr4 = array ( 21 | 'PrevailExcel\\Nowpayments\\' => 22 | array ( 23 | 0 => __DIR__ . '/../..' . '/src', 24 | ), 25 | ); 26 | 27 | public static $classMap = array ( 28 | 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 29 | ); 30 | 31 | public static function getInitializer(ClassLoader $loader) 32 | { 33 | return \Closure::bind(function () use ($loader) { 34 | $loader->prefixLengthsPsr4 = ComposerStaticInitf2703251081e00d290418a10a15c4757::$prefixLengthsPsr4; 35 | $loader->prefixDirsPsr4 = ComposerStaticInitf2703251081e00d290418a10a15c4757::$prefixDirsPsr4; 36 | $loader->classMap = ComposerStaticInitf2703251081e00d290418a10a15c4757::$classMap; 37 | 38 | }, null, ClassLoader::class); 39 | } 40 | } 41 | --------------------------------------------------------------------------------