allow vendord
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m3s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 32s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s

This commit is contained in:
2026-03-30 14:54:57 +07:00
parent 66aed7c4e8
commit b5e3a778ce
21316 changed files with 2777892 additions and 13 deletions

View File

@@ -0,0 +1,13 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: dipeshkhanal
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

View File

@@ -0,0 +1,2 @@
/.idea
.DS_Store

21
vendor/dipesh79/laravel-phonepe/LICENSE vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Dipesh Khanal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,89 @@
# Laravel PhonePe
[![Latest Stable Version](http://poser.pugx.org/dipesh79/laravel-phonepe/v)](https://packagist.org/packages/dipesh79/laravel-phonepe)
[![Total Downloads](http://poser.pugx.org/dipesh79/laravel-phonepe/downloads)](https://packagist.org/packages/dipesh79/laravel-phonepe)
[![License](http://poser.pugx.org/dipesh79/laravel-phonepe/license)](https://packagist.org/packages/dipesh79/laravel-phonepe)
This Laravel package allows you to integrate PhonePe payment on your Laravel Application.
## Usage/Examples
### Install Using Composer
```
composer require dipesh79/laravel-phonepe
```
### Add Variables in .env
```
PHONEPE_MERCHANT_ID="PGTESTPAYUAT"
PHONEPE_MERCHANT_USER_ID="MUID123"
PHONEPE_ENV="staging" //staging or production
PHONEPE_SALT_KEY="099eb0cd-02cf-4e2a-8aca-3e6c6aff0399"
PHONEPE_SALT_INDEX="1"
PHONEPE_CALLBACK_URL="http://localhost:8000"
```
### Publish Vendor File
```
php artisan vendor:publish
```
And publish "Dipesh79\LaravelPhonePe\LaravelPhonePeServiceProvider"
Redirect the user to payment page from your controller
```
use Dipesh79\LaravelPhonePe\LaravelPhonePe;
//Your Controller Method
public function phonePePayment()
{
$phonepe = new LaravelPhonePe();
//amount, phone number, callback url, unique merchant transaction id
$url = $phonepe->makePayment(1000, '9999999999', 'https://locahost:8000/redirct-url','1');
return redirect()->away($url);
}
```
### Check Payment Status
After Successful Payment PhonePe will redirect to your callback url with transaction id and status. You can check the
payment status using transaction id.
```
use Dipesh79\LaravelPhonePe\LaravelPhonePe;
use Illuminate\Http\Request;
public function callBackAction(Request $request)
{
$phonepe = new LaravelPhonePe();
$response = $phonepe->getTransactionStatus($request->all());
if($response == true){
//Payment Success
}
else
{
//Payment Failed
}
}
```
## License
[MIT](https://choosealicense.com/licenses/mit/)
## Author
- [@Dipesh79](https://www.github.com/Dipesh79)
## Support
For support, email dipeshkhanal79[at]gmail[dot]com.

View File

@@ -0,0 +1,29 @@
{
"name": "dipesh79/laravel-phonepe",
"description": "Laravel PhonePe - Laravel PhonePe Payment Integration Library",
"type": "library",
"license": "MIT",
"autoload": {
"psr-4": {
"Dipesh79\\LaravelPhonePe\\": "src"
}
},
"authors": [
{
"name": "Dipesh79",
"email": "dipeshkhanal79@gmail.com",
"homepage": "https://www.khanaldipesh.com.np",
"role": "Developer"
}
],
"minimum-stability": "dev",
"require": {},
"extra": {
"laravel": {
"providers": [
"Dipesh79\\LaravelPhonePe\\LaravelPhonePeServiceProvider"
]
}
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace Dipesh79\LaravelPhonePe\Exception;
class InvalidEnvironmentVariableException extends \Exception
{
public function __construct($message = "Invalid Environment Variable", $code =500, \Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace Dipesh79\LaravelPhonePe\Exception;
class PhonePeException extends \Exception
{
public function __construct($message = "PhonePe Exception", $code = 500, \Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
}
}

View File

@@ -0,0 +1,143 @@
<?php
namespace Dipesh79\LaravelPhonePe;
use Dipesh79\LaravelPhonePe\Exception\InvalidEnvironmentVariableException;
use Dipesh79\LaravelPhonePe\Exception\PhonePeException;
class LaravelPhonePe
{
private mixed $merchantId;
private mixed $merchantUserId;
private string $baseUrl;
private mixed $saltKey;
private mixed $saltIndex;
private mixed $callBackUrl;
/**
* @throws InvalidEnvironmentVariableException
*/
public function __construct()
{
$this->merchantId = config('phonepe.merchantId');
$this->merchantUserId = config('phonepe.merchantUserId');
$this->baseUrl = config('phonepe.env') == 'production' ? 'https://api.phonepe.com/apis/hermes' : 'https://api-preprod.phonepe.com/apis/pg-sandbox';
$this->saltKey = config('phonepe.saltKey');
$this->saltIndex = config('phonepe.saltIndex');
$this->callBackUrl = config('phonepe.callBackUrl');
$this->checkEnvironment();
}
/**
* @throws InvalidEnvironmentVariableException
*/
public function checkEnvironment(): void
{
if ($this->merchantId == null || $this->merchantId == '') {
throw new InvalidEnvironmentVariableException("Merchant Id is not added in .env file");
}
if ($this->merchantUserId == null || $this->merchantUserId == '') {
throw new InvalidEnvironmentVariableException("Merchant User Id is not added in .env file");
}
if ($this->saltKey == null || $this->saltKey == '') {
throw new InvalidEnvironmentVariableException("Salt Key is not added in .env file");
}
if ($this->saltIndex == null || $this->saltIndex == '') {
throw new InvalidEnvironmentVariableException("Salt Index is not added in .env file");
}
if ($this->callBackUrl == null || $this->callBackUrl == '') {
throw new InvalidEnvironmentVariableException("Call Back Url is not added in .env file");
}
}
/**
* @throws PhonePeException
*/
public function makePayment($amount, $phone, $redirectUrl, $merchantTransactionId): string
{
$data = array(
'merchantId' => $this->merchantId,
'merchantTransactionId' => $merchantTransactionId,
'merchantUserId' => $this->merchantUserId,
'amount' => $amount * 100,
'redirectUrl' => $redirectUrl,
'redirectMode' => 'POST',
'callbackUrl' => $this->callBackUrl,
'mobileNumber' => $phone,
'paymentInstrument' =>
array(
'type' => 'PAY_PAGE',
),
);
$encode = base64_encode(json_encode($data));
$string = $encode . '/pg/v1/pay' . $this->saltKey;
$sha256 = hash('sha256', $string);
$finalXHeader = $sha256 . '###' . $this->saltIndex;
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $this->baseUrl . '/pg/v1/pay',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => json_encode(['request' => $encode]),
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json',
'X-VERIFY: ' . $finalXHeader
),
));
$response = curl_exec($curl);
curl_close($curl);
$rData = json_decode($response);
if ($rData->success) {
return $rData->data->instrumentResponse->redirectInfo->url;
} else {
throw new PhonePeException($rData->message);
}
}
public function getTransactionStatus(array $request): bool
{
$finalXHeader = hash('sha256','/pg/v1/status/' . $request['merchantId'] . '/' . $request['transactionId'] . $this->saltKey) . '###' . $this->saltIndex;
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $this->baseUrl . '/pg/v1/status/' . $request['merchantId'] . '/' . $request['transactionId'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json',
'accept: application/json',
'X-VERIFY: ' . $finalXHeader,
'X-MERCHANT-ID: ' . $request['transactionId']
),
));
$response = curl_exec($curl);
curl_close($curl);
if (json_decode($response)->success) {
return true;
} else {
return false;
}
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace Dipesh79\LaravelPhonePe;
use Illuminate\Support\ServiceProvider;
class LaravelPhonePeServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
$this->publishes(
[
__DIR__ . '/config/phonepe.php' => config_path('phonepe.php'),
], 'config'
);
}
}

View File

@@ -0,0 +1,11 @@
<?php
return array(
'merchantId' => env('PHONEPE_MERCHANT_ID'),
'merchantUserId' => env('PHONEPE_MERCHANT_USER_ID'),
'env' => env('PHONEPE_ENV'),
'saltKey' => env('PHONEPE_SALT_KEY'),
'saltIndex' => env('PHONEPE_SALT_INDEX'),
'redirectUrl' => env('PHONEPE_REDIRECT_URL'),
'callBackUrl' => env('PHONEPE_CALLBACK_URL')
);