Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pdf.ref is not a function #259

Open
riicardojs opened this issue Jul 4, 2024 · 0 comments
Open

pdf.ref is not a function #259

riicardojs opened this issue Jul 4, 2024 · 0 comments

Comments

@riicardojs
Copy link

riicardojs commented Jul 4, 2024

I'm having trouble generating the signature in the document. I’ve tried with both a PDF created from scratch using pdf-lib and an existing PDF in versions 1.7 and 1.4, but all attempts have failed. I keep getting the error "pdf.ref is not a function." Has anyone encountered this problem? I was successful with placeholder-plain, but I'm unable to get it to work with placeholder-pdfkit010, which is supposed to allow for a visible signature.

import {
  pdfkitAddPlaceholder,
  ReturnType,
} from "@signpdf/placeholder-pdfkit010";
import { P12Signer } from "@signpdf/signer-p12";
import signpdf from "@signpdf/signpdf";
import { FastifyInstance } from "fastify";
import fs from "fs";
import { PDFDocument, rgb } from "pdf-lib";
import z from "zod";

export async function getSign(app: FastifyInstance) {
  app.get("/sign/:certificateId", async (request, reply) => {
    const getSignBody = z.object({
      certificateId: z.string().uuid(),
    });

    const { certificateId } = getSignBody.parse(request.params);

    const pdfBuffer = fs.readFileSync(
      `${__dirname}/../../../resources/${certificateId}.pdf`
    );
    const certificateBuffer = fs.readFileSync(
      `${__dirname}/../../../resources/certificate.p12`
    );

    const targetPath = `${__dirname}/../../../output/${certificateId}.pdf`;

    const pdfWithVisual = await addVisual(pdfBuffer);

    const signer = new P12Signer(certificateBuffer, {
      passphrase: process.env.CERT_PASSWORD,
    });

    const signedPdf = await signpdf.sign(pdfWithVisual, signer);

    fs.writeFileSync(targetPath, signedPdf);

    return reply.status(200).send({ certificateId });
  });
}

async function addVisual(pdfBuffer: Buffer): Promise<Uint8Array> {
  const pdfDoc = await PDFDocument.load(pdfBuffer);
  const pages = pdfDoc.getPages();
  const firstPage = pages[0];

  const { width, height } = firstPage.getSize();

  const margin = 30;
  const padding = 10;
  const labelDoc = "Doc signature";
  const labelName = "Company name";
  const labelDate = "Data: 03/07/2024 19:22:23-0300";
  const imageBuffer = fs.readFileSync(
    `${__dirname}/../../../assets/govbr-logo.png`
  );
  const textWidth = 200;
  const textHeight = 20;

  const x = width - textWidth - margin;
  const y = height - textHeight - margin;

  firstPage.drawText(labelDoc, {
    x,
    y,
    size: 10,
    color: rgb(0, 0, 0),
  });

  firstPage.drawText(labelName, {
    x,
    y: y - 20,
    size: 10,
    color: rgb(0, 0, 0),
  });

  firstPage.drawText(labelDate, {
    x,
    y: y - 35,
    size: 10,
    color: rgb(0, 0, 0),
  });

  const pngImage = await pdfDoc.embedPng(imageBuffer);

  // Desenhar a imagem na primeira página
  firstPage.drawImage(pngImage, {
    x: x - 65,
    y: y - 40,
    width: 70,
    height: 30,
  });

  const visualRect = [
    x - padding,
    y - padding,
    x + textWidth + padding,
    y + textHeight + padding,
  ];
  const widgetRect = topLeftToBottomLeft(visualRect, { width, height });

  const refs = pdfkitAddPlaceholder({
    pdf: pdfDoc,
    pdfBuffer,
    reason: "Showing off.",
    contactInfo: "[email protected]",
    name: "Sign PDF",
    location: "The digital world.",
    signatureLength: 1612,
    widgetRect,
    signingTime: new Date(),
  });

  // Manually end the refs
  (Object.keys(refs) as (keyof ReturnType)[]).forEach((key) => {
    refs[key].end();
  });

  const modifiedPdfBuffer = await pdfDoc.save();

  return modifiedPdfBuffer;
}

function topLeftToBottomLeft(
  coords: number[],
  page: { width: number; height: number }
): number[] {
  return [
    coords[0], // x1
    page.height - coords[1], // y1
    coords[2], // x2
    page.height - coords[3], // y2
  ];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant