O PWA do MishiPay aumenta as transações em 10 vezes e economiza 2,5 anos de filas

Saiba como a mudança para o PWA ajudou os negócios da MishiPay.

O MishiPay permite que os compradores digitalizem e paguem suas compras com smartphones, em vez de perdendo tempo na fila do caixa. Com os métodos Scan & Go, os compradores podem usar o próprio smartphone para ler o código de barras dos itens e pagar, da loja. Os estudos revelam que o processo de filas na loja custa ao setor de varejo global cerca de US $200 bilhões por ano.

Nossa tecnologia depende de recursos de hardware do dispositivo, como câmeras e sensores de GPS que permitem os usuários localizarem lojas que usam o MishiPay, lerem códigos de barras de itens na loja física e pagarem usando a forma de pagamento digital que preferirem. As versões iniciais da nossa biblioteca Tecnologia Go eram aplicativos iOS e Android específicos da plataforma, e os primeiros usuários adoraram a tecnologia. Lida para saber como mudar para um PWA aumentou as transações em 10 vezes e economizou 2,5 anos na fila.

    10×

    Mais transações

    2,5 anos

    Fila salva

Desafio

Os usuários acham nossa tecnologia extremamente útil ao esperar em uma fila ou fila de check-out, pois permite a pular a fila e proporcionar uma experiência tranquila na loja. Mas o incômodo de fazer o download O aplicativo Android ou iOS fez com que os usuários não escolhessem nossa tecnologia, apesar do valor. Foi um crescimento para o MishiPay, e precisávamos aumentar a adoção dos usuários com uma barreira menor de entrada.

Solução

Nossos esforços na criação e lançamento do PWA nos ajudaram a eliminar a complicação da instalação e encorajamos novos usuários a testar nossa tecnologia em uma loja física, pular a fila e ter um uma experiência de compra perfeita. Desde o lançamento, vimos um grande pico na adoção dos usuários com nosso PWA em comparação com nossos aplicativos específicos da plataforma.

Comparação lado a lado entre iniciar diretamente o PWA (à esquerda, mais rápido) com a instalação e inicialização do app Android (à direita, mais lenta).
.
Transações por plataforma. SO: 16.397 (3,98%). Android: 13.769 (3,34%). Web: 382184 (92,68%).
A maioria de todas as transações acontece na Web.

Detalhes técnicos

Localização de lojas que aceitam o MishiPay

Para ativar esse recurso, contamos com o getCurrentPosition() com uma solução substituta baseada em IP.

const geoOptions = {
  timeout: 10 * 1000,
  enableHighAccuracy: true,
  maximumAge: 0,
};

window.navigator.geolocation.getCurrentPosition(
  (position) => {
    const cords = position.coords;
    console.log(`Latitude :  ${cords.latitude}`);
    console.log(`Longitude :  ${cords.longitude}`);
  },
  (error) => {
    console.debug(`Error: ${error.code}:${error.message}`);
    /**
     * Invoke the IP based location services
     * to fetch the latitude and longitude of the user.
     */
  },
  geoOptions,
);

Essa abordagem funcionou bem nas versões anteriores do aplicativo, mas foi comprovadamente um grande problema para os usuários do MishiPay pelos seguintes motivos:

  • Imprecisões de localização nas soluções de substituição baseadas em IP.
  • A lista crescente de lojas compatíveis com o MishiPay por região exige que os usuários rolem a lista e identificar a loja correta.
  • Às vezes, os usuários escolhem acidentalmente a loja errada, fazendo com que as compras sejam registradas. de forma incorreta.

Para resolver esses problemas, incorporamos códigos QR exclusivos geolocalizados nas vitrines das lojas para cada loja on-line. Isso abriu caminho para uma experiência de integração mais rápida. Os usuários só precisam ler o QR code geolocalizado impressos em materiais de marketing presentes nas lojas para acessar o recurso Aplicativo da Web Go. Assim, eles não precisam digitar o endereço da Web mishipay.shop para acessar o serviço.

Experiência de verificação na loja usando o PWA.

Como verificar produtos

Um recurso importante do app MishiPay é a leitura de código de barras, que permite que nossos usuários leiam os próprios suas próprias compras e ver o total das compras antes mesmo que elas atingissem o dinheiro se registrar.

Para criar uma experiência de digitalização na Web, identificamos três camadas principais.

Diagrama mostrando as três principais camadas da linha de execução: stream de vídeo, camada de processamento e camada decodificador.

Stream de vídeo

Com a ajuda da método getUserMedia(), pode acessar a câmera traseira do usuário com as restrições listadas abaixo. Como invocar o método aciona automaticamente uma solicitação para os usuários aceitarem ou negarem o acesso à câmera. Assim que tivermos acesso à transmissão de vídeo, podemos retransmiti-lo para um elemento de vídeo, conforme mostrado abaixo:

/**
 * Video Stream Layer
 * https://developer.mozilla.org/docs/Web/API/MediaDevices/getUserMedia
 */
const canvasEle = document.getElementById('canvas');
const videoEle = document.getElementById('videoElement');
const canvasCtx = canvasEle.getContext('2d');
fetchVideoStream();
function fetchVideoStream() {
  let constraints = { video: { facingMode: 'environment' } };
  if (navigator.mediaDevices !== undefined) {
    navigator.mediaDevices
      .getUserMedia(constraints)
      .then((stream) => {
        videoEle.srcObject = stream;
        videoStream = stream;
        videoEle.play();
        // Initiate frame capture - Processing Layer.
      })
      .catch((error) => {
        console.debug(error);
        console.warn(`Failed to access the stream:${error.name}`);
      });
  } else {
    console.warn(`getUserMedia API not supported!!`);
  }
}

Camada de processamento

Para detectar um código de barras em um stream de vídeo, precisamos capturar periodicamente quadros e transferir para a camada decodificador. Para capturar um frame, simplesmente desenhamos os streams de VideoElement para um HTMLCanvasElement usando o drawImage() da API Canvas.

/**
 * Processing Layer - Frame Capture
 * https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Manipulating_video_using_canvas
 */
async function captureFrames() {
  if (videoEle.readyState === videoEle.HAVE_ENOUGH_DATA) {
    const canvasHeight = (canvasEle.height = videoEle.videoHeight);
    const canvasWidth = (canvasEle.width = videoEle.videoWidth);
    canvasCtx.drawImage(videoEle, 0, 0, canvasWidth, canvasHeight);
    // Transfer the `canvasEle` to the decoder for barcode detection.
    const result = await decodeBarcode(canvasEle);
  } else {
    console.log('Video feed not available yet');
  }
}

Para casos de uso avançados, essa camada também realiza algumas tarefas de pré-processamento, como corte, rotação ou conversão para escala de cinza. Essas tarefas podem consumir muita CPU e resultar não responde, já que a leitura do código de barras é uma operação de longa duração. Com a ajuda da OffscreenCanvas, podemos descarregar a tarefa com uso intensivo de CPU a um web worker. Em dispositivos com suporte a aceleração gráfica de hardware, A API WebGL e seus WebGL2RenderingContext pode otimizar os ganhos nas tarefas de pré-processamento com uso intensivo da CPU.

Camada de decodificador

A camada final é a camada decodificadora, responsável por decodificar os códigos de barras dos frames são capturados pela camada de processamento. Graças à API Shape Detection (que é ainda não está disponível em todos os navegadores), o próprio navegador decodifica o código de barras a partir de uma ImageBitmapSource, que pode ser um elemento img, um elemento image SVG, um elemento video, um canvas, um objeto Blob, um objeto ImageData ou um objeto ImageBitmap.

Diagrama mostrando as três principais camadas da linha de execução: stream de vídeo, camada de processamento e API Shape Detection.

/**
 * Barcode Decoder with Shape Detection API
 * https://web.dev/shape-detection/
 */
async function decodeBarcode(canvas) {
  const formats = [
    'aztec',
    'code_128',
    'code_39',
    'code_93',
    'codabar',
    'data_matrix',
    'ean_13',
    'ean_8',
    'itf',
    'pdf417',
    'qr_code',
    'upc_a',
    'upc_e',
  ];
  const barcodeDetector = new window.BarcodeDetector({
    formats,
  });
  try {
    const barcodes = await barcodeDetector.detect(canvas);
    console.log(barcodes);
    return barcodes.length > 0 ? barcodes[0]['rawValue'] : undefined;
  } catch (e) {
    throw e;
  }
}

Para dispositivos que ainda não têm suporte à API Shape Detection, precisamos de uma solução substituta para decodificar os códigos de barras. A API Shape Detection expõe uma getSupportedFormats() que ajuda a alternar entre a API Shape Detection e a solução substituta.

// Feature detection.
if (!('BarceodeDetector' in window)) {
  return;
}
// Check supported barcode formats.
BarcodeDetector.getSupportedFormats()
.then((supportedFormats) => {
  supportedFormats.forEach((format) => console.log(format));
});

Diagrama de fluxo mostrando como, dependendo do suporte ao Detector de código de barras e dos formatos compatíveis, a API Shape Detection ou a solução substituta está sendo usada.

Solução substituta

Várias bibliotecas de código aberto e de varredura empresarial estão disponíveis e podem ser facilmente integradas com qualquer aplicativo da Web para implementar a verificação. Estas são algumas das bibliotecas que o MishiPay que recomendamos.

.
Nome da biblioteca Tipo Solução Wasm Formatos de código de barras
QuaggaJs Código aberto Não 1D
ZxingJs Código aberto Não 1D e 2D (limitado)
CodeCorp Enterprise Sim 1D e 2D
Scandit Enterprise Sim 1D e 2D
Comparação de bibliotecas de código aberto e comerciais para leitura de códigos de barras

Todas as bibliotecas acima são SDKs completos que compõem todas as camadas discutidas acima. Eles também expor interfaces para dar suporte a várias operações de verificação. Dependendo dos formatos de código de barras e de detecção do caso de negócios, é possível decidir entre soluções Wasm e não Wasm. Apesar da sobrecarga de exigir um recurso adicional (Wasm) para decodificar o código de barras, o Wasm em termos de acurácia, as soluções superam as soluções não Wasm.

O Scandit foi nossa principal escolha. Compatível com todos os códigos de barras formatos necessários para nossos casos de uso comerciais; ele supera todas as bibliotecas de código aberto disponíveis em e a velocidade de leitura.

O futuro da verificação

Depois que a API Shape Detection tiver suporte total em todos os principais navegadores, poderemos ter novo elemento HTML <scanner> que tem os recursos necessários para um leitor de código de barras. Engenharia da MishiPay acredita que há um bom caso de uso para que a funcionalidade de leitura de código de barras seja uma nova Elemento HTML, devido ao crescente número de bibliotecas de código aberto e licenciadas que estão permitindo experiências como Scan & Go e muitos outros.

Conclusão

O desgaste do app é um problema que os desenvolvedores enfrentam quando seus produtos entram no mercado. Os usuários muitas vezes querem para entender o valor que um aplicativo oferece antes de fazer o download. Em uma loja, onde O MishiPay economiza e melhorar a experiência, não é intuitivo esperar fazer o download antes de usar um aplicativo. É aqui que nosso PWA ajuda. Ao eliminar a barreira do Google, aumentamos nossas transações em 10 vezes e permitimos que nossos usuários economizassem 2,5 anos de esperando na fila.

Agradecimentos

Este artigo foi revisado por Joe Medley.