Salesforce - 在按钮单击时调用外部 API 并根据响应更新自定义字段

Salesforce - Call external API on button click and update custom field from response

所以我首先要说我是一名 C# .Net/Javascript 开发人员,具有丰富的经验,但我对 Salesforce 的经验为零。今天之前从未见过它。因此,另一个团队要求我向 Contact 对象添加自定义按钮,单击该按钮时会调用外部 API 并使用响应更新 Contact 中的自定义字段。它被宣传为“只需编写一些 Javascript,在单击按钮时调用 API,它实际上嵌入到页面中,15 分钟的工作...”。

按照看起来相当过时的文档,我最终进入了对象管理器,选择了联系人对象,然后进入了按钮、链接和操作页面。我假设在此之前使用 Execute Javascript 行为完成,在 Lightning 版本中我被建议不要使用。因此,经过大量谷歌搜索后,我阅读了有关 APEX classes、Visualforce 组件、Lightning 组件、Salesforce REST API 等的信息。不是 15 分钟的工作。

本质上,要求是将一个按钮(或操作,或..?)嵌入此联系人页面,以便当销售人员单击它时,它会收集一些联系人的详细信息并使用它们来形成 API调用外部服务。数据将用于形成响应,然后必须读取(如 JSON,然后解析)并写入联系人上的自定义字段。

开发解决方案的最佳方法是什么?在 Apex 调试环境中,我将调用 API 的代码放在一起并解析 JSON 响应,我假设我需要将其包装在 Apex class 中,并带有调用此代码的方法和 returns 响应。我不确定的是如何从按钮调用它,并更新联系人中的字段。 我是否需要通过 Apex Class 方法执行所有这些操作?传递对联系人的引用,或者是否有另一个组件需要位于两者之间并执行此操作。 我假设我需要使用 Salesforce API 更新联系人是否正确?

感谢任何指点。

我把我的做法写给你

记录按钮 page/page 布局 -> 照明组件或流程 -> Apex class 用于收集数据 -> apex class 请求和响应 API(don不要忘记将端点添加到远程站点设置)-> 解析响应并更新联系人(您可以在 Apex 中使用查询和 DML 操作)

灯饰组件 有一个顶点class作为控制器例子就很简单了

<aura:component implements="force:appHostable,lightning:isUrlAddressable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" controller="contactController" access="global" >

<aura:handler name="init" value="{!this}" action="{!c.fetchContact}"/>
</aura:component>

控制器

({
fetchContact : function(component, event, helper) {
    helper.fetchContactHelper(component, event, helper);
    
}
})

帮手

({
fetchAccHelper : function(component, event, helper) {
    var action = component.get("c.fetchContacts");
    action.setParams({
    });
    action.setCallback(this, function(response){
        var state = response.getState();
        if (state === "SUCCESS") {
        }
    });
    $A.enqueueAction(action);
}
})

假设 apex 函数是 fetchContacts 和 class contactController

天哪。这可能是一个 15 分钟的工作,但它绝对是“当你知道怎么做时很容易”或者有一些例子;)

  1. 您的用户界面是什么,Classic 还是 Lightning?他们有计划很快迁移到 Lightning 吗?如果您发现“Execute JavaScript”技巧已经过时,我假设它是 Lightning。
  2. 你关心 button/action 在哪里吗?右上角的所有其他按钮是否正常,或者您希望它可以拖放到页面中的几乎任何区域?
  3. API 标注是否需要用户名、密码或证书?它将确定您是只需要将端点列入防火墙的白名单(设置 -> 远程站点设置)还是需要更高级的东西(设置 -> 命名凭据)。
  4. 您是否有 SFDX 命令行 (CLI),VSCode/是否确定要安装一些工具? Lightning Web 组件是尖端的、最时尚的等,但您不能直接在浏览器中创建它们(至少现在还不能),您需要工具。 Visualforce 还可以,但对于这个用例来说没有什么特别之处,Aura 组件编写起来有点笨拙 - 但您可以在开发人员控制台中完成这两个操作而无需额外的工具。
  5. 解析 JSON 响应 - 取决于它的复杂程度,您可以使用 JSON.deserializeUntyped() but life's too short for this. Here's nice apex code generator similar to what you'd get from parsing WSDL: https://json2apex.herokuapp.com/
  6. hand-craft 解析器

我们会尝试做Aura组件的方式。这很丑陋,LWC 是未来,但嘿,它会让你开始。


转到设置 -> 远程站点设置并使用 https://en.wikipedia.org/

添加新条目

创建新的 Apex class:

public with sharing class Stack63364119 {
    static final String endpoint = 'https://en.wikipedia.org/w/api.php?action=query&format=json&list=search&srsearch=';
    @AuraEnabled
    public static String doCallout(Id contactId){
        if(contactId == null){
            throw new MyException('Missing record id');
        }
        List<Contact> contacts = [SELECT MailingCountry FROM Contact WHERE Id = :contactId];
        if(contacts.isEmpty() || String.isBlank(contacts[0].MailingCountry)){
            throw new MyException('Could not find the contact');
        }
        Contact c = contacts[0];

        HttpRequest req = new HttpRequest();
        req.setEndpoint(endpoint + c.MailingCountry);
        req.setMethod('GET');

        HTTPResponse res = new Http().send(req);
        System.debug(res.getStatus());
        System.debug(res.getBody());
        // no special parsing, just chuck it into Description field
        // no error handling
        if(res.getStatusCode() == 200){
            c.Description = res.getBody().abbreviate(32000);
            update c;
        }
        return res.getBody();
    }
    public class MyException extends Exception{}
}

在开发者控制台中制作新的“闪电组件”(它将是 Aura,而不是 LWC)。您可以勾选关于“闪电般快速行动”的最后一个复选框。名称可以与 class 相同,但并非必须如此。

对于组件(~ html 部分)粘贴这个

<!-- Loosely based on https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/controllers_server_actions_call.htm -->
<aura:component controller="Stack63364119" implements="force:hasRecordId,force:lightningQuickAction" >
    <!-- in the name of all that is holy do not name the JS function same as the Apex class function, it'll give you very cryptic errors to debug -->
    <aura:handler name="init" value="{!this}" action="{!c.runCallout}"/> 
</aura:component>

对于控制器 (~ JavaScript) 粘贴这个

({
    runCallout : function(cmp) {
        let action = cmp.get('c.doCallout');
        action.setParams({contactId : cmp.get('v.recordId')});
        action.setCallback(this, function(response){
            let state = response.getState();
            if (state === "SUCCESS") {
                alert('Saved OK: ' + response.getReturnValue());
                $A.get("e.force:closeQuickAction").fire(); // if you want to self-close
            } else if (state === "ERROR") {
                var errors = response.getError();
                if (errors) {
                    if (errors[0] && errors[0].message) {
                        console.log("Error message: " + errors[0].message);
                    }
                } else {
                    console.log("Unknown error");
                }
            }
        });
        $A.enqueueAction(action);
    }
})

最后转到对象管理器 -> 联系人 -> 按钮链接和操作。创建新的快速操作。 并将其添加到页面布局!

它应该可以帮助您入门。也许你会决定稍微拆分一下,Apex 只会做标注,return 结果为 UI,如果用户满意 - 更新联系人可以使用以下之一完成:https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/data_service_save_record.htm.关注点分离等等(但用户会对 2 次点击感到满意)。

P.S。如果你调整它并且它死了但是很难看到任何 JavaScript 错误 - 这是因为在发布模式下默认是 运行 ,SF 稍微重写你的源代码,优化,polyfills “ IE11 之类的浏览器...转到设置 -> 调试模式并为您的用户启用。

P.P.S。在 sandbox / dev org 中,最好转到设置 -> 会话设置 -> 并取消勾选“启用安全和持久的浏览器缓存以提高性能”。您的组件将永远是新鲜的,省去了按 Ctrl+R 的狂热。不要在产品中这样做 ;)