#php #laravel #paypal
#php #laravel #paypal
Вопрос:
Я получаю эту ошибку, когда пытаюсь создать новый объект
$provider = new ExpressCheckout;
$response = $provider->setExpressCheckout($checkoutData);
Я использую этот пакет https://github.com/srmklive/laravel-paypal чтобы интегрировать PayPal ExpressCheckout в мое приложение Laravel
Это модель из пакета, которую я использую для создания объекта.
ExpressCheckout.php
<?php
namespace SrmklivePayPalServices;
use Exception;
use IlluminateSupportCollection;
use PsrHttpMessageStreamInterface;
use SrmklivePayPalTraitsPayPalRequest as PayPalAPIRequest;
use SrmklivePayPalTraitsPayPalTransactions;
use SrmklivePayPalTraitsRecurringProfiles;
class ExpressCheckout
{
// Integrate PayPal Request trait
use PayPalAPIRequest;
use PayPalTransactions;
use RecurringProfiles;
/**
* ExpressCheckout constructor.
*
* @param array $config
*
* @throws Exception
*/
public function __construct(array $config = [])
{
// Setting PayPal API Credentials
$this->setConfig($config);
$this->httpBodyParam = 'form_params';
$this->options = [];
}
/**
* Set ExpressCheckout API endpoints amp; options.
*
* @param array $credentials
*
* @return void
*/
public function setExpressCheckoutOptions($credentials)
{
// Setting API Endpoints
if ($this->mode === 'sandbox') {
$this->config['api_url'] = !empty($this->config['secret']) ?
'https://api-3t.sandbox.paypal.com/nvp' : 'https://api.sandbox.paypal.com/nvp';
$this->config['gateway_url'] = 'https://www.sandbox.paypal.com';
$this->config['ipn_url'] = 'https://ipnpb.sandbox.paypal.com/cgi-bin/webscr';
} else {
$this->config['api_url'] = !empty($this->config['secret']) ?
'https://api-3t.paypal.com/nvp' : 'https://api.paypal.com/nvp';
$this->config['gateway_url'] = 'https://www.paypal.com';
$this->config['ipn_url'] = 'https://ipnpb.paypal.com/cgi-bin/webscr';
}
// Adding params outside sandbox / live array
$this->config['payment_action'] = $credentials['payment_action'];
$this->config['notify_url'] = $credentials['notify_url'];
$this->config['locale'] = $credentials['locale'];
}
/**
* Set cart item details for PayPal.
*
* @param array $items
*
* @return Collection
*/
protected function setCartItems($items)
{
return (new Collection($items))->map(static function ($item, $num) {
return [
'L_PAYMENTREQUEST_0_NAME'.$num => $item['name'],
'L_PAYMENTREQUEST_0_AMT'.$num => $item['price'],
'L_PAYMENTREQUEST_0_DESC'.$num => isset($item['desc']) ? $item['desc'] : null,
'L_PAYMENTREQUEST_0_QTY'.$num => isset($item['qty']) ? $item['qty'] : 1,
];
})->flatMap(static function ($value) {
return $value;
});
}
/**
* Set Recurring payments details for SetExpressCheckout API call.
*
* @param array $data
* @param bool $subscription
*/
protected function setExpressCheckoutRecurringPaymentConfig($data, $subscription = false)
{
$billingType = $this->billingType;
// Overwrite billing type if $subscription flag is enabled
if ($subscription) {
$billingType = 'RecurringPayments';
}
// Send L_BILLINGTYPE0 and L_BILLINGAGREEMENTDESCRIPTION0 only if there is billing type
if (isset($billingType)) {
$this->post = $this->post->merge([
'L_BILLINGTYPE0' => $billingType,
'L_BILLINGAGREEMENTDESCRIPTION0' => !empty($data['subscription_desc']) ?
$data['subscription_desc'] : $data['invoice_description'],
]);
}
}
/**
* Set item subtotal if available.
*
* @param array $data
*/
protected function setItemSubTotal($data)
{
$this->subtotal = isset($data['subtotal']) ? $data['subtotal'] : $data['total'];
}
/**
* Set shipping amount if available.
*
* @param array $data
*/
protected function setShippingAmount($data)
{
if (isset($data['shipping'])) {
$this->post = $this->post->merge([
'PAYMENTREQUEST_0_SHIPPINGAMT' => $data['shipping'],
]);
}
}
/**
* Set tax amount if available.
*
* @param array $data
*/
protected function setTaxAmount($data)
{
if (isset($data['tax'])) {
$this->post = $this->post->merge([
'PAYMENTREQUEST_0_TAXAMT' => $data['tax'],
]);
}
}
/**
* Set shipping discount if available.
*
* @param array $data
*/
protected function setShippingDiscount($data)
{
if (isset($data['shipping_discount'])) {
if ($data['shipping_discount'] > 0) {
$data['shipping_discount'] *= -1;
}
$this->post = $this->post->merge([
'PAYMENTREQUEST_0_SHIPDISCAMT' => $data['shipping_discount'],
'PAYMENTREQUEST_0_AMT' => round($data['total'] $data['shipping_discount'], 2),
]);
}
}
/**
* Perform a SetExpressCheckout API call on PayPal.
*
* @param array $data
* @param bool $subscription
*
* @throws Exception
*
* @return array|StreamInterface
*/
public function setExpressCheckout($data, $subscription = false)
{
$this->setItemSubTotal($data);
$this->post = $this->setCartItems($data['items'])->merge([
'PAYMENTREQUEST_0_ITEMAMT' => $this->subtotal,
'PAYMENTREQUEST_0_AMT' => $data['total'],
'PAYMENTREQUEST_0_PAYMENTACTION' => $this->paymentAction,
'PAYMENTREQUEST_0_CURRENCYCODE' => $this->currency,
'PAYMENTREQUEST_0_DESC' => $data['invoice_description'],
'PAYMENTREQUEST_0_INVNUM' => $data['invoice_id'],
'NOSHIPPING' => 1,
'RETURNURL' => $data['return_url'],
'CANCELURL' => $data['cancel_url'],
'LOCALE' => $this->locale,
]);
$this->setTaxAmount($data);
$this->setShippingAmount($data);
$this->setShippingDiscount($data);
$this->setTaxAmount($data);
$this->setExpressCheckoutRecurringPaymentConfig($data, $subscription);
$response = $this->doPayPalRequest('SetExpressCheckout');
return collect($response)->merge([
'paypal_link' => !empty($response['TOKEN']) ? $this->config['gateway_url'].'/webscr?cmd=_express-checkoutamp;token='.$response['TOKEN'] : null,
])->toArray();
}
/**
* Perform a GetExpressCheckoutDetails API call on PayPal.
*
* @param string $token
*
* @throws Exception
*
* @return array|StreamInterface
*/
public function getExpressCheckoutDetails($token)
{
$this->setRequestData([
'TOKEN' => $token,
]);
return $this->doPayPalRequest('GetExpressCheckoutDetails');
}
/**
* Perform DoExpressCheckoutPayment API call on PayPal.
*
* @param array $data
* @param string $token
* @param string $payerId
*
* @throws Exception
*
* @return array|StreamInterface
*/
public function doExpressCheckoutPayment($data, $token, $payerId)
{
$this->setItemSubTotal($data);
$this->post = $this->setCartItems($data['items'])->merge([
'TOKEN' => $token,
'PAYERID' => $payerId,
'PAYMENTREQUEST_0_ITEMAMT' => $this->subtotal,
'PAYMENTREQUEST_0_AMT' => $data['total'],
'PAYMENTREQUEST_0_PAYMENTACTION' => !empty($this->config['payment_action']) ? $this->config['payment_action'] : 'Sale',
'PAYMENTREQUEST_0_CURRENCYCODE' => $this->currency,
'PAYMENTREQUEST_0_DESC' => $data['invoice_description'],
'PAYMENTREQUEST_0_INVNUM' => $data['invoice_id'],
'PAYMENTREQUEST_0_NOTIFYURL' => $this->notifyUrl,
]);
$this->setTaxAmount($data);
$this->setShippingAmount($data);
return $this->doPayPalRequest('DoExpressCheckoutPayment');
}
/**
* Perform a DoAuthorization API call on PayPal.
*
* @param string $authorizationId Transaction ID
* @param float $amount Amount to capture
* @param array $data Optional request fields
*
* @throws Exception
*
* @return array|StreamInterface
*/
public function doAuthorization($authorizationId, $amount, $data = [])
{
$this->setRequestData(
array_merge($data, [
'AUTHORIZATIONID' => $authorizationId,
'AMT' => $amount,
])
);
return $this->doPayPalRequest('DoAuthorization');
}
/**
* Perform a DoCapture API call on PayPal.
*
* @param string $authorizationId Transaction ID
* @param float $amount Amount to capture
* @param string $complete Indicates whether or not this is the last capture.
* @param array $data Optional request fields
*
* @throws Exception
*
* @return array|StreamInterface
*/
public function doCapture($authorizationId, $amount, $complete = 'Complete', $data = [])
{
$this->setRequestData(
array_merge($data, [
'AUTHORIZATIONID' => $authorizationId,
'AMT' => $amount,
'COMPLETETYPE' => $complete,
'CURRENCYCODE' => $this->currency,
])
);
return $this->doPayPalRequest('DoCapture');
}
/**
* Perform a DoReauthorization API call on PayPal to reauthorize an existing authorization transaction.
*
* @param string $authorizationId
* @param float $amount
* @param array $data
*
* @throws Exception
*
* @return array|StreamInterface
*/
public function doReAuthorization($authorizationId, $amount, $data = [])
{
$this->setRequestData(
array_merge($data, [
'AUTHORIZATIONID' => $authorizationId,
'AMOUNT' => $amount,
])
);
return $this->doPayPalRequest('DoReauthorization');
}
/**
* Perform a DoVoid API call on PayPal.
*
* @param string $authorizationId Transaction ID
* @param array $data Optional request fields
*
* @throws Exception
*
* @return array|StreamInterface
*/
public function doVoid($authorizationId, $data = [])
{
$this->setRequestData(
array_merge($data, [
'AUTHORIZATIONID' => $authorizationId,
])
);
return $this->doPayPalRequest('DoVoid');
}
/**
* Perform a CreateBillingAgreement API call on PayPal.
*
* @param string $token
*
* @throws Exception
*
* @return array|StreamInterface
*/
public function createBillingAgreement($token)
{
$this->setRequestData([
'TOKEN' => $token,
]);
return $this->doPayPalRequest('CreateBillingAgreement');
}
/**
* Perform a CreateRecurringPaymentsProfile API call on PayPal.
*
* @param array $data
* @param string $token
*
* @throws Exception
*
* @return array|StreamInterface
*/
public function createRecurringPaymentsProfile($data, $token)
{
$this->post = $this->setRequestData($data)->merge([
'TOKEN' => $token,
]);
return $this->doPayPalRequest('CreateRecurringPaymentsProfile');
}
/**
* Perform a GetRecurringPaymentsProfileDetails API call on PayPal.
*
* @param string $id
*
* @throws Exception
*
* @return array|StreamInterface
*/
public function getRecurringPaymentsProfileDetails($id)
{
$this->setRequestData([
'PROFILEID' => $id,
]);
return $this->doPayPalRequest('GetRecurringPaymentsProfileDetails');
}
/**
* Perform a UpdateRecurringPaymentsProfile API call on PayPal.
*
* @param array $data
* @param string $id
*
* @throws Exception
*
* @return array|StreamInterface
*/
public function updateRecurringPaymentsProfile($data, $id)
{
$this->post = $this->setRequestData($data)->merge([
'PROFILEID' => $id,
]);
return $this->doPayPalRequest('UpdateRecurringPaymentsProfile');
}
/**
* Change Recurring payment profile status on PayPal.
*
* @param string $id
* @param string $status
*
* @throws Exception
*
* @return array|StreamInterface
*/
protected function manageRecurringPaymentsProfileStatus($id, $status)
{
$this->setRequestData([
'PROFILEID' => $id,
'ACTION' => $status,
]);
return $this->doPayPalRequest('ManageRecurringPaymentsProfileStatus');
}
/**
* Perform a ManageRecurringPaymentsProfileStatus API call on PayPal to cancel a RecurringPaymentsProfile.
*
* @param string $id
*
* @throws Exception
*
* @return array|StreamInterface
*/
public function cancelRecurringPaymentsProfile($id)
{
return $this->manageRecurringPaymentsProfileStatus($id, 'Cancel');
}
/**
* Perform a ManageRecurringPaymentsProfileStatus API call on PayPal to suspend a RecurringPaymentsProfile.
*
* @param string $id
*
* @throws Exception
*
* @return array|StreamInterface
*/
public function suspendRecurringPaymentsProfile($id)
{
return $this->manageRecurringPaymentsProfileStatus($id, 'Suspend');
}
/**
* Perform a ManageRecurringPaymentsProfileStatus API call on PayPal to reactivate a RecurringPaymentsProfile.
*
* @param string $id
*
* @throws Exception
*
* @return array|StreamInterface
*/
public function reactivateRecurringPaymentsProfile($id)
{
return $this->manageRecurringPaymentsProfileStatus($id, 'Reactivate');
}
}
PayPalRequest.php
<?php
namespace SrmklivePayPalTraits;
use Exception;
use GuzzleHttpClient as HttpClient;
use IlluminateSupportCollection;
use PsrHttpMessageStreamInterface;
use RuntimeException;
use SrmklivePayPalServicesAdaptivePayments;
use SrmklivePayPalServicesExpressCheckout;
trait PayPalRequest
{
use PayPalHttpClient;
/**
* Http Client class object.
*
* @var HttpClient
*/
private $client;
/**
* Http Client configuration.
*
* @var array
*/
private $httpClientConfig;
/**
* PayPal API Certificate data for authentication.
*
* @var string
*/
private $certificate;
/**
* PayPal API mode to be used.
*
* @var string
*/
public $mode;
/**
* Request data to be sent to PayPal.
*
* @var Collection
*/
protected $post;
/**
* PayPal API configuration.
*
* @var array
*/
private $config;
/**
* Item subtotal.
*
* @var float
*/
private $subtotal;
/**
* Default currency for PayPal.
*
* @var string
*/
private $currency;
/**
* Default billing type for PayPal reference transactions.
*
* @var string
*/
private $billingType;
/**
* Additional options for PayPal API request.
*
* @var array
*/
private $options;
/**
* Default payment action for PayPal.
*
* @var string
*/
private $paymentAction;
/**
* Default locale for PayPal.
*
* @var string
*/
private $locale;
/**
* PayPal API Endpoint.
*
* @var string
*/
private $apiUrl;
/**
* IPN notification url for PayPal.
*
* @var string
*/
private $notifyUrl;
/**
* Http Client request body parameter name.
*
* @var string
*/
private $httpBodyParam;
/**
* Validate SSL details when creating HTTP client.
*
* @var bool
*/
private $validateSSL;
/**
* Set PayPal API Credentials.
*
* @param array $credentials
*
* @throws Exception
*
* @return void
*/
public function setApiCredentials($credentials)
{
// Setting Default PayPal Mode If not set
$this->setApiEnvironment($credentials);
// Set API configuration for the PayPal provider
$this->setApiProviderConfiguration($credentials);
// Set default currency.
$this->setCurrency($credentials['currency']);
// Set default billing type
$this->setBillingType($credentials['billing_type']);
// Set Http Client configuration.
$this->setHttpClientConfiguration();
}
/**
* Set other/override PayPal API parameters.
*
* @param array $options
*
* @return $this
*/
public function addOptions(array $options)
{
$this->options = $options;
return $this;
}
/**
* Function to set currency.
*
* @param string $currency
*
* @throws Exception
*
* @return $this
*/
public function setCurrency($currency = 'USD')
{
$allowedCurrencies = ['AUD', 'BRL', 'CAD', 'CZK', 'DKK', 'EUR', 'HKD', 'HUF', 'ILS', 'INR', 'JPY', 'MYR', 'MXN', 'NOK', 'NZD', 'PHP', 'PLN', 'GBP', 'SGD', 'SEK', 'CHF', 'TWD', 'THB', 'USD', 'RUB'];
// Check if provided currency is valid.
if (!in_array($currency, $allowedCurrencies, true)) {
throw new Exception('Currency is not supported by PayPal.');
}
$this->currency = $currency;
return $this;
}
/**
* Function to set billing type.
*
* @param string $billingType
*
* @throws Exception
*
* @return $this
*/
public function setBillingType($billingType = 'MerchantInitiatedBilling')
{
$allowedBillingTypes = ['MerchantInitiatedBilling', 'MerchantInitiatedBillingSingleAgreement', 'RecurringPayments'];
if ($billingType !== null amp;amp; !in_array($billingType, $allowedBillingTypes, true)) {
throw new RuntimeException('Billing type is not supported by PayPal.');
}
$this->billingType = $billingType;
return $this;
}
/**
* Retrieve PayPal IPN Response.
*
* @param array $post
*
* @throws Exception
*
* @return array
*/
public function verifyIPN($post)
{
$this->setRequestData($post);
$this->apiUrl = $this->config['ipn_url'];
return $this->doPayPalRequest('verifyipn');
}
/**
* Setup request data to be sent to PayPal.
*
* @param array $data
*
* @return Collection
*/
protected function setRequestData(array $data = [])
{
if (($this->post instanceof Collection) amp;amp; (!$this->post->isEmpty())) {
unset($this->post);
}
$this->post = new Collection($data);
return $this->post;
}
/**
* Function To Set PayPal API Configuration.
*
* @param array $config
*
* @throws Exception
*/
private function setConfig(array $config = [])
{
// Set Api Credentials
if (function_exists('config')) {
$this->setApiCredentials(
config('paypal')
);
} elseif (!empty($config)) {
$this->setApiCredentials($config);
}
$this->setRequestData();
}
/**
* Set default values for configuration.
*
* @return void
*/
private function setDefaultValues()
{
// Set default payment action.
if (empty($this->paymentAction)) {
$this->paymentAction = 'Sale';
}
// Set default locale.
if (empty($this->locale)) {
$this->locale = 'en_US';
}
// Set default value for SSL validation.
if (empty($this->validateSSL)) {
$this->validateSSL = false;
}
}
/**
* Set API environment to be used by PayPal.
*
* @param array $credentials
*
* @return void
*/
private function setApiEnvironment($credentials)
{
if (empty($credentials['mode']) || !in_array($credentials['mode'], ['sandbox', 'live'])) {
$this->mode = 'live';
} else {
$this->mode = $credentials['mode'];
}
}
/**
* Set configuration details for the provider.
*
* @param array $credentials
*
* @throws Exception
*
* @return void
*/
private function setApiProviderConfiguration($credentials)
{
// Setting PayPal API Credentials
collect($credentials[$this->mode])->map(function ($value, $key) {
$this->config[$key] = $value;
});
// Setup PayPal API Signature value to use.
$this->config['signature'] = empty($this->config['certificate']) ?
$this->config['secret'] : $this->config['certificate'];
$this->paymentAction = $credentials['payment_action'];
$this->locale = $credentials['locale'];
$this->certificate = $this->config['certificate'];
$this->validateSSL = $credentials['validate_ssl'];
$this->setApiProvider($credentials);
}
/**
* Determines which API provider should be used.
*
* @param array $credentials
*
* @throws Exception
*/
private function setApiProvider($credentials)
{
if ($this instanceof AdaptivePayments) {
return $this->setAdaptivePaymentsOptions();
}
if ($this instanceof ExpressCheckout) {
return $this->setExpressCheckoutOptions($credentials);
}
throw new RuntimeException('Invalid api credentials provided for PayPal!. Please provide the right api credentials.');
}
/**
* Create request payload to be sent to PayPal.
*
* @param string $method
*/
private function createRequestPayload($method)
{
$config = array_merge([
'USER' => $this->config['username'],
'PWD' => $this->config['password'],
'SIGNATURE' => $this->config['signature'],
'VERSION' => 123,
'METHOD' => $method,
], $this->options);
$this->post = $this->post->merge($config);
if ($method === 'verifyipn') {
$this->post->forget('METHOD');
}
}
/**
* Parse PayPal NVP Response.
*
* @param string $method
* @param array|StreamInterface $response
*
* @return array
*/
private function retrieveData($method, $response)
{
if ($method === 'verifyipn') {
return $response;
}
parse_str($response, $output);
return $output;
}
}
Сообщение об ошибке
ErrorException Пытается получить доступ к смещению массива по значению типа null
Комментарии:
1. Где
$this->config
определено?2. Он определен в PaypalRequest.php позвольте мне обновить код с помощью этого файла
3. @jrswgtr Я обновил код. но вот как выглядит setConfig. частная функция setConfig(array $config = []) { // Установить учетные данные Api, если (function_exists(‘config’)) { $this->setApiCredentials(config(‘paypal’)); } elseif (!empty($config)) { $this->setApiCredentials($config); } $this->setRequestData(); }
Ответ №1:
Попробуйте выполнить эти команды
composer update
php artisan cache:clear
php artisan config:clear
php artisan view:clear