Proven Expertise
Our team brings years of experience in the digital payments industry to provide reliable services.
<?php
namespace Laravel\Socialite\Two;
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Laravel\Socialite\Contracts\Provider as ProviderContract;
abstract class AbstractProvider implements ProviderContract
{
/**
* The HTTP request instance.
*
* @var \Illuminate\Http\Request
*/
protected $request;
/**
* The HTTP Client instance.
*
* @var \GuzzleHttp\Client
*/
protected $httpClient;
/**
* The client ID.
*
* @var string
*/
protected $clientId;
/**
* The client secret.
*
* @var string
*/
protected $clientSecret;
/**
* The redirect URL.
*
* @var string
*/
protected $redirectUrl;
/**
* The custom parameters to be sent with the request.
*
* @var array
*/
protected $parameters = [];
/**
* The scopes being requested.
*
* @var array
*/
protected $scopes = [];
/**
* The separating character for the requested scopes.
*
* @var string
*/
protected $scopeSeparator = ',';
/**
* The type of the encoding in the query.
*
* @var int Can be either PHP_QUERY_RFC3986 or PHP_QUERY_RFC1738.
*/
protected $encodingType = PHP_QUERY_RFC1738;
/**
* Indicates if the session state should be utilized.
*
* @var bool
*/
protected $stateless = false;
/**
* Indicates if PKCE should be used.
*
* @var bool
*/
protected $usesPKCE = false;
/**
* The custom Guzzle configuration options.
*
* @var array
*/
protected $guzzle = [];
/**
* The cached user instance.
*
* @var \Laravel\Socialite\Two\User|null
*/
protected $user;
/**
* Create a new provider instance.
*
* @param \Illuminate\Http\Request $request
* @param string $clientId
* @param string $clientSecret
* @param string $redirectUrl
* @param array $guzzle
* @return void
*/
public function __construct(Request $request, $clientId, $clientSecret, $redirectUrl, $guzzle = [])
{
$this->guzzle = $guzzle;
$this->request = $request;
$this->clientId = $clientId;
$this->redirectUrl = $redirectUrl;
$this->clientSecret = $clientSecret;
}
/**
* Get the authentication URL for the provider.
*
* @param string $state
* @return string
*/
abstract protected function getAuthUrl($state);
/**
* Get the token URL for the provider.
*
* @return string
*/
abstract protected function getTokenUrl();
/**
* Get the raw user for the given access token.
*
* @param string $token
* @return array
*/
abstract protected function getUserByToken($token);
/**
* Map the raw user array to a Socialite User instance.
*
* @param array $user
* @return \Laravel\Socialite\Two\User
*/
abstract protected function mapUserToObject(array $user);
/**
* Redirect the user of the application to the provider's authentication screen.
*
* @return \Illuminate\Http\RedirectResponse
*/
public function redirect()
{
$state = null;
if ($this->usesState()) {
$this->request->session()->put('state', $state = $this->getState());
}
if ($this->usesPKCE()) {
$this->request->session()->put('code_verifier', $this->getCodeVerifier());
}
return new RedirectResponse($this->getAuthUrl($state));
}
/**
* Build the authentication URL for the provider from the given base URL.
*
* @param string $url
* @param string $state
* @return string
*/
protected function buildAuthUrlFromBase($url, $state)
{
return $url.'?'.http_build_query($this->getCodeFields($state), '', '&', $this->encodingType);
}
/**
* Get the GET parameters for the code request.
*
* @param string|null $state
* @return array
*/
protected function getCodeFields($state = null)
{
$fields = [
'client_id' => $this->clientId,
'redirect_uri' => $this->redirectUrl,
'scope' => $this->formatScopes($this->getScopes(), $this->scopeSeparator),
'response_type' => 'code',
];
if ($this->usesState()) {
$fields['state'] = $state;
}
if ($this->usesPKCE()) {
$fields['code_challenge'] = $this->getCodeChallenge();
$fields['code_challenge_method'] = $this->getCodeChallengeMethod();
}
return array_merge($fields, $this->parameters);
}
/**
* Format the given scopes.
*
* @param array $scopes
* @param string $scopeSeparator
* @return string
*/
protected function formatScopes(array $scopes, $scopeSeparator)
{
return implode($scopeSeparator, $scopes);
}
/**
* {@inheritdoc}
*/
public function user()
{
if ($this->user) {
return $this->user;
}
if ($this->hasInvalidState()) {
throw new InvalidStateException;
}
$response = $this->getAccessTokenResponse($this->getCode());
$user = $this->getUserByToken(Arr::get($response, 'access_token'));
return $this->userInstance($response, $user);
}
/**
* Create a user instance from the given data.
*
* @param array $response
* @param array $user
* @return \Laravel\Socialite\Two\User
*/
protected function userInstance(array $response, array $user)
{
$this->user = $this->mapUserToObject($user);
return $this->user->setToken(Arr::get($response, 'access_token'))
->setRefreshToken(Arr::get($response, 'refresh_token'))
->setExpiresIn(Arr::get($response, 'expires_in'))
->setApprovedScopes(explode($this->scopeSeparator, Arr::get($response, 'scope', '')));
}
/**
* Get a Social User instance from a known access token.
*
* @param string $token
* @return \Laravel\Socialite\Two\User
*/
public function userFromToken($token)
{
$user = $this->mapUserToObject($this->getUserByToken($token));
return $user->setToken($token);
}
/**
* Determine if the current request / session has a mismatching "state".
*
* @return bool
*/
protected function hasInvalidState()
{
if ($this->isStateless()) {
return false;
}
$state = $this->request->session()->pull('state');
return empty($state) || $this->request->input('state') !== $state;
}
/**
* Get the access token response for the given code.
*
* @param string $code
* @return array
*/
public function getAccessTokenResponse($code)
{
$response = $this->getHttpClient()->post($this->getTokenUrl(), [
RequestOptions::HEADERS => $this->getTokenHeaders($code),
RequestOptions::FORM_PARAMS => $this->getTokenFields($code),
]);
return json_decode($response->getBody(), true);
}
/**
* Get the headers for the access token request.
*
* @param string $code
* @return array
*/
protected function getTokenHeaders($code)
{
return ['Accept' => 'application/json'];
}
/**
* Get the POST fields for the token request.
*
* @param string $code
* @return array
*/
protected function getTokenFields($code)
{
$fields = [
'grant_type' => 'authorization_code',
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret,
'code' => $code,
'redirect_uri' => $this->redirectUrl,
];
if ($this->usesPKCE()) {
$fields['code_verifier'] = $this->request->session()->pull('code_verifier');
}
return $fields;
}
/**
* Refresh a user's access token with a refresh token.
*
* @param string $refreshToken
* @return \Laravel\Socialite\Two\Token
*/
public function refreshToken($refreshToken)
{
$response = $this->getRefreshTokenResponse($refreshToken);
return new Token(
Arr::get($response, 'access_token'),
Arr::get($response, 'refresh_token'),
Arr::get($response, 'expires_in'),
explode($this->scopeSeparator, Arr::get($response, 'scope', ''))
);
}
/**
* Get the refresh token response for the given refresh token.
*
* @param string $refreshToken
* @return array
*/
protected function getRefreshTokenResponse($refreshToken)
{
return json_decode($this->getHttpClient()->post($this->getTokenUrl(), [
RequestOptions::HEADERS => ['Accept' => 'application/json'],
RequestOptions::FORM_PARAMS => [
'grant_type' => 'refresh_token',
'refresh_token' => $refreshToken,
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret,
],
])->getBody(), true);
}
/**
* Get the code from the request.
*
* @return string
*/
protected function getCode()
{
return $this->request->input('code');
}
/**
* Merge the scopes of the requested access.
*
* @param array|string $scopes
* @return $this
*/
public function scopes($scopes)
{
$this->scopes = array_unique(array_merge($this->scopes, (array) $scopes));
return $this;
}
/**
* Set the scopes of the requested access.
*
* @param array|string $scopes
* @return $this
*/
public function setScopes($scopes)
{
$this->scopes = array_unique((array) $scopes);
return $this;
}
/**
* Get the current scopes.
*
* @return array
*/
public function getScopes()
{
return $this->scopes;
}
/**
* Set the redirect URL.
*
* @param string $url
* @return $this
*/
public function redirectUrl($url)
{
$this->redirectUrl = $url;
return $this;
}
/**
* Get a instance of the Guzzle HTTP client.
*
* @return \GuzzleHttp\Client
*/
protected function getHttpClient()
{
if (is_null($this->httpClient)) {
$this->httpClient = new Client($this->guzzle);
}
return $this->httpClient;
}
/**
* Set the Guzzle HTTP client instance.
*
* @param \GuzzleHttp\Client $client
* @return $this
*/
public function setHttpClient(Client $client)
{
$this->httpClient = $client;
return $this;
}
/**
* Set the request instance.
*
* @param \Illuminate\Http\Request $request
* @return $this
*/
public function setRequest(Request $request)
{
$this->request = $request;
return $this;
}
/**
* Determine if the provider is operating with state.
*
* @return bool
*/
protected function usesState()
{
return ! $this->stateless;
}
/**
* Determine if the provider is operating as stateless.
*
* @return bool
*/
protected function isStateless()
{
return $this->stateless;
}
/**
* Indicates that the provider should operate as stateless.
*
* @return $this
*/
public function stateless()
{
$this->stateless = true;
return $this;
}
/**
* Get the string used for session state.
*
* @return string
*/
protected function getState()
{
return Str::random(40);
}
/**
* Determine if the provider uses PKCE.
*
* @return bool
*/
protected function usesPKCE()
{
return $this->usesPKCE;
}
/**
* Enables PKCE for the provider.
*
* @return $this
*/
public function enablePKCE()
{
$this->usesPKCE = true;
return $this;
}
/**
* Generates a random string of the right length for the PKCE code verifier.
*
* @return string
*/
protected function getCodeVerifier()
{
return Str::random(96);
}
/**
* Generates the PKCE code challenge based on the PKCE code verifier in the session.
*
* @return string
*/
protected function getCodeChallenge()
{
$hashed = hash('sha256', $this->request->session()->get('code_verifier'), true);
return rtrim(strtr(base64_encode($hashed), '+/', '-_'), '=');
}
/**
* Returns the hash method used to calculate the PKCE code challenge.
*
* @return string
*/
protected function getCodeChallengeMethod()
{
return 'S256';
}
/**
* Set the custom parameters of the request.
*
* @param array $parameters
* @return $this
*/
public function with(array $parameters)
{
$this->parameters = $parameters;
return $this;
}
}
How it Works
Getting started with NFC Pay is simple and quick. Register your account, add your cards, and you're ready to make payments in no time. Whether you're paying at a store, sending money to a friend, or managing your merchant transactions, NFC Pay makes it easy and secure.
Download the NFC Pay app and sign up with your email or phone number. Complete the registration process by verifying your identity, and set up your secure PIN to protect your account.
Link your debit or credit cards to your NFC Pay wallet. Simply scan your card or enter the details manually, and you’re set to load funds, shop, and pay with ease.
To pay, simply tap your phone or scan the QR code at checkout. You can also transfer money to other users with a few taps. Enjoy fast, contactless payments with top-notch security.
Security System
NFC Pay prioritizes your security with advanced features that safeguard every transaction. From SMS or email verification to end-to-end encryption, we've implemented robust measures to ensure your data is always protected. Our security systems are designed to prevent unauthorized access and provide you with a safe and reliable payment experience.
Receive instant alerts for every transaction to keep track of your account activities.
Verify your identity through our Know Your Customer process to prevent fraud and enhance security.
Dramatically supply transparent backward deliverables before caward comp internal or "organic" sources.
All your data and transactions are encrypted, ensuring that your sensitive information remains private.
Monitor unusual activity patterns to detect and prevent suspicious behavior in real-time.
Why Choice Us
With NFC Pay, you get a trusted platform backed by proven expertise and a commitment to quality. We put our customers first, offering innovative solutions tailored to your needs, ensuring every transaction is secure, swift, and seamless.
Our team brings years of experience in the digital payments industry to provide reliable services.
We prioritize excellence, ensuring that every aspect of our platform meets the highest standards.
Your needs drive our solutions, and we are dedicated to delivering a superior user experience.
We continuously evolve, integrating the latest technologies to enhance your payment experience.
Testimonial Section
Hear from our users who trust NFC Pay for their everyday transactions. Our commitment to security, ease of use, and exceptional service shines through in their experiences. See why our clients choose NFC Pay for their payment needs and how it has transformed the way they manage their finances.
App Section
Unlock the full potential of NFC Pay by downloading our app, designed to bring secure, swift, and smart transactions to your fingertips. Whether you're paying at a store, transferring money to friends, or managing your business payments, the NFC Pay app makes it effortless. Available on both iOS and Android, it's your all-in-one solution for convenient and reliable digital payments. Download now and experience the future of payments!