React 应用程序中的 Docusign 焦点视图,加载图标进入无限循环,控制台日志中出现 CSP 错误

问题描述 投票:0回答:1

我一直在尝试将 docusign 与焦点视图集成到我的 React 应用程序中。我正在使用用于nodejs的docusign SDK,并且express服务器发出所有API请求并通过docusign获取数据,因此我能够使用postman获取URL并访问链接直接打开表单,但是当在react应用程序中嵌入新的URL时,文档签名加载图标在焦点视图中无限循环。

控制台日志显示内容安全策略错误。 docusign React 示例应用程序没有太多运气。

下面是取自 docusign How-to 指南并针对 React 进行调整的代码:LINK

import React, { useEffect } from 'react';
import PropTypes from 'prop-types';

function DocumentSignUI({ integrationKey, docUrl }) {
  useEffect(() => {
    const loadDocuSign = async () => {
      try {
        const docusign = await window.DocuSign.loadDocuSign(integrationKey);
        const url = `${docUrl}&output=embed`;

        const signing = docusign.signing({
          url,
          displayFormat: 'focused',
        });

        signing.mount('#agreement');
      } catch (ex) {
        console.error(ex);
        // Handle error
      }
    };

    console.log('DOCUSIGN RENDER');
    loadDocuSign();
  }, []);

  return (
    <div className="docusign-agreement" id="agreement" />
  );
}

DocumentSignUI.propTypes = {
  integrationKey: PropTypes.string.isRequired,
  docUrl: PropTypes.string.isRequired,
};

export default DocumentSignUI;

控制台日志中遇到的错误(Chromium) Chromium 控制台错误

控制台日志中遇到的错误(Firefox) Firefox 控制台错误

尝试在服务器上禁用内容安全策略,但不起作用,尝试在index.html中添加元标记,但这也不起作用。

这是API调用的代码

router.get("/sign-document", processFile, async (req, res) => {
  try {
    var userData = "";

    await checkToken(req);


    var apiClient = new docusign.ApiClient({
      basePath: basePath,
      oAuthBasePath: oAuthBasePath + "/oauth/token",
    });

    apiClient.addDefaultHeader(
      "Authorization",
      "Basic KEY"
    );

    userData = await apiClient.getUserInfo(req.session.access_token);

    var baseUri = userData.accounts[0].baseUri;
    var accountDomain = baseUri.split("/v2");
    apiClient.setBasePath(accountDomain[0] + "/restapi");

    const envelopeArgs = {
      signerEmail: "EMAIL",
      signerName: "NAME",
      signerClientId: DOCUSIGN_JWT_CLIENT_ID,
      docFile: req.file,
      status: "created",
    };

    const envelope = makeEnvelope(envelopeArgs);


    const envelopesApi = await getEnvelopes(req);



    const userEnvelopeResult = await envelopesApi.createEnvelope(
      userData.accounts[0].accountId,
      { envelopeDefinition: envelope }
    );

    const recepientRequest = {
      dsReturnUrl: "https://localhost:5173/success",
      signerEmail: "EMAIL",
      signerName: "NAME",
      signerClientId: DOCUSIGN_JWT_CLIENT_ID,
    };


    const viewRequest = await makeRecipientViewRequest(recepientRequest);


    const viewRequestResult = await envelopesApi.createRecipientView(
      userData.accounts[0].accountId,
      userEnvelopeResult.envelopeId,
      {
        recipientViewRequest: viewRequest,
        frameAncestors: [
          "http://localhost",
          "https://apps-d.docusign.com",
        ],
        messageOrigins: ["https://apps-d.docusign.com"],
        signerEmail: "[email protected]",
        signerName: "KinessaJJJ"
      }
    );


    res.status(200).json({
      envelopeId: userEnvelopeResult.envelopeId,
      redirectUrl: viewRequestResult.url,
    });
  } catch (error) {
    console.error("Error processing request:", error);
    res.status(500).json({
      success: false,
      message: "An error occurred while processing the request",
    });
  }
});

功能如下

    const checkToken = async (req) => {
  try {
    var apiClient = new docusign.ApiClient({
      basePath: basePath,
      oAuthBasePath: oAuthBasePath + "/oauth/token",
    });

    apiClient.addDefaultHeader(
      "Authorization",
      "Basic OTAyY2IxNmYtYjBmZi00MzY2LWIyYzQtZDBmNWM3MTk1NTc0OjhlMzJjNzI0LTI1NjMtNDM0MC1iMTk5LWQxYTEwMTBhODM5YQ=="
    );

    var oauthLoginUrl = await apiClient.getJWTUri(
      DOCUSIGN_JWT_CLIENT_ID,
      "http://localhost:5173/",
      oAuthBasePath
    );
    var scopes = [oAuth.Scope.IMPERSONATION, oAuth.Scope.SIGNATURE];

    if (req.session.access_token && Date.now() < req.session.expires_at) {
      console.log("re-using access token ", req.session.access_token);
    } else {
      console.log("creating new access token");
      jWTResponse = await apiClient.requestJWTUserToken(
        DOCUSIGN_JWT_CLIENT_ID,
        DOCUSIGN_IMPERSONATED_USER_GUID,
        scopes,
        DOCUSIGN_RSA_KEY,
        36000
      );

      console.log(jWTResponse.body.access_token);

      req.session.access_token = jWTResponse.body.access_token;

      req.session.expires_at =
        Date.now() + (jWTResponse.body.expires_in - 60) * 1000;
    }
  } catch (error) {
    console.error("Error while checking token:", error);
  }
};

const getEnvelopes = async (req) => {
  let dsApiClient = new docusign.ApiClient();
  dsApiClient.setBasePath(basePath);
  dsApiClient.addDefaultHeader(
    "Authorization",
    "Bearer " + req.session.access_token
  );
  return new docusign.EnvelopesApi(dsApiClient);
};

const makeEnvelope = (args) => {
  let docPdfBytes;
  // const filePath = path.resolve(__dirname, args.docFile);
  // docPdfBytes = fs.readFileSync(filePath);

  console.log(args.docFile);

  let env = new docusign.EnvelopeDefinition();
  env.emailSubject = "Please sign this document";

  let doc1 = new docusign.Document();
  let doc1b64 = Buffer.from(args.docFile.buffer).toString("base64");
  doc1.documentBase64 = doc1b64;
  doc1.name = "Lorem Ipsum";
  doc1.fileExtension = "pdf";
  doc1.documentId = "3";

  env.documents = [doc1];

  let signer1 = docusign.Signer.constructFromObject({
    email: args.signerEmail,
    name: args.signerName,
    clientUserId: args.signerClientId,
    recipientId: 1,
  });

  let signHere1 = docusign.SignHere.constructFromObject({
    anchorString: "/sn1/",
    anchorYOffset: "10",
    anchorUnits: "pixels",
    anchorXOffset: "20",
  });
  let signer1Tabs = docusign.Tabs.constructFromObject({
    signHereTabs: [signHere1],
  });
  signer1.tabs = signer1Tabs;

  let recipients = docusign.Recipients.constructFromObject({
    signers: [signer1],
  });
  env.recipients = recipients;
  env.status = "sent";

  return env;
};

const makeRecipientViewRequest = (args) => {
  let viewRequest = new docusign.RecipientViewRequest();
  viewRequest.returnUrl = args.dsReturnUrl;

  viewRequest.authenticationMethod = "none";

  viewRequest.email = args.signerEmail;
  viewRequest.userName = args.signerName;
  viewRequest.clientUserId = args.signerClientId;

  viewRequest.frameAncestors = [
    "http://localhost:4000/api",
    "https://apps-d.docusign.com",
  ];
  viewRequest.messageOrigins = ["https://apps-d.docusign.com"];

  return viewRequest;
};
reactjs node.js express docusignapi docusign-sdk
1个回答
0
投票

问题是(已在评论中确认)

frameAncestors(一个数组,表示将在其中呈现聚焦视图的框架的原始域。它必须包含您网站的 URL 以及 https://apps-d.docusign.comhttps://apps-d。 docusign.com,在开发环境中在新窗口中打开,或 https://apps.docusign.comhttps://apps.docusign.com,在生产环境中在新窗口中打开 除非您的站点必须具有有效的 SSL 证书。您正在使用 http://localhost 域。)

未正确设置。

这是在服务器代码中完成的(或者 REST API 代码仍然可以来自使用 CORS 的客户端),这就是这里的问题。虽然您仍然会得到一个可以使用的 URL,但如果您没有正确设置 frameAncestors,它将不会加载。

这是一个片段:

viewRequest.frameAncestors = ['http://localhost:3000', 'https://apps-d.docusign.com'];
viewRequest.messageOrigins = ['https://apps-d.docusign.com'];
© www.soinside.com 2019 - 2024. All rights reserved.