如何检测Salesforce中的环境?

如何检测Salesforce中的环境?,salesforce,sandbox,apex-code,Salesforce,Sandbox,Apex Code,我正在使用web服务将我们的后端系统与Salesforce集成。我有在不同URL上运行的生产和阶段环境。我需要能够使web服务调用的端点有所不同,这取决于代码是在生产实例中运行还是在sandbox Salesforce实例中运行 String s = System.URL.getSalesforceBaseUrl().getHost(); //this will return "na1.salesforce.com" or "na1-api.salesforce.com", // wher

我正在使用web服务将我们的后端系统与Salesforce集成。我有在不同URL上运行的生产和阶段环境。我需要能够使web服务调用的端点有所不同,这取决于代码是在生产实例中运行还是在sandbox Salesforce实例中运行

String s  =  System.URL.getSalesforceBaseUrl().getHost();
//this will return "na1.salesforce.com"  or "na1-api.salesforce.com",
// where na1 is your instance of SF, and -api may be there depending on where you run this
s = s.substring(0,s.indexOf('.'));
if(s.contains('-'))
{
    s = s.substring(0,s.indexOf('-'));
}
system.debug(s);
如何检测环境

目前,我正在考虑查找一个用户,看看是否有用户名以“devsandbox”结尾,因为我无法识别可以查询以获取环境的系统对象

进一步澄清:


我需要确定的位置是在我在Salesforce中选择按钮时调用的Apex代码中。我的自定义控制器需要知道它是在生产环境还是在沙盒Salesforce环境中运行。

登录API调用在返回的LoginResult结构中返回一个沙盒元素,该元素从WSDL指示它是否是沙盒环境

        <complexType name="LoginResult">
            <sequence>
                <element name="metadataServerUrl" type="xsd:string" nillable="true"/>
                <element name="passwordExpired"   type="xsd:boolean" />
                <element name="sandbox"      type="xsd:boolean"/>
                <element name="serverUrl"         type="xsd:string" nillable="true"/>
                <element name="sessionId"         type="xsd:string" nillable="true"/>
                <element name="userId"           type="tns:ID" nillable="true"/>
                <element name="userInfo"         type="tns:GetUserInfoResult" minOccurs="0"/>
            </sequence>
        </complexType>

我认为最简单的方法是在Salesforce中创建一个自定义对象,然后在其中存储一个指示sandbox或production的值。然后,您的Apex代码可以查询该对象。一个建议是使用Apex静态构造函数加载此信息,并为请求缓存它

我的另一个想法(但我不想建议)是使用外部服务来确定Apex代码的执行位置。这可能很难实现,因为每次SalesForce服务器场发生更改时,您的代码都会被破坏,但我只是觉得我应该把它扔出去

HttpRequest req = new HttpRequest();
req.setEndpoint('http://www.whatismyip.com/automation/n09230945.asp');
req.setMethod('GET');

Http http = new Http();
HTTPResponse res = http.send(req);
System.debug(res.getBody());

您必须将“”添加到远程站点设置以使其正常工作(设置>管理设置>安全控制>远程站点设置)。单击“系统日志”时,此代码应在调试窗口中运行。

根据响应,Salesforce似乎没有一个系统对象可以告诉我Apex代码是在生产环境还是沙箱环境中运行

我将根据以下假设继续进行:

  • 我可以读取当前环境的组织id
  • 我的生产系统的组织id将始终保持不变
  • 沙箱的组织id始终与生产不同(因为它们是唯一的)
当前组织ID可以通过
System.getOrganizationId()找到


我的解决方案是让我的代码将当前组织id与代表生产的常量值进行比较。

我在这里执行巫术,答案已经被接受,但可能有人会从中受益

在Visualforce页/S控件上使用以下合并字段之一:

{!$Api.Enterprise_Server_URL_180}, {!$Api.Partner_Server_URL_180}, {!$Api.Session_ID}
您可以轻松地从中解析出组织ID


在Apex代码中:

我知道这是一篇老文章,但为了便于人们在2011年春季发布时寻找更新的答案,有一个新方法System.URL.getSalesforceBaseUrl().toExternalForm()返回当前URL。
你可以从那里得到你需要的所有信息


这里是指向文档的链接:

在您的apex代码中,您可以使用以下内容获取您所在的SF实例

保持其动态性将确保在组织迁移到其他实例时不必更新代码

String s  =  System.URL.getSalesforceBaseUrl().getHost();
//this will return "na1.salesforce.com"  or "na1-api.salesforce.com",
// where na1 is your instance of SF, and -api may be there depending on where you run this
s = s.substring(0,s.indexOf('.'));
if(s.contains('-'))
{
    s = s.substring(0,s.indexOf('-'));
}
system.debug(s);

沙盒可能有一个个性化的url(例如acme.cs1.my.salesforce.com),或者可能托管一个visualforce页面(cs2.visual.force.com),或者两者都托管(acme.cs2.visual.force.com),因此我使用以下方法:

public static Boolean isRunningInSandbox() {
    String s  =  System.URL.getSalesforceBaseUrl().getHost();
    return (Pattern.matches('(.*\\.)?cs[0-9]*(-api)?\\..*force.com',s));
}   

Salesforce StackExchange上有一个类似的问题,用于检测您是否在沙箱中-

在中,您可以使用OrgId中的pod标识符来确定是否正在处理沙箱

string podId = UserInfo.getOrganizationId().substring(3,4);
boolean isSandbox = 'TSRQPONMLKJZVWcefg'.contains(podId);
System.debug('IsSandbox: ' + isSandbox);

Caveat Confector:这里最大的缺点是,当Salesforce将新的沙盒豆荚上线时,您需要更新已知沙盒豆荚列表(因此使用其他解决方案可能更安全)

您可以使用Salesforce权威机构Michael Farrington提供的以下代码块

原文如下:

如果您在测试或沙盒环境中,此方法将返回true,否则返回false

    public Static Boolean isSandbox(){

    String host = URL.getSalesforceBaseUrl().getHost();
    String server = host.substring(0,host.indexOf('.'));

    // It's easiest to check for 'my domain' sandboxes first 
    // even though that will be rare
    if(server.contains('--'))
        return true;

    // tapp0 is a unique "non-cs" server so we check it now
    if(server == 'tapp0')
        return true;

    // If server is 'cs' followed by a number it's a sandbox
    if(server.length()>2){
        if(server.substring(0,2)=='cs'){
            try{
                Integer.valueOf(server.substring(2,server.length()));
            }
            catch(exception e){
                //started with cs, but not followed by a number
                return false;
            }

            //cs followed by a number, that's a hit
            return true;
        }
    }

    // If we made it here it's a production box
    return false;
}

对于所有通过搜索结果找到这些的人来说,有一个重要的更新。正如Daniel Hoechst在中指出的,SF现在直接提供沙箱与生产信息:

2014年夏天(31.0版),在 组织对象

从组织限制1中选择Id、IsSandbox

从“新建和更改对象”下的发行说明中:


如果您知道这两个URL,为什么不检查您当前的Url以查看您的位置?我的自定义控制器中的Apex代码如何获取调用它的页面的Url?这将在后端工作,但我的问题在于我的自定义控制器需要确定要调用的后端web服务。我已经考虑了第一个后端web服务,但担心这一点每次刷新沙盒时都需要手动更改。错过此手动更新的代价是阶段/测试数据将在后端投入生产。第二个选项很有趣,但您的状态不稳定。就您所知,这些都是有效的假设吗?请注意,Salesforce根据上下文存储组织ID的方式不同:UserInfo.getOrganizationId()供参考:public Boolean isSandbox(){return URL.getSalesforceBaseUrl().getHost()。左(2).equalsignorecase('cs');}