使用JavaScript URL模拟JSONP响应

fzsnzjdm  于 2023-01-29  发布在  Java
关注(0)|答案(4)|浏览(153)

我在WP站点上使用Gravity Forms。我的表单使用Pardot form handlers通过 AJAX 发布到Pardot。我遇到了Pardot处理表单6x的问题,没有其他错误。研究表明这是因为Pardot不支持CORS或JSONP,因此在使用 AJAX 提交时会陷入循环。当表单处理程序的Success URL被设置为refering URL时,它会处理提交,但永远不会“完成”。它尝试6x之前放弃,处理提交的数据,并发送新的前景通知电子邮件每一次.
Pardot help docs建议采用以下解决方案:
通过将表单处理程序的Success和Error URL设置为分别执行Success和Error回调的JavaScript URL,可以模拟JSONP响应。
我不太清楚这意味着什么,也不知道该怎么做。我做了一些堆栈溢出和谷歌搜索,但我似乎无法完全理解如何做。有人能帮助澄清这个概念,或者给我指出正确的方向吗?
谢谢!

fhity93d

fhity93d1#

编辑:经过几天的努力,我将发布我的最终解决方案,它可能会帮助其他人尝试使用JSONP与Pardot通信。
1.向Pardot表单处理程序发送JSONP请求
1.将Pardot表单处理程序成功/错误重定向到您自己的服务器
1.从服务器返回JSONP

从处理程序向Pardot发送JSONP请求

要将表单数据发送到表单处理程序,您需要对字段名称和值进行URI编码。
(使用JQuery的示例。 AJAX ()在指定dataType时添加了'?callback=':“jsonp”):

var data = { 'field1' = 'value1', 'field' = 'value2' };
var uriEncodedParams = $.param(data);
var targetUrl = <Pardot Form Handler URL> + '?' + uriEncodedParams;

$.ajax({
    url: targetUrl,
    dataType: 'jsonp',
    jsonpCallback: 'callback'
});

window.callback = function (data) {...}

将Pardot从处理程序成功/错误重定向到您自己的服务器

看@nickjag的回答:
将成功位置和错误位置设置为后端上的端点。
由于pardot不会转发您传入的任何GET参数,因此您必须使用一些默认值,例如回调函数名称(因此指定jsonpCallback,并且在我的请求中没有成功)。

从服务器返回JSONP

我在使用时遇到控制台错误(Uncaught SyntaxError: Unexpected token :)问题:return "{ 'result' : 'success' }",因为它是JSON对象,并且JSONP需要使用JavaScript的文件。因此,返回的格式应为:return "callback({ 'result' : 'success' })"
同样,Pardot不转发GET参数,JQuery生成的回调函数名不传播,我无法返回正确的JavaScript代码。如果没有提供函数名,默认使用“callback”。
Guide for returning JSONP from .NET MVC backend

sh7euo9m

sh7euo9m2#

Pardot的建议是在您自己的服务器上创建2个静态URL,返回一个简单的JSON响应。
例如:

  1. mysite.com/pardot-success
    退货:{"result":"success"}
  2. mysite.com/pardot-error
    返回值:{"result":"error"}
    然后,您将使用这两个URL作为Pardot表单处理程序设置的成功和错误重定向URL。
    然后可以使用JSONP向Pardot表单处理程序发出AJAX请求,JSONP将 Package 并返回来自其中一个URL的JSON响应(取决于结果)。
    AJAX响应数据将包含JSON结果(成功或错误)。
rkttyhzu

rkttyhzu3#

这里的所有答案确实帮助我着手实施这个解决方案,但我的要求是让所有东西都只通过Salesforce运行。因此,对于那些只使用Salesforce后端架构寻找答案的人来说,我希望这能有所帮助。我不得不稍微改变一下 AJAX 调用的结构,让它运行起来:

var data = { 'username': username };
var uriEncodedParams = $.param(data);
var targetUrl = 'https://my.pardot.url' + '?' + uriEncodedParams;
$.ajax({
    url: targetUrl,
    type: 'GET',
    dataType: 'jsonp',
    crossDomain: true
});

window.callback = function(data) {
    performMoreActions(data);
}

我的服务器是用Apex(Salesforce的编程语言)构建的,如下所示:

@RestResource(urlMapping='/pardot/success/*')
global without sharing class Pardot_SuccessProxy {

    @HttpGet
    global static void Pardot_SuccessProxy() {
        RestContext.response.addHeader('Content-Type', 'application/json');
        RestContext.response.responseBody = (Blob.valueOf('callback({ "result" : "success" })'));
    }
}

然后,我通过Salesforce站点公开此REST Web服务,URL如下所示:
https://my-domain.server-domain.force.com/services/apexrest/pardot/success
https://my-domain.server-domain.force.com/services/apexrest/pardot/error
在Pardot表单处理程序UI中,将Success Location和Error Location字段分别设置为这些URL。
这与这个问题的其他答案非常相似,但完全来自Salesforce的方法。它可能与OP技术栈有些无关,但它应该对未来寻找答案的人有所帮助。

mec1mxoz

mec1mxoz4#

谢谢你在这里的所有答案,经过一天的挠头,我设法找到了如何让这个工作与香草js(使用vue)。我想我会张贴在这里,以帮助避免任何可怜的灵魂经历同样的挫折。

相同域上的js文件成功/错误

success.js:

logResult({ result: 'success' });

error.js:

logResult({ result: 'error' });

将这些URL添加到Pardot表单处理程序的“成功位置”和“错误位置”字段中
Jsonp函数

我使用vue构建了这个站点,所以我将下面的函数添加到/asses/js/util. js

//  Copyright (c) 2017 Ziqiang Li - copied and edited from https://github.com/liziqiang/simple-jsonp-promise/blob/master/src/index.js
// Callback index.
let count = 0;

function jsonp(url, options) {
  options = options || {};
  const prefix = options.prefix || 'logResult';
  const callback = options.callback || 'callback';
  const callbackName = options.callbackName;
  const params = options.data || {};
  const target = document.getElementsByTagName('script')[0] || document.head;
  let script;
  let timer;
  // Generate a unique id for the request.
  const id = callbackName || prefix + count++;

  function noop() {}

  function cleanup() {
    // Remove the script tag.
    if (script && script.parentNode) {
      script.parentNode.removeChild(script);
    }
    window[id] = noop;
    if (timer) {
      clearTimeout(timer);
    }
  }

  function serialize(params) {
    let param = '';
    for (const key in params) {
      if (params.hasOwnProperty(key)) {
        param += `&${key}=${encodeURIComponent(params[key])}`;
      }
    }
    return param;
  }

  function handleUrl(url, params) {
    if (!~url.indexOf('?')) { url += '?'; }
    url += serialize(params);
    url = url.replace('?&', '?');
    return url;
  }

  return new Promise((resolve, reject) => {
    window[id] = function(data) {
      cleanup();
      resolve(data);
    };
    if (!callbackName) {
      params[callback] = id;
    }
    url = handleUrl(url, params);
    // Create script.
    script = document.createElement('script');
    script.src = url;

    window.logResult = function(json) {
      if (json.result === 'success') {
        resolve();
      } else if (json.result === 'error') {
        reject(new Error('Error'));
      }
    };

    script.onerror = function() {
      cleanup();
      reject(new Error('Network Error'));
    };
    target.parentNode.insertBefore(script, target);
  });
}

export default jsonp;

注意:回调函数名(logResult)必须与success/error js文件中的函数名相同

提交功能

我的vue组件中的脚本(应该很容易转移到vanilla js/其他框架):

<script>
import jsonp from '@/assets/js/util';

export default {
  name: 'FormTest',

  data() {
    return {
      firstname: '',
      lastname: '',
      email: '',
    };
  },

  methods: {
    submit() {
      const options = {
        data: {
          firstname: this.firstname,
          lastname: this.lastname,
          email: this.email,
        },
      };

      jsonp('PARDOT_FORM_HANDLER_URL', options).then(() => {
        console.log('success');
      }).catch(err => {
        console.error(err);
      });
    },
  },
};
</script>

相关问题