View source
<?php
namespace Drupal\commerce_authnet\Plugin\Commerce\PaymentGateway;
use CommerceGuys\AuthNet\DataTypes\CreditCard as AuthnetCreditCard;
use CommerceGuys\AuthNet\UpdateCustomerPaymentProfileRequest;
use Drupal\commerce_order\Entity\OrderInterface;
use Drupal\commerce_payment\CreditCard;
use Drupal\commerce_payment\Entity\PaymentInterface;
use Drupal\commerce_payment\Entity\PaymentMethodInterface;
use Drupal\commerce_payment\Exception\DeclineException;
use Drupal\commerce_payment\Exception\HardDeclineException;
use Drupal\commerce_payment\Exception\InvalidResponseException;
use Drupal\commerce_payment\Exception\PaymentGatewayException;
use Drupal\commerce_price\Price;
use CommerceGuys\AuthNet\CreateCustomerPaymentProfileRequest;
use CommerceGuys\AuthNet\CreateCustomerProfileRequest;
use CommerceGuys\AuthNet\CreateTransactionRequest;
use CommerceGuys\AuthNet\UpdateHeldTransactionRequest;
use CommerceGuys\AuthNet\DataTypes\BillTo;
use CommerceGuys\AuthNet\DataTypes\CardholderAuthentication;
use CommerceGuys\AuthNet\DataTypes\CreditCard as CreditCardDataType;
use CommerceGuys\AuthNet\DataTypes\LineItem;
use CommerceGuys\AuthNet\DataTypes\Order as OrderDataType;
use CommerceGuys\AuthNet\DataTypes\OpaqueData;
use CommerceGuys\AuthNet\DataTypes\PaymentProfile;
use CommerceGuys\AuthNet\DataTypes\Profile;
use CommerceGuys\AuthNet\DataTypes\TransactionRequest;
use CommerceGuys\AuthNet\DataTypes\ShipTo;
use Drupal\Core\Form\FormStateInterface;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
class AcceptJs extends OnsiteBase implements AcceptJsInterface {
public function defaultConfiguration() {
return [
'cca_status' => FALSE,
'cca_api_id' => '',
'cca_org_unit_id' => '',
'cca_api_key' => '',
] + parent::defaultConfiguration();
}
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form = parent::buildConfigurationForm($form, $form_state);
$form['cca_status'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Enable Cardinal Cruise Authentication'),
'#default_value' => $this->configuration['cca_status'],
];
$form['cca'] = [
'#type' => 'fieldset',
'#title' => $this
->t('Cardinal Cruise Authentication'),
'#states' => [
'visible' => [
'input[name="configuration[authorizenet_acceptjs][cca_status]"]' => [
'checked' => TRUE,
],
],
],
'#description' => $this
->t('In test mode the credentials provided here are not used (but the fields are still required).'),
];
$form['cca']['cca_api_id'] = [
'#type' => 'textfield',
'#title' => $this
->t('API Identifier'),
'#default_value' => $this->configuration['cca_api_id'],
'#states' => [
'required' => [
'input[name="configuration[authorizenet_acceptjs][cca_status]"]' => [
'checked' => TRUE,
],
],
],
];
$form['cca']['cca_org_unit_id'] = [
'#type' => 'textfield',
'#title' => $this
->t('Org Unit ID'),
'#default_value' => $this->configuration['cca_org_unit_id'],
'#states' => [
'required' => [
'input[name="configuration[authorizenet_acceptjs][cca_status]"]' => [
'checked' => TRUE,
],
],
],
];
$form['cca']['cca_api_key'] = [
'#type' => 'textfield',
'#title' => $this
->t('API key'),
'#default_value' => $this->configuration['cca_api_key'],
'#states' => [
'required' => [
'input[name="configuration[authorizenet_acceptjs][cca_status]"]' => [
'checked' => TRUE,
],
],
],
];
return $form;
}
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
parent::submitConfigurationForm($form, $form_state);
if (!$form_state
->getErrors()) {
$values = $form_state
->getValue($form['#parents']);
$this->configuration['cca_status'] = $values['cca_status'];
$this->configuration['cca_api_id'] = $values['cca']['cca_api_id'];
$this->configuration['cca_org_unit_id'] = $values['cca']['cca_org_unit_id'];
$this->configuration['cca_api_key'] = $values['cca']['cca_api_key'];
}
}
public function getCcaApiId() {
if ($this->configuration['cca_status']) {
if ($this->configuration['mode'] == 'test') {
return '582e0a2033fadd1260f990f6';
}
else {
return $this->configuration['cca_api_id'];
}
}
}
public function getCcaOrgUnitId() {
if ($this->configuration['cca_status']) {
if ($this->configuration['mode'] == 'test') {
return '582be9deda52932a946c45c4';
}
else {
return $this->configuration['cca_org_unit_id'];
}
}
}
public function getCcaApiKey() {
if ($this->configuration['cca_status']) {
if ($this->configuration['mode'] == 'test') {
return '754be3dc-10b7-471f-af31-f20ce12b9ec1';
}
else {
return $this->configuration['cca_api_key'];
}
}
}
public function getJsLibrary() {
if ($this->configuration['cca_status']) {
if ($this
->getMode() === 'test') {
return 'commerce_authnet/cardinalcruise-dev';
}
return 'commerce_authnet/cardinalcruise';
}
return 'commerce_authnet/form-accept';
}
public function createPayment(PaymentInterface $payment, $capture = TRUE) {
$this
->assertPaymentState($payment, [
'new',
]);
$payment_method = $payment
->getPaymentMethod();
$this
->assertPaymentMethod($payment_method);
$order = $payment
->getOrder();
$owner = $payment_method
->getOwner();
$transaction_request = new TransactionRequest([
'transactionType' => $capture ? TransactionRequest::AUTH_CAPTURE : TransactionRequest::AUTH_ONLY,
'amount' => $payment
->getAmount()
->getNumber(),
]);
$tempstore_3ds = $this->privateTempStore
->get('commerce_authnet')
->get($payment_method
->id());
if (!empty($tempstore_3ds)) {
$payment_storage = $this->entityTypeManager
->getStorage('commerce_payment');
$payment_method_has_been_used = $payment_storage
->getQuery()
->condition('payment_method', $payment_method
->id())
->range(0, 1)
->execute();
if (!$payment_method_has_been_used) {
$cardholder_authentication = new CardholderAuthentication();
$cardholder_authentication_empty = TRUE;
if (!empty($tempstore_3ds['eci']) && $tempstore_3ds['eci'] != '07') {
$cardholder_authentication->authenticationIndicator = $tempstore_3ds['eci'];
$cardholder_authentication_empty = FALSE;
}
if (!empty($tempstore_3ds['cavv'])) {
$cardholder_authentication->cardholderAuthenticationValue = urlencode($tempstore_3ds['cavv']);
$cardholder_authentication_empty = FALSE;
}
if (!$cardholder_authentication_empty) {
$transaction_request
->addDataType($cardholder_authentication);
}
}
else {
$this->privateTempStore
->get('commerce_authnet')
->delete($payment_method
->id());
}
}
$customer_profile_id = $this
->getRemoteCustomerId($owner);
if (empty($customer_profile_id)) {
$customer_profile_id = $this
->getPaymentMethodCustomerId($payment_method);
}
$payment_profile_id = $this
->getRemoteProfileId($payment_method);
$profile_to_charge = new Profile([
'customerProfileId' => $customer_profile_id,
]);
$profile_to_charge
->addData('paymentProfile', [
'paymentProfileId' => $payment_profile_id,
]);
$transaction_request
->addData('profile', $profile_to_charge
->toArray());
$profiles = $order
->collectProfiles();
if (isset($profiles['shipping']) && !$profiles['shipping']
->get('address')
->isEmpty()) {
$shipping_address = $profiles['shipping']
->get('address')
->first();
$ship_data = [
'firstName' => $shipping_address
->getGivenName(),
'lastName' => $shipping_address
->getFamilyName(),
'address' => substr($shipping_address
->getAddressLine1() . ' ' . $shipping_address
->getAddressLine2(), 0, 60),
'country' => $shipping_address
->getCountryCode(),
'company' => $shipping_address
->getOrganization(),
'city' => $shipping_address
->getLocality(),
'state' => $shipping_address
->getAdministrativeArea(),
'zip' => $shipping_address
->getPostalCode(),
];
$transaction_request
->addDataType(new ShipTo(array_filter($ship_data)));
}
$transaction_request
->addOrder(new OrderDataType([
'invoiceNumber' => $order
->getOrderNumber() ?: $order
->id(),
]));
$transaction_request
->addData('customerIP', $order
->getIpAddress());
$line_items = $this
->getLineItems($order);
foreach ($line_items as $line_item) {
$transaction_request
->addLineItem($line_item);
}
$transaction_request
->addData('tax', $this
->getTax($order)
->toArray());
$transaction_request
->addData('shipping', $this
->getShipping($order)
->toArray());
$request = new CreateTransactionRequest($this->authnetConfiguration, $this->httpClient);
$request
->setTransactionRequest($transaction_request);
$response = $request
->execute();
if ($response
->getResultCode() != 'Ok') {
$this
->logResponse($response);
$message = $response
->getMessages()[0];
switch ($message
->getCode()) {
case 'E00040':
$payment_method
->delete();
throw new PaymentGatewayException('The provided payment method is no longer valid');
case 'E00042':
$payment_method
->delete();
throw new PaymentGatewayException('You cannot add more than 10 payment methods.');
default:
throw new PaymentGatewayException($message
->getText());
}
}
if (!empty($response
->getErrors())) {
$message = $response
->getErrors()[0];
throw new HardDeclineException($message
->getText());
}
$code = $response
->getMessageCode();
$expires = 0;
$next_state = 'authorization';
if ($code == 1 && $capture) {
$next_state = 'completed';
}
elseif ($code == 252) {
$next_state = 'unauthorized_review';
$expires = strtotime('+5 days');
}
elseif ($code == 253) {
$next_state = 'authorization_review';
$expires = strtotime('+5 days');
}
$payment
->setExpiresTime($expires);
$payment
->setState($next_state);
$payment
->setRemoteId($response->transactionResponse->transId);
$payment
->setAvsResponseCode($response->transactionResponse->avsResultCode);
$payment
->save();
}
public function approvePayment(PaymentInterface $payment) {
$this
->assertPaymentState($payment, [
'unauthorized_review',
'authorization_review',
]);
if ($payment
->isExpired()) {
throw new HardDeclineException('This payment has expired.');
}
$request = new UpdateHeldTransactionRequest($this->authnetConfiguration, $this->httpClient);
$request
->setAction(UpdateHeldTransactionRequest::APPROVE);
$request
->setRefTransId($payment
->getRemoteId());
$response = $request
->execute();
if ($response
->getResultCode() != 'Ok') {
$this
->logResponse($response);
$message = $response
->getMessages()[0];
throw new PaymentGatewayException($message
->getText());
}
$new_state = $payment
->getState()
->getId() == 'unauthorized_review' ? 'authorization' : 'completed';
$payment
->setState($new_state);
$payment
->save();
}
public function declinePayment(PaymentInterface $payment) {
$this
->assertPaymentState($payment, [
'unauthorized_review',
'authorization_review',
]);
if ($payment
->isExpired()) {
throw new HardDeclineException('This payment has expired.');
}
$request = new UpdateHeldTransactionRequest($this->authnetConfiguration, $this->httpClient);
$request
->setAction(UpdateHeldTransactionRequest::DECLINE);
$request
->setRefTransId($payment
->getRemoteId());
$response = $request
->execute();
if ($response
->getResultCode() != 'Ok') {
$this
->logResponse($response);
$message = $response
->getMessages()[0];
throw new PaymentGatewayException($message
->getText());
}
$new_state = $payment
->getState()
->getId() == 'unauthorized_review' ? 'unauthorized_declined' : 'authorization_declined';
$payment
->setState($new_state);
$payment
->save();
}
public function refundPayment(PaymentInterface $payment, Price $amount = NULL) {
$payment_method = $payment
->getPaymentMethod();
$this
->assertPaymentState($payment, [
'completed',
'partially_refunded',
]);
$amount = $amount ?: $payment
->getAmount();
$this
->assertRefundAmount($payment, $amount);
$request = new CreateTransactionRequest($this->authnetConfiguration, $this->httpClient);
$transaction_request = new TransactionRequest([
'transactionType' => TransactionRequest::REFUND,
'amount' => $amount
->getNumber(),
'refTransId' => $payment
->getRemoteId(),
]);
if ($billing_profile = $payment_method
->getBillingProfile()) {
$address = $billing_profile
->get('address')
->first();
$bill_to = array_filter([
'firstName' => $address
->getGivenName(),
'lastName' => $address
->getFamilyName(),
'company' => $address
->getOrganization(),
'address' => substr($address
->getAddressLine1() . ' ' . $address
->getAddressLine2(), 0, 60),
'country' => $address
->getCountryCode(),
'city' => $address
->getLocality(),
'state' => $address
->getAdministrativeArea(),
'zip' => $address
->getPostalCode(),
]);
$transaction_request
->addDataType(new BillTo($bill_to));
}
$order = $payment
->getOrder();
$transaction_request
->addOrder(new OrderDataType([
'invoiceNumber' => $order
->getOrderNumber() ?: $order
->id(),
]));
$transaction_request
->addPayment(new CreditCardDataType([
'cardNumber' => $payment_method->card_number->value,
'expirationDate' => str_pad($payment_method->card_exp_month->value, 2, '0', STR_PAD_LEFT) . str_pad($payment_method->card_exp_year->value, 2, '0', STR_PAD_LEFT),
]));
$request
->setTransactionRequest($transaction_request);
$response = $request
->execute();
if ($response
->getResultCode() != 'Ok') {
$this
->logResponse($response);
$message = $response
->getMessages()[0];
throw new PaymentGatewayException($message
->getText());
}
$old_refunded_amount = $payment
->getRefundedAmount();
$new_refunded_amount = $old_refunded_amount
->add($amount);
if ($new_refunded_amount
->lessThan($payment
->getAmount())) {
$payment
->setState('partially_refunded');
}
else {
$payment
->setState('refunded');
}
$payment
->setRefundedAmount($new_refunded_amount);
$payment
->save();
}
public function createPaymentMethod(PaymentMethodInterface $payment_method, array $payment_details) {
if (!empty($this
->getConfiguration()['cca_status']) && !empty($payment_details['cca_jwt_token'])) {
if (empty($payment_details['cca_jwt_response_token'])) {
throw new PaymentGatewayException('Cannot continue when CCA is enabled but not used.');
}
$token = (new Parser())
->parse($payment_details['cca_jwt_response_token']);
$signer = new Sha256();
if (!$token
->verify($signer, $this
->getCcaApiKey())) {
throw new PaymentGatewayException('Response CCA JWT is not valid.');
}
$claims = $token
->getClaims();
$payload = $claims['Payload'];
if (isset($payload
->getValue()->Payment->ExtendedData->SignatureVerification) && $payload
->getValue()->Payment->ExtendedData->SignatureVerification === 'N') {
throw new PaymentGatewayException('Unsuccessful signature verification.');
}
}
$required_keys = [
'data_descriptor',
'data_value',
];
foreach ($required_keys as $required_key) {
if (empty($payment_details[$required_key])) {
throw new \InvalidArgumentException(sprintf('$payment_details must contain the %s key.', $required_key));
}
}
$remote_payment_method = $this
->doCreatePaymentMethod($payment_method, $payment_details);
$payment_method->card_type = $this
->mapCreditCardType($remote_payment_method['card_type']);
$payment_method->card_number = $remote_payment_method['last4'];
$payment_method->card_exp_month = $remote_payment_method['expiration_month'];
$payment_method->card_exp_year = $remote_payment_method['expiration_year'];
$payment_method
->setRemoteId($remote_payment_method['remote_id']);
$expires = CreditCard::calculateExpirationTimestamp($remote_payment_method['expiration_month'], $remote_payment_method['expiration_year']);
$payment_method
->setExpiresTime($expires);
$payment_method
->save();
if (!empty($this
->getConfiguration()['cca_status']) && !empty($payment_details['cca_jwt_token'])) {
$value = [];
if (isset($payload
->getValue()->Payment->ExtendedData->CAVV)) {
$value['cavv'] = $payload
->getValue()->Payment->ExtendedData->CAVV;
$this->privateTempStore
->get('commerce_authnet')
->set($payment_method
->id(), $value);
}
if (isset($payload
->getValue()->Payment->ExtendedData->ECIFlag)) {
$value['eci'] = $payload
->getValue()->Payment->ExtendedData->ECIFlag;
$this->privateTempStore
->get('commerce_authnet')
->set($payment_method
->id(), $value);
}
}
}
public function updatePaymentMethod(PaymentMethodInterface $payment_method) {
$request = new UpdateCustomerPaymentProfileRequest($this->authnetConfiguration, $this->httpClient);
$customer_profile_id = $this
->getRemoteCustomerId($payment_method
->getOwner());
if (empty($customer_profile_id)) {
$customer_profile_id = $this
->getPaymentMethodCustomerId($payment_method);
}
$request
->setCustomerProfileId($customer_profile_id);
$payment_profile = new PaymentProfile([
'customerType' => 'individual',
]);
$payment_profile
->addCustomerPaymentProfileId($this
->getRemoteProfileId($payment_method));
if ($billing_profile = $payment_method
->getBillingProfile()) {
$address = $billing_profile
->get('address')
->first();
$bill_to = array_filter([
'firstName' => $address
->getGivenName(),
'lastName' => $address
->getFamilyName(),
'company' => $address
->getOrganization(),
'address' => substr($address
->getAddressLine1() . ' ' . $address
->getAddressLine2(), 0, 60),
'country' => $address
->getCountryCode(),
'city' => $address
->getLocality(),
'state' => $address
->getAdministrativeArea(),
'zip' => $address
->getPostalCode(),
]);
$payment_profile
->addBillTo(new BillTo($bill_to));
}
$request
->setPaymentProfile($payment_profile);
$payment_profile
->addPayment(new AuthnetCreditCard([
'cardNumber' => 'XXXX' . $payment_method
->get('card_number')->value,
'expirationDate' => sprintf('%s-%s', $payment_method
->get('card_exp_month')->value, $payment_method
->get('card_exp_year')->value),
]));
$response = $request
->execute();
if ($response
->getResultCode() != 'Ok') {
$this
->logResponse($response);
$error = $response
->getMessages()[0];
throw new DeclineException('Unable to update the payment method.');
}
}
protected function doCreatePaymentMethod(PaymentMethodInterface $payment_method, array $payment_details) {
$owner = $payment_method
->getOwner();
$customer_profile_id = NULL;
$customer_data = [];
if ($owner && !$owner
->isAnonymous()) {
$customer_profile_id = $this
->getRemoteCustomerId($owner);
if (empty($customer_profile_id)) {
$customer_profile_id = $this
->getPaymentMethodCustomerId($payment_method);
}
$customer_data['email'] = $owner
->getEmail();
}
if ($customer_profile_id) {
$payment_profile = $this
->buildCustomerPaymentProfile($payment_method, $payment_details, $customer_profile_id);
$request = new CreateCustomerPaymentProfileRequest($this->authnetConfiguration, $this->httpClient);
$request
->setCustomerProfileId($customer_profile_id);
$request
->setPaymentProfile($payment_profile);
$response = $request
->execute();
if ($response
->getResultCode() != 'Ok') {
$this
->logResponse($response);
$error = $response
->getMessages()[0];
switch ($error
->getCode()) {
case 'E00039':
if (!isset($response->customerPaymentProfileId)) {
throw new InvalidResponseException('Duplicate payment profile ID, however could not get existing ID.');
}
break;
case 'E00040':
$this
->setRemoteCustomerId($owner, NULL);
$owner
->save();
throw new InvalidResponseException('The customer record could not be found');
default:
throw new InvalidResponseException($error
->getText());
}
}
$payment_profile_id = $response->customerPaymentProfileId;
$validation_direct_response = explode(',', $response->validationDirectResponse);
}
else {
$request = new CreateCustomerProfileRequest($this->authnetConfiguration, $this->httpClient);
if ($owner
->isAuthenticated()) {
$profile = new Profile([
'merchantCustomerId' => $owner
->id(),
'email' => $owner
->getEmail(),
]);
}
else {
$profile = new Profile([
'merchantCustomerId' => $owner
->id() . '_' . $this->time
->getRequestTime(),
'email' => $payment_details['customer_email'],
]);
}
$request
->setProfile($profile);
$request
->setValidationMode(NULL);
$response = $request
->execute();
if ($response
->getResultCode() == 'Ok') {
$customer_profile_id = $response->customerProfileId;
}
else {
if ($response
->getMessages()[0]
->getCode() == 'E00039') {
$result = array_filter(explode(' ', $response
->getMessages()[0]
->getText()), 'is_numeric');
$customer_profile_id = reset($result);
}
else {
$this
->logResponse($response);
throw new InvalidResponseException("Unable to create customer profile.");
}
}
$payment_profile = $this
->buildCustomerPaymentProfile($payment_method, $payment_details, $customer_profile_id);
$request = new CreateCustomerPaymentProfileRequest($this->authnetConfiguration, $this->httpClient);
$request
->setCustomerProfileId($customer_profile_id);
$request
->setPaymentProfile($payment_profile);
$response = $request
->execute();
if ($response
->getResultCode() != 'Ok') {
if ($response
->getMessages()[0]
->getCode() != 'E00039') {
$this
->logResponse($response);
throw new InvalidResponseException("Unable to create payment profile for existing customer");
}
}
$payment_profile_id = $response->customerPaymentProfileId;
$validation_direct_response = explode(',', $response->validationDirectResponse);
if ($owner
->isAuthenticated()) {
$this
->setRemoteCustomerId($owner, $customer_profile_id);
$owner
->save();
}
}
$card_type_key = 51;
foreach ($validation_direct_response as $key => $value) {
if (!empty($value) && strpos($value, 'XXXX') !== FALSE) {
$card_type_key = $key + 1;
}
}
$remote_id = $owner
->isAuthenticated() ? $payment_profile_id : $customer_profile_id . '|' . $payment_profile_id;
return [
'remote_id' => $remote_id,
'card_type' => $validation_direct_response[$card_type_key],
'last4' => $payment_details['last4'],
'expiration_month' => $payment_details['expiration_month'],
'expiration_year' => $payment_details['expiration_year'],
];
}
protected function buildCustomerPaymentProfile(PaymentMethodInterface $payment_method, array $payment_details, $customer_id = NULL) {
$payment = new OpaqueData([
'dataDescriptor' => $payment_details['data_descriptor'],
'dataValue' => $payment_details['data_value'],
]);
$payment_profile = new PaymentProfile([
'customerType' => 'individual',
]);
if ($billing_profile = $payment_method
->getBillingProfile()) {
$address = $billing_profile
->get('address')
->first();
$bill_to = array_filter([
'firstName' => $address
->getGivenName(),
'lastName' => $address
->getFamilyName(),
'company' => $address
->getOrganization(),
'address' => substr($address
->getAddressLine1() . ' ' . $address
->getAddressLine2(), 0, 60),
'country' => $address
->getCountryCode(),
'city' => $address
->getLocality(),
'state' => $address
->getAdministrativeArea(),
'zip' => $address
->getPostalCode(),
]);
$payment_profile
->addBillTo(new BillTo($bill_to));
}
$payment_profile
->addPayment($payment);
return $payment_profile;
}
protected function mapCreditCardType($card_type) {
$map = [
'American Express' => 'amex',
'Diners Club' => 'dinersclub',
'Discover' => 'discover',
'JCB' => 'jcb',
'MasterCard' => 'mastercard',
'Visa' => 'visa',
'China UnionPay' => 'unionpay',
];
if (!isset($map[$card_type])) {
throw new HardDeclineException(sprintf('Unsupported credit card type "%s".', $card_type));
}
return $map[$card_type];
}
protected function getLineItems(OrderInterface $order) {
$line_items = [];
foreach ($order
->getItems() as $order_item) {
$name = $order_item
->label();
$name = strlen($name) > 31 ? substr($name, 0, 28) . '...' : $name;
$line_items[] = new LineItem([
'itemId' => $order_item
->id(),
'name' => $name,
'quantity' => $order_item
->getQuantity(),
'unitPrice' => $order_item
->getUnitPrice()
->getNumber(),
]);
}
return $line_items;
}
public function buildPaymentOperations(PaymentInterface $payment) {
$payment_state = $payment
->getState()
->getId();
$operations = parent::buildPaymentOperations($payment);
$operations['approve'] = [
'title' => $this
->t('Approve'),
'page_title' => $this
->t('Approve payment'),
'plugin_form' => 'approve-payment',
'access' => in_array($payment_state, [
'unauthorized_review',
'authorization_review',
]),
];
$operations['decline'] = [
'title' => $this
->t('Decline'),
'page_title' => $this
->t('Decline payment'),
'plugin_form' => 'decline-payment',
'access' => in_array($payment_state, [
'unauthorized_review',
'authorization_review',
]),
];
return $operations;
}
}