Проблемы с кириллицей при генерации QR-кодов

Я генерирую qr-код для оплаты.

public GenerateQrResponse createQr(CreateQrRequest request) {
        var bnplEntity = bnplRepository.findByOrderId(request.getOrderNumber());
        if (bnplEntity.isEmpty()) {
            messengerUtils.sendTelegramBotMessage(telegramChatId, "bnpl not found by orderId. createQr method, orderNumber = " + request.getOrderNumber());
            throw new RuntimeException("bnpl entity not found while requesting qr code for bnpl with order number = " + request.getOrderNumber());
        }
        var bnplDto = bnplService.prepareBnplResponse(bnplEntity.get());
        bnplDto.setBnplId(bnplEntity.get().getId());
        bnplDto.setDate(bnplEntity.get().getCreatedAt());
        String linkUrl = bnplUrlService.getBnplUrl(bnplDto);

        BufferedImage logoImage = createRedCircleImage(50, 50);
        String logoBase64 = convertImageToBase64(logoImage);

        try {
            QRCodeWriter qrCodeWriter = new QRCodeWriter();
            BitMatrix bitMatrix = qrCodeWriter.encode(linkUrl, BarcodeFormat.QR_CODE, 250, 250, getQrCodeHintMap());

            BufferedImage qrImage = MatrixToImageWriter.toBufferedImage(bitMatrix);

            byte[] logoBytes = Base64.getDecoder().decode(logoBase64);
            ByteArrayInputStream logoStream = new ByteArrayInputStream(logoBytes);
            logoImage = ImageIO.read(logoStream);

            BufferedImage combined = new BufferedImage(250, 250, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = combined.createGraphics();
            g.drawImage(qrImage, 0, 0, null);
            int x = (combined.getWidth() - logoImage.getWidth()) / 2;
            int y = (combined.getHeight() - logoImage.getHeight()) / 2;
            g.drawImage(logoImage, x, y, null);
            g.dispose();

            ByteArrayOutputStream combinedOutputStream = new ByteArrayOutputStream();
            ImageIO.write(combined, "PNG", combinedOutputStream);
            byte[] imageBytes = combinedOutputStream.toByteArray();
            return new GenerateQrResponse(Base64.getEncoder().encodeToString(imageBytes), request.getOrderNumber(), request.getAmount(), linkUrl);
        } catch (IOException | WriterException e) {
            throw new RuntimeException(e.getMessage());
        }
    }

Проблема в том, что когда я создаю DTO для qr, мне нужно указать адрес. Если адрес будет на английском языке, проблем не будет. Но если адрес будет написан кириллицей, то в qr-ссылке весь кириллический текст станет типа ?????

Основная проблема в том, что у меня все адреса написаны кириллицей, наша система работает так. Здесь ДТО

return BnplDTO.builder()
                      .bnplId(bnpl.getId())
                      .amount(bnpl.getAmount())
                      .bin("111111111111")
                      .address("ул. Астана 58А")
                      .legalName("Example")
                      .build();

Я использую библиотеку qrgen

<dependency>
            <groupId>net.glxn</groupId>
            <artifactId>qrgen</artifactId>
            <version>1.4</version>
</dependency>

Есть идея сменить библиотеку, но может кто-нибудь знает, как решить эту проблему? заранее спасибо

Проблема в том, что все, что закодировано в QR-матрице, представляет собой строку байтов. Нет ничего, что указывало бы на набор символов. Читатель не может сказать, что это должно быть.

Tim Roberts 13.06.2024 07:30

@TimRoberts, спасибо, помог поставить эту строку кодаhints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); и теперь qr выполняет ссылку noraml с кириллицей!

Dmitriy Gerassimenko 13.06.2024 08:33
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

QR-коды AFAIK используются для указания URL-адресов. И они обычно кодируются как UTF-8. Чтобы быть уверенным, используйте URL-кодирование. См. https://stackoverflow.com/a/10786112/4222206

Другой вариант — не помещать все данные в QR-код, а создать URL-адрес с кодом (транзакции), который ведет обратно на ваш веб-сайт, который затем предоставляет полную информацию.

Другие вопросы по теме