Enlaces de SMS para abrir páginas específicas en Mini Programas de WeChat con parámetros

La siguiente guía detalla el proceso de implementación basado en recursos existentes, adaptándolos para cumplir con los requisitos específicos del proyecto.

Configuración del Desarrollo en la Nube de WeChat

1. Activación de los servicios de Desarrollo en la Nube

a) Habilitar el servicio de Desarrollo en la Nube

En las herramientas de desarrollador de WeChat, accede a la sección de Desarrollo en la Nube.

Crea un nuevo entorno de desarrollo en la nube, especificando un nombre y el método de pago (se recomienda el pago por uso, que incluye una cuota gratuita tanto para desarrollo personal como para proyectos empresariales).

Una vez activado, podrás ver el ID de entorno en el panel de resumen. Anota este ID, ya que será necesario para la configuración de las páginas H5.

b) Configurar permisos de Desarrollo en la Nube

En la configuración, ajusta los permisos de acceso a recursos en la nube. Asegúrate de habilitar el acceso para usuarios no autenticados marcando la opción correspondiente.

c) Activar sitio estático

En el menú "Más", selecciona "Sitio estático" y activa esta funcionalidad.

Escanea el código QR para confirmar. La inicialización puede tomar algún tiempo, pero no es necesario esperar a que se complete para continuar con los siguientes pasos.

2. Configuración del entorno de Desarrollo en la Nube

En la raíz del proyecto, haz clic derecho en la carpeta "cloudfunctions" y selecciona "Establecer entorno actual", eligiendo el entorno de nube que creaste anteriormente.

Implementación de Funciones de la Nube

1. Configuración del proyecto

En el archivo "project.config.json" en la raíz del proyecto, agrega el siguiente campo:

"cloudfunctionRoot": "cloudfunctions/",

En el archivo "app.json" en la raíz del proyecto, agrega:

"cloud": true,

2. Creación de la Función de la Nube

a) Crear carpeta para funciones de la nube

En la raíz del proyecto, crea una carpeta llamada "cloudfunctions". Debido a la configuración anterior, esta carpeta mostrará un icono de nube.

b) Crear nueva función de la nube

La función de la nube para el manejo de enlaces de SMS debe tener el nombre "public" (este nombre es obligatorio según las especificaciones de WeChat).

Para crearla, haz clic derecho en la carpeta "cloudfunctions" y selecciona "Nueva función Node.js de la nube". Ingresa "public" como nombre de la función.

Alternativamente, puedes descargar la función pública desde la documentación oficial y copiarla en la carpeta "cloudfunctions" de tu proyecto.

c) Modificar el archivo index.js

Edita el archivo "index.js" dentro de la carpeta "public" y ajusta la función "getUrlscheme" para que coincida con las rutas de las páginas de tu Mini Programa:

// Archivo de entrada de la función de la nube
const cloud = require('wx-server-sdk')

cloud.init()

// Función principal de la nube
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()
  switch (event.action) {
    case 'getEnlaceEspecial': {
      return getEnlaceEspecial(event.ruta, event.parametros)
    }
  }
  return 'acción no encontrada'
}

async function getEnlaceEspecial(ruta, parametros) {
  return cloud.openapi.urlscheme.generate({
    jumpWxa: {
      path: ruta || '/pages/inicio', // Reemplaza con tu ruta
      query: parametros || '',
    },
    // Configura si el enlace expira
    esExpirable: false,
    // Duración de validez (en segundos)
    tiempoExpiracion: parseInt(Date.now() / 1000 + 60),
  })
}

3. Instalación de dependencias

Coloca el cursor sobre la carpeta "public", haz clic derecho y selecciona "Abrir en terminal integrado". Ejecuta el siguiente comando:

npm install

4. Implementación de la función de la nube

Haz clic derecho en la carpeta "public" y selecciona "Subir e implementar: Instalar dependencias en la nube (no subir node_modules)".

Después de la implementación, ve al panel de control del Desarrollo en la Nube > Funciones de la nube para verificar que tu función se ha implementado correctamente. La implementación puede tardar unos segundos.

5. Modificación de permisos de la función de la nube

En el panel de control del Desarrollo en la Nube, ve a "Permisos de la nube" y haz clic en "Modificar" en las reglas de seguridad personalizadas.

Permite el acceso de todos los usuarios para que cualquiera pueda invocar el Mini Programa desde H5 sin autenticación.

Opcionalmente, puedes usar una plantilla avanzada de reglas de seguridad (solo se permite el acceso no autenticado a la función "public"):

{
  // * es un comodín que aplica a todas las funciones
  "*": {
    // invoke controla los permisos de llamada
    // auth contiene la información de autenticación, en modo no autenticado auth == null
    "invoke": "auth != null"
  },
  // Nombre de la función, esta regla tiene prioridad sobre el comodín
  "public": {
    // Permite llamadas de todas las fuentes, incluyendo usuarios no autenticados
    "invoke": true
  }
}

Implementación de la página H5

1. Creación del archivo HTML

Implementa el archivo HTML que manejará la redirección al Mini Programa. A continuación se muestra un ejemplo completo que permite la navegación a diferentes páginas según parámetros:


<html>

  <head>
    <title>Abrir Mini Programa</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
    <script>
      window.onerror = e => {
        console.error(e);
        alert('Ocurrió un error: ' + e);
      }
    </script>
    <script>
      function obtenerParametroConsulta(clave) {
        const reg = new RegExp('(^|&)' + clave + '=([^&]*)(&|$)', 'i');
        const r = window.location.search.substr(1).match(reg);
        if (r != null) {
          return decodeURI(r[2]);
        }
        return null;
      }
      
      // Configura ID de entorno y AppID vinculado
      var appIdRecurso = ''; // Reemplaza con tu AppID
      var idEntorno = ''; // Reemplaza con tu ID de entorno
      var idOriginal = ''; // Reemplaza con tu ID original
      
      // Determina la ruta según el parámetro de tipo
      var tipoLanzamiento = obtenerParametroConsulta('tipo');
      var rutaPagina = '';
      var idCatalogo = obtenerParametroConsulta('id');
      var claveConsulta = 'clienteIdNotificacion=' + idCatalogo;
      
      if (tipoLanzamiento == '0') {
        rutaPagina = '/paginas/inicio';
      } else {
        rutaPagina = '/paginas/detalle';
      }
    </script>

    // Estilos de WeUI
    <link rel="stylesheet" href="https://res.wx.qq.com/open/libs/weui/2.4.1/weui.min.css" />
    <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
    <script src="https://res.wx.qq.com/open/js/cloudbase/1.1.0/cloud.js"></script>

    <style>
      .oculto {
        display: none
      }

      .completo {
        position: absolute;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0
      }

      .contenedor-web-publico {
        display: flex;
        flex-direction: column;
        align-items: center
      }

      .contenedor-web-publico p {
        position: absolute;
        top: 25%
      }

      .contenedor-web-publico a {
        position: absolute;
        bottom: 40%
      }

      .contenedor-wechat {
        display: flex;
        flex-direction: column;
        align-items: center
      }

      .contenedor-wechat div {
        position: absolute;
        top: 20%
      }

      .contenedor-wechat wx-open-launch-weapp {
        position: absolute;
        bottom: 40%;
        left: 0;
        right: 0;
        display: flex;
        flex-direction: column;
        align-items: center
      }

      .contenedor-web-escritorio {
        display: flex;
        flex-direction: column;
        align-items: center
      }

      .contenedor-web-escritorio p {
        position: absolute;
        top: 40%
      }
    </style>
  </head>

  <body>
    <div class="pagina completa">
      <div id="contenedor-web-publico" class="oculto">
        <p>
          <img style="width: 60px;height:60px;border-radius: 50%;display: block;margin: 10px auto;" src='https://ejemplo.com/logo.svg'></img>
          <span style="color:#17908E;text-align:center;margin:10px auto;">Nombre del Mini Programa</span>
        </p>
        <a id="boton-salto-web-publico" href="javascript:" class="weui-btn weui-btn_primary weui-btn_loading" onclick="abrirMiniPrograma()">
          <span id="cargando-boton-salto" class="weui-primary-loading weui-primary-loading_transparent"><i
              class="weui-primary-loading__dot"></i></span>Hacer clic para abrir el Mini Programa</a>
      </div>
      <div id="contenedor-wechat" class="oculto">
        <div style="width: 100%;">
          <img style="width: 60px;height:60px;border-radius: 50%;display: block;margin: 0 auto;" src='https://ejemplo.com/logo.svg'></img>
          <p style="color:#17908E;text-align:center;margin:auto;">Nombre del Mini Programa</p>
        </div>
        <script>
          document.write('<wx-open-launch-weapp id="boton-lanzamiento" username="' + idOriginal + '" path="' +
            rutaPagina + '">');
          document.write(
            ' <template><button style="width: 240px; height: 45px; text-align: center; font-size: 17px; display: block; margin: 0 auto; padding: 8px 24px; border: none; border-radius: 4px; background-color: #07c160; color:#fff;">Abrir Mini Programa de WeChat</button></template>'
          );
          document.write('</wx-open-launch-weapp>');
        </script>
      </div>
      <div id="contenedor-web-escritorio" class="oculto">
        <p class="font-size:26px;">Por favor, abre este enlace en tu dispositivo móvil</p>
      </div>
    </div>
    <script>
      function documentoListo(fn) {
        if (document.readyState === 'complete' || document.readyState === 'interactive') {
          fn();
        } else {
          document.addEventListener('DOMContentLoaded', fn);
        }
      }
      
      documentoListo(async function() {
        var ua = navigator.userAgent.toLowerCase()
        var esWXWork = ua.match(/wxwork/i) == 'wxwork';
        var esWeixin = !esWXWork && ua.match(/MicroMessenger/i) == 'micromessenger';
        var esMovil = esEscritorio = false;
        if (navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|IEMobile)/i)) {
          esMovil = true
        } else {
          esEscritorio = true
        }
        var esAndroid = ua.indexOf('android') > -1 || ua.indexOf('Adr') > -1;
        var esOS = ua.indexOf('iPhone') > -1 || ua.indexOf('iPad') > -1 || ua.indexOf('Mac') > -1;
        
        if (esWeixin) {
          var contenedorEl = document.getElementById('contenedor-wechat');
          contenedorEl.classList.remove('oculto');
          contenedorEl.classList.add('completo', 'contenedor-wechat');

          var botonLanzamiento = document.getElementById('boton-lanzamiento');
          botonLanzamiento.addEventListener('ready', function(e) {
            console.log('Etiqueta de apertura lista');
          });
          botonLanzamiento.addEventListener('launch', function(e) {
            console.log('Etiqueta de apertura exitosa');
          });
          botonLanzamiento.addEventListener('error', function(e) {
            console.log('Etiqueta de apertura fallida', e.detail);
          });
          
          wx.config({
            debug: false,
            appId: appIdRecurso, // Reemplaza con tu AppID
            timestamp: 0, // Requerido, cualquier número
            nonceStr: 'nonceStr', // Requerido, cualquier cadena no vacía
            signature: 'signature', // Requerido, cualquier cadena no vacía
            jsApiList: ['chooseImage'], // Requerido, cualquier API
            openTagList: ['wx-open-launch-weapp'], // Etiqueta para abrir Mini Programa
          })

        } else if (esEscritorio) {
          // En PC muestra un mensaje para abrir en móvil
          var contenedorEl = document.getElementById('contenedor-web-escritorio')
          contenedorEl.classList.remove('oculto')
          contenedorEl.classList.add('completo', 'contenedor-web-escritorio')

        } else {
          // Invocación sin autenticación usando Tencent Cloud
          var contenedorEl = document.getElementById('contenedor-web-publico')
          contenedorEl.classList.remove('oculto')
          contenedorEl.classList.add('completo', 'contenedor-web-publico')

          var nube = new cloud.Cloud({
            sinIdentidad: true,
            appIdRecurso: appIdRecurso, // AppID del Mini Programa principal
            entornoRecurso: idEntorno, // ID de entorno del recurso
          })
          await nube.init();

          window.nube = nube;
          var botonEl = document.getElementById('boton-salto-web-publico')
          var cargandoBotonEl = document.getElementById('cargando-boton-salto')
          try {
            await abrirMiniPrograma(() => {
              botonEl.classList.remove('weui-btn_loading');
              cargandoBotonEl.classList.add('oculto');
            })
          } catch (e) {
            console.log('error', e)
            botonEl.classList.remove('weui-btn_loading')
            cargandoBotonEl.classList.add('oculto');
            throw e
          }
        }
      })

      async function abrirMiniPrograma(antesDeSaltar) {
        var nube = window.nube
        const resultado = await nube.callFunction({
          nombre: 'public', // Función de la nube en el entorno principal
          datos: {
            action: 'getEnlaceEspecial',
            appid: appIdRecurso,
            path: rutaPagina,
            query: claveConsulta || '',
          },
        })
        
        if (antesDeSaltar) {
          antesDeSaltar();
        }
        
        location.href = resultado.result.enlace;
      }
    </script>
  </body>

</html>

2. Carga de la página H5 al entorno de Desarrollo en la Nube

En el panel de control del Desarrollo en la Nube, ve a "Más" > "Sitio estático" > "Gestión de archivos" y carga el archivo HTML modificado.

3. Pruebas y configuración de dominios

En la ventana del sitio estático, selecciona "Gestión de archivos" y haz clic en "Detalles" para obtener la URL de acceso. Copia esta URL en el navegador de tu móvil para verificar que el Mini Programa se abre correctamente.

Para la implementación final, se recomienda configurar un dominio personalizado según las especificaciones de WeChat.

Consideraciones adicionales

Si necesitas cambiar la cuenta de Tencent Cloud asociada al entorno de Desarrollo en la Nube, sigue los pasos oficiales de desvinculación y vinculación. Este proceso solo afecta las funcionalidades del Desarrollo en la Nube del Mini Programa, sin impactar otras partes del sistema.

Para más información sobre problemas de cuenta, consulta la documentación oficial de Desarrollo en la Nube de Tencent Cloud.

Etiquetas: Mini Programas WeChat Desarrollo en la Nube Funciones de la Nube SMS H5

Publicado el 7-2 21:02