0

I am trying to set up a subscription-based site in Drupal 8/Commerce 2.

I'm using Commerce Stripe to process payments. I want to remove a role from a user ("needs to add new card" role) when the user adds a new payment method (credit card via Stripe) on the payment method page (user/UID/payment-methods).

I assume I need to write an event subscriber, but I don't know which event to use for adding a payment method.

I tried to read through the code in commerce/modules/payment/src/EventSubscriber, but I couldn't find the event I need to hook into to remove the role.

Background

When a user's credit card has expired, they need to add a new card (add a new payment method). In this case, I have flagged the users with a role, Add new card role.

Then I show a block to users with the Add new card role that says "Please update your card info." with a link to add a card.

However, when the user adds a new card, they still see the block asking them to add a new card, which is confusing. So I want to immediately remove the Add new card role (to hide the block) as soon as the user adds a new card.

1

commerce doesn't offer the (content-)entity create event. You could use a hook ..

Or setup events for entity creation, see Does Drupal 8 entities have any events I can listen to?

1
  • Thanks, this is what I needed to know! Note that in this case, it turns out that Commerce requires using hook_ENTITY_TYPE_insert instead of create; see my answer for details. Sep 30 '20 at 7:12
0

Based on the hint from rémy, here's the actual code I used.

Note that for commerce payment methods, you have to use hook_entity_insert() specifically instead of hook_entity_create() because hook_entity_create() gets called when you go to the payment method add page-- even if you immediately go back without entering any information.

/**
 * Remove the 'credit_card_update_role' upon adding a credit card.
 *
 * {@inheritDoc}
 */
function MYMODULE_commerce_payment_method_insert(\Drupal\Core\Entity\EntityInterface $entity) {
  $uid = \Drupal::currentUser()->id();
  $account = User::load($uid);
  if ($account->hasRole('credit_card_update')) {
    $account->removeRole('credit_card_update');
    $account->save();
  }
}

I added a redirect because by default users are redirected to the payment method edit page, which will result in an access denied error. To avoid this, I send them to the user profile page with a confirmation that the card was added.

/**
 * Redirect users to their profile pages after adding a new card.
 *
 * {@inheritDoc}
 */
function MYMODULE_form_commerce_payment_method_add_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  // Redirect users to their profile pages.
  $form['actions']['submit']['#submit'][] = '_MYMODULE_commerce_payment_method_insert_form_submit';
}

/**
 * Redirect users to their profile pages when submitting the edit form.
 */
function _MYMODULE_commerce_payment_method_insert_form_submit($form, &$form_state) {
  \Drupal::messenger()->addStatus('Thank you for updating your credit card!');
  $form_state->setRedirect('entity.user.canonical', ['user' => \Drupal::currentUser()->id()]);
}
1
  • Thx for sharing :D
    – rémy
    Oct 2 '20 at 22:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.