How can I give permissions to automations VELO code?

Product:
Wix Studio Editor and Wix Automations

What are you trying to achieve:
I’m trying to update a contact field every time someone buys a subscription trough the wix pricing plans on my website. I basically want to get the "plan_valid_until": "DATE" from the subscription payload and put it in a custom field called validuntil: DATE on the contact that bought that subscription.

What have you already tried:
I tried doing an automation “Plan ordered -> Run Velo code” where it got the payload and then updated the contact, however using contacts.updateContact from wix-crm.v2 gave me a FORBIDDEN error then I tried using elevate as elevate(contacts.updateContact) but it only worked on my account and not on new unprivileged(?) accounts

Additional information:
Basically I have another page for internal use where I check the contact’s validuntil: DATE value to check if that contact is still subscribed or not.

Question:
How do I get the DATE value from “plan_valid_until” of the subscription and put it trough an automation on the contact’s custom validuntil field?
Any other similar path to achieve this instantaneously is also welcomed

PS: Writing this I realized there must be a way to retrieve that information from “My Subscriptions” no?

My code on wix automations (Plan ordered → Run Velo code):

// Import elevate from wix-auth to run functions with elevated permissions
import { elevate } from 'wix-auth';
// Import contacts from the newer wix-crm.v2 module
import { contacts } from 'wix-crm.v2';

/**
 * Autocomplete function declaration, do not delete
 * @param {import('./__schema__.js').Payload} options
 */
export const invoke = async ({ payload }) => {
  // Log the start of the automation and the full payload received
  console.log('Automation started: invoke function called.');
  console.log('Received payload:', JSON.stringify(payload, null, 2)); // Stringify for better readability in logs

  const contactId = payload.contact_id;
  const validUntilDate = payload.plan_valid_until;

  // Log the extracted contactId and validUntilDate
  console.log(`Extracted contactId: ${contactId}`);
  console.log(`Extracted validUntilDate: ${validUntilDate}`);

  if (!contactId) {
    console.error('Error: contact_id is missing from the payload.');
    return {}; // Exit if critical data is missing
  }

  try {
    // Fetch the contact to get its revision
    console.log(`Attempting to fetch contact with ID: ${contactId}`);
    const contact = await contacts.getContact(contactId);
    console.log('Contact fetched successfully. Contact object:', JSON.stringify(contact, null, 2));

    // CORRECTED: Access contact.info.extendedFields directly as it's a flat object
    // Ensure it's an object even if undefined
    const existingExtendedFields = contact.info.extendedFields || {};

    // Preserve existing extendedFields and add/update custom.validuntil
    // IMPORTANT: Using 'validuntil' (lowercase u) to match the existing field key in your data
    const extendedFieldsForUpdate = {
      ...existingExtendedFields, // Spread existing fields directly
      "custom.validuntil": validUntilDate // Add or update the specific field with correct casing
    };

    // Log the extendedFields object before the update
    console.log('Extended fields to be updated:', JSON.stringify(extendedFieldsForUpdate, null, 2));
    console.log(`Contact revision for update: ${contact.revision}`);

    // Elevate the contacts.updateContact function to bypass permission issues
    const elevatedUpdateContact = elevate(contacts.updateContact);

    // Update the contact with the revised extended fields using the elevated function
    await elevatedUpdateContact(
      contactId,                                 // First argument: contactId (string)
      { extendedFields: extendedFieldsForUpdate }, // Second argument: info object (containing extendedFields)
      contact.revision                           // Third argument: revision (number)
    );

    console.log(`SUCCESS: Contact ${contactId} updated successfully with validUntil: ${validUntilDate}`);
  } catch (error) {
    // Log the full error object for detailed debugging
    console.error('ERROR: Failed to update contact.', error);
    // You might want to log specific error properties if available, e.g., error.message, error.code
  }

  console.log('Automation finished: invoke function completed.');
  return {};
};

1 Like

Hi, @user1985 !!

Hmm :thinking:, what would happen if I tried using elevate() for this part as well? :upside_down_face:

const contact = await contacts.getContact(contactId);