欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Salesforce Lightning Component通过Lightning Out暴露给外部服务

程序员文章站 2023-12-22 16:06:58
...

前言】:在实施Service Cloud Embeded Service时候,自定义Pre-Chat,Chat WIndow等需要用到Lightning Component,所以之前使用VFP + Site这一套方案实施的Live Agent需要升级为Lightning Component + Embeded Service + Site了,那么第一步需要解决的是如何将Lightning Component通过Site暴露给外部服务?经查阅资料,发现Lightning Out可以在VFP中引用Lightning Component。本篇将以Demo形式展示Lightning Out这一技术。

应用场景举例】:
1、使用Aura Component写了Trailhead排名应用,想暴露给参与者;
2、通过git应用托管服务,将sf资源暴露给end user,Sample

技术骨架】:
Salesforce Lightning Component通过Lightning Out暴露给外部服务

Demo演练】:
目标:我们有2个Aura Component,分别用来展示10个Accounts和Contacts,我们将2个组件放入同一个App里面,然后通过Lightning Out将组件内容渲染到VFP指定的块,最终通过Site将VFP暴露给外部(免登陆访问SF资源)。
效果:
Salesforce Lightning Component通过Lightning Out暴露给外部服务

代码示例:
Lightning Component部分:
a. Component & Controller.js

<!-- DisplayTenAccountsComp.cmp -->
<aura:component controller="LightningOutCtrl">
    <aura:attribute name="accList" type="Account[]" access="private"/>
    <aura:attribute name="userInfo" type="String" access="private"/>
    <aura:attribute name="conList" type="Contact[]" access="private"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <div>
    	<p>Current UserInfo: {!v.userInfo}</p>
    </div>
    <br/>
    <ul>
    	<aura:iteration items="{!v.accList}" var="acc">
            <li>{!acc.Id} · {!acc.Name}</li>
        </aura:iteration>
    </ul>
    <br/>
	<ul>
    	<aura:iteration items="{!v.conList}" var="con">
            <li>{!con.Id} · {!con.Name} · {!con.Account.Name}</li>
        </aura:iteration>
    </ul>
</aura:component>

<!-- DisplayTenAccountsCompController.js -->
({
	doInit : function(component, event, helper) {
		let action = component.get("c.getTenAccounts");
        action.setCallback(this, function(response) {
            const data = response.getReturnValue();
            const dataSize = data.length;
            console.log('dataSize: ' + dataSize);
            component.set('v.accList', data);
        });
        $A.enqueueAction(action);
        
        let action1 = component.get("c.getTenContacts");
        action1.setCallback(this, function(response) {
            const data = response.getReturnValue();
            const dataSize = data.length;
            console.log('dataSize: ' + dataSize);
            component.set('v.conList', data);
        });
        $A.enqueueAction(action1);
        
        let action2 = component.get("c.getUserInfo");
        action2.setCallback(this, function(response) {
            const data = response.getReturnValue();
            component.set('v.userInfo', data);
        });
        $A.enqueueAction(action2);
	}
})
<!-- DisplayTenContactsComp.cmp -->
<aura:component controller="LightningOutCtrl">
    <aura:attribute name="conList" type="Contact[]" access="private"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
	<ul>
    	<aura:iteration items="{!v.conList}" var="con">
            <li>{!con.Id} · {!con.Name}</li>
        </aura:iteration>
    </ul>
</aura:component>

<!-- DisplayTenContactsCompController.js -->
({
	doInit : function(component, event, helper) {
        let action1 = component.get("c.getTenContacts");
        action1.setCallback(this, function(response) {
            const data = response.getReturnValue();
            const dataSize = data.length;
            console.log('dataSize: ' + dataSize);
            component.set('v.conList', data);
        });
        $A.enqueueAction(action1);
	}
})

b. Apex Controller

public without sharing class LightningOutCtrl {
	@AuraEnabled
    public static List<Account> getTenAccounts() {
        return [SELECT Id, Name FROM Account LIMIT 10];
    }
    
    @AuraEnabled
    public static List<Contact> getTenContacts() {
        return [SELECT Id, Name, Account.Name FROM Contact LIMIT 10];
    }
    
    @AuraEnabled
    public static String getUserInfo() {
        return '{"UserName": '+UserInfo.getUserName()+', "Name": '+UserInfo.getName()+', "Email": '+UserInfo.getUserEmail()+'}';
        // return [SELECT Id, Name, UserName, Email, EmailEncodingKey, Profile.Name, UserRole.Name FROM User WHERE Id =:UserInfo.getUserId()];
    }
}

c. Dependency App(此处实现了ltng:allowGuestAccess接口用于暴露服务给外部用户,若未声明需要通过配置Connected App,然后再第三方应用通过账密/token登录后访问SF资源

<!-- ALightningOutApp.app -->
<aura:application extends="ltng:outApp" access="global" implements="ltng:allowGuestAccess">
    <aura:dependency resource="c:DisplayTenAccountsComp" />
    <aura:dependency resource="c:DisplayTenContactsComp" />
</aura:application>

d. VFP

<!-- Component和VFP不同源 -->
<apex:page showHeader="false" sidebar="false">
    <script src="https://yoursitedomain.force.com/site/lightning/lightning.out.js"></script>
    <center><apex:outputText style="font-size: 18px; color: #f0f" value="Hello, this is my Lightning Out Demo" /></center>
    <div id='accList'></div>
    <br/>
    <div id='conList'></div>
    
    <script>
        // dependencyApp
        $Lightning.use('c:ALightningOutApp', function() {
                // component used in dependencyApp
                $Lightning.createComponent('c:DisplayTenAccountsComp', 
                                           {},
                                           'accList',
                                           function() {
                                               //do some stuff
                                               console.log('accList has been created...');
                                           });
                // component used in dependencyApp
                $Lightning.createComponent('c:DisplayTenContactsComp',
                                           {},
                                           'conList',
                                           function() {
                                               //do some stuff
                                               console.log('conList has been created...');
                                           });
            }, 'https://yoursitedomain.force.com/site'
        );
    </script>
</apex:page>

<!-- Component和VFP同源 -->
<apex:page showHeader="false" sidebar="false">
    <apex:includeLightning />
    <center><apex:outputText style="font-size: 18px; color: #f0f" value="Hello, this is my Lightning Out Demo" /></center>
    <div id='accList'></div>
    <br/>
    <div id='conList'></div>
    
    <script>
        $Lightning.use('c:ALightningOutApp', function() {
            // component used in dependencyApp
            $Lightning.createComponent('c:DisplayTenAccountsComp', 
                                       {},
                                       'accList',
                                       function() {
                                           //do some stuff
                                           console.log('accList has been created...');
                                       });
            // component used in dependencyApp
            $Lightning.createComponent('c:DisplayTenContactsComp',
                                       {},
                                       'conList',
                                       function() {
                                           //do some stuff
                                           console.log('conList has been created...');
                                       });
        });
    </script>
</apex:page>

特别注意】:
1. 如果不同源,需要在Comonent所在的Org加CORS(同源不存在跨域,不需要加);
2. 必须在site profile里启用vfp(同源时),apex和OLS(缺一不可);
3. 如果查询org级别数据,apex必须使用without sharing,FLS加不加无所谓;
否则console出现服务器500错误或如下错误:
Access to XMLHttpRequest at 'https://yoursitedomain1.force.com/site1/ALightningOutApp.app?aura.format=JSON&aura.formatAdapter=LIGHTNING_OUT' from origin 'https://yoursitedomain2.force.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

上一篇:

下一篇: