如何将Salesforce与Google Maps集成? [英] How do I integrate Salesforce with Google Maps?

查看:312
本文介绍了如何将Salesforce与Google Maps集成?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如何将Salesforce与Google Maps集成?我只是在寻找关于如何...的信息。


  1. 在Salesforce中搜索联系人

  2. 在Google地图上绘制这些图。


  3. 感谢
    ,指向 https://maps.googleapis.com 启用来自Apex的标注

  4. 在设置 - >自定义 - >联系人 - >字段中添加字段位置。类型应该是地理定位。

     公共分享类mapController {
    public String searchText {get; set;}
    public List< Contact>接触{获取; private set;}

    public static final String GEOCODING_URI_BASE ='https://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=';

    //对于本演示的目的,我只能对服务器端的几个地址进行地理编码。实际代码可以使用注释掉的值。
    public static final Integer MAX_CALLOUTS_FROM_APEX = 3; // Limits.getLimitCallouts()

    public mapController(){
    searchText = ApexPages.currentPage()。getParameters()。get('q');

    $ b $ public void find(){
    if(searchText!= null&& searchText.length()> 1){
    List< List< ;&的sObject GT;>结果= [查找:('*'+ searchText +'*')在所有域中返回
    联系人(Id,Name,Email,Account.Name,
    MailingStreet,MailingCity,MailingPostalCode,MailingState,MailingCountry,
    Location__Latitude__s,Location__Longitude__s)
    ];
    contacts =(列表<联系人>)结果[0];
    if(contacts.isEmpty()){
    ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO,'No matches for''+ searchText +''));
    } else {
    serverSideGeocode();
    }
    } else {
    if(contacts!= null){
    contacts.clear();
    }
    ApexPages.addMessage(新的ApexPages.Message(ApexPages.Severity.INFO,'请提供至少2个字符的搜索。'));


    $ b $ public void clearGeocodedData(){
    for(Contact c:contacts){
    c.Location__Latitude__s = c.Location__Longitude__s = null;
    }
    Database.update(contacts,false);
    contacts.clear();
    }

    public String getContactsJson(){
    return JSON.serialize(contacts);
    }
    public String getDebugContactsJson(){
    return JSON.serializePretty(contacts);
    }

    private void serverSideGeocode(){
    List< Contact> contactsToUpdate =新列表<联系人>();
    Http h = new Http();
    HttpRequest req = new HttpRequest();
    req.setMethod('GET');
    req.setTimeout(10000);
    $ b $(联系人c:联系人){
    if((c.Location__Latitude__s == null || c.Location__Longitude__s == null)){
    String address = c.MailingStreet != null? c.MailingStreet +'':''+
    c.MailingCity!= null? c.MailingCity +'':''+
    c.MailingState!= null? c.MailingState +'':''+
    c.MailingPostalCode!= null? c.MailingPostalCode +'':''+
    c.MailingCountry!= null? c.MailingCountry:'';
    if(address!=''){
    req.setEndpoint(GEOCODING_URI_BASE + EncodingUtil.urlEncode(address,'UTF-8'));
    尝试{
    HttpResponse res = h.send(req);
    GResponse gr =(GResponse)JSON.deserialize(res.getBody(),mapController.GResponse.class);
    if(gr.status =='OK'){
    LatLng ll = gr.results [0] .geometry.location;
    c.Location__Latitude__s = ll.lat;
    c.Location__Longitude__s = ll.lng;
    contactsToUpdate.add(c);
    } else {
    ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,''+地址+'的地理编码失败:'+ gr.status));
    }
    } catch(Exception e){
    ApexPages.addMessages(e);
    }
    }
    //如果我们达到了标注限制(并非所有联系人可能已处理),请退出。
    if(Limits.getCallouts()== MAX_CALLOUTS_FROM_APEX){
    break; $!


    $ b if(!contactsToUpdate.isEmpty()){
    Database.update(contactsToUpdate,false); //开发者版本中的某些数据无效(我认为目的)。
    //如果由于j.davis@expressl& t.net不是有效的电子邮件而导致更新失败,我希望其余的成功
    }
    }

    //辅助类 - 查找结果将被分析到的模板。有些字段会被跳过!
    //如果您需要创建完整映射,请访问https://developers.google.com/maps/documentation/geocoding/#Results。
    public class GResponse {
    public String status;
    public GComponents []结果;
    }
    公共类GComponents {
    public String formatted_address;
    public G几何几何;
    }
    公共类GGeometry {
    公共LatLng位置;
    }
    公共类LatLng {
    public Double lat,lng;


    code





     < apex:page controller =mapControllertabStyle =Contactaction ={!find}id =page> ; 
    < head>
    < style>
    div #map_canvas {height:400px; }
    < / style>
    < script type =text / javascriptsrc =https://maps.googleapis.com/maps/api/js?sensor=false>< / script>
    < / head>
    < apex:pageMes​​sages />
    < apex:form id =form>
    < apex:pageBlock id =searchBlock>
    < apex:inputText value ={!searchText}/>
    < apex:commandButton value =Searchaction ={!find}/>
    < p>示例:< a href =/ apex / {!$ CurrentPage.Name}?q = USA>USA< / a> ;,Singapore,Uni (336)222-7000。如果它在全局搜索框中有效,它就会在这里工作。< / p>
    < / apex:pageBlock>
    < apex:pageBlock title =Found {!contacts.size} Contact(s)...rendered ={!NOT(ISNULL(contacts))&& contacts.size> 0} id =resultsBlock>
    < apex:pageBlockButtons location =top>
    < / apex:pageBlockButtons>
    < apex:column headerValue ={!$ ObjectType.Contact.fields.Name.label}>
    < / apex:column>
    < apex:列headerValue =地址>
    {!c.MailingStreet} {!c.MailingCity} {!c.MailingCountry}
    < / apex:column>
    < apex:列值={!c.Account.Name}/>
    {!c.Location__Latitude__s},{!c.Location__Longitude__s}
    < / apex:column>
    < / apex:pageBlockTable>
    < apex:pageBlockSection columns =1id =mapSection>
    < div id =map_canvas/>
    < / apex:pageBlockSection>
    < pre> {!debugContactsJson}< / pre>
    < / apex:pageBlockSection>
    < pre id =log>< / pre>
    < / apex:pageBlock>
    < / apex:form>
    < script type =text / javascript>
    twistSection(document.getElementById('page:form:resultsBlock:debugSection')。childNodes [0] .childNodes [0]); //最初隐藏调试部分

    var contacts = {!contactsJson}; //联系人数据数组,其中一些可能有经纬度信息,有些我们必须对客户端进行地理编码
    var coords = []; //每个联系人的经度/纬度
    var requestCounter = 0;

    var markers = []; //我们固定在地图上的红色东西。
    var balloon = new google.maps.InfoWindow(); //漂浮在标记上的漫画般的气球。

    函数geocodeClientSide(){
    for(var i = 0; i< contacts.length; i ++){
    if(contacts [i] .Location__Latitude__s!= null& amp ;& contacts [i] .Location__Longitude__s!= null){
    coords.push(new google.maps.LatLng(contacts [i] .Location__Latitude__s,contacts [i] .Location__Longitude__s));
    } else {
    ++ requestCounter;
    var address = contacts [i] .MailingStreet +''+ contacts [i] .MailingCity +''+ contacts [i] .MailingCountry;
    var geocoder = new google.maps.Geocoder();
    if(geocoder){
    geocoder.geocode({'address':address},function(results,status){
    if(status == google.maps.GeocoderStatus.OK){
    coords.push(results [0] .geometry.location);
    } else {
    var pTag = document.createElement(p);
    pTag.innerHTML = status ;
    document.getElementById('log')。appendChild(pTag);
    }
    if( - requestCounter == 0){
    drawMap();
    }
    });
    }
    }
    }
    //可能会出现这种情况,所有内容都是在服务器端进行地理编码(或仅从数据库中检索)。
    //所以如果我们幸运的话,就继续绘制地图。
    if(requestCounter == 0){
    drawMap();



    函数drawMap(){
    var mapOptions = {
    center:coords [0],
    zoom:3,
    mapTypeId:google.maps.MapTypeId.ROADMAP
    };
    var map = new google.maps.Map(document.getElementById(map_canvas),mapOptions); (var i = 0; i var marker = new google.maps.Marker({map:map,position:coords [我],标题:contacts [i] .Name,zIndex:i});

    google.maps.event.addListener(marker,'click',function(){
    var index = this.zIndex;
    balloon.content ='< b> '+ contacts [index] .Name +'< / b>< br />'+ contacts [index] .Account.Name +'< br />'+ contacts [index] .Email;
    balloon.open(map,this);
    });
    markers.push(marker);
    }
    }

    geocodeClientSide();
    < / script>
    < / apex:page>


    How do I integrate Salesforce with Google Maps? I'm just looking for information on how to...

    1. Search for contacts in Salesforce
    2. Plot those on a google map.

    解决方案

    EDIT:

    Thanks to tggagne's comment I've realized that people still see this answer. The code that was here is over 2.5 years old. If you want to see it - check the history of edits.

    A lot has changed in the meantime, more mashup examples were created. Not the least of them being "SF Bus Radar" (github, youtube) app by Cory Cowgill (created on Dreamforce'11 I think).

    Nonetheless - here's my updated example with server-side geocoding, new field of type Geolocation and usage of JSON parsers.

    It tries to cache the geocoding results in the contact records. Bear in mind it might not be 'production-ready' (no Google Business API key = as all our requests come out from same pool of Salesforce IP servers there might be error messages). That's why I've left the client-side geocoding too.


    You'll need to make 2 changes in your environment before checking it out:

    1. Add "Remote Site Setting" that points to https://maps.googleapis.com to enable callouts from Apex
    2. Add field "Location" in Setup -> Customize -> Contacts -> fields. Type should be "Geolocation". I've selected display as decimals and precision of 6 decimal places.

      public with sharing class mapController {
      public String searchText {get;set;}
      public List<Contact> contacts{get; private set;}
      
      public static final String GEOCODING_URI_BASE = 'https://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=';
      
      // For purposes of this demo I'll geocode only couple of addresses server-side. Real code can use the commented out value.
      public static final Integer MAX_CALLOUTS_FROM_APEX = 3; // Limits.getLimitCallouts()
      
      public mapController(){
          searchText = ApexPages.currentPage().getParameters().get('q');
      }
      
      public void find() {
          if(searchText != null && searchText.length() > 1){
              List<List<SObject>> results = [FIND :('*' + searchText + '*') IN ALL FIELDS RETURNING 
                  Contact (Id, Name, Email, Account.Name,
                      MailingStreet, MailingCity, MailingPostalCode, MailingState, MailingCountry, 
                      Location__Latitude__s, Location__Longitude__s)
                  ];
              contacts = (List<Contact>)results[0];
              if(contacts.isEmpty()){
                  ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO, 'No matches for "' + searchText + '"'));
              } else {
                  serverSideGeocode();
              }
          } else {
              if(contacts != null) {
                  contacts.clear();
              }
              ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO, 'Please provide at least 2 characters for the search.'));
          }
      }
      
      public void clearGeocodedData(){
          for(Contact c : contacts){
              c.Location__Latitude__s = c.Location__Longitude__s = null;
          }
          Database.update(contacts, false);
          contacts.clear();
      }
      
      public String getContactsJson(){
          return JSON.serialize(contacts);
      }
      public String getDebugContactsJson(){
          return JSON.serializePretty(contacts);
      }
      
      private void serverSideGeocode(){
          List<Contact> contactsToUpdate = new List<Contact>();
          Http h = new Http();  
          HttpRequest req = new HttpRequest();
          req.setMethod('GET'); 
          req.setTimeout(10000);
      
          for(Contact c : contacts){
              if((c.Location__Latitude__s == null || c.Location__Longitude__s == null)){
                  String address = c.MailingStreet != null ? c.MailingStreet + ' ' : '' +
                      c.MailingCity != null ? c.MailingCity + ' ' : '' +
                      c.MailingState != null ? c.MailingState + ' ' : '' +
                      c.MailingPostalCode != null ? c.MailingPostalCode + ' ' : '' +
                      c.MailingCountry != null ? c.MailingCountry : '';
                  if(address != ''){
                      req.setEndpoint(GEOCODING_URI_BASE + EncodingUtil.urlEncode(address, 'UTF-8'));
                      try{
                          HttpResponse res = h.send(req);
                          GResponse gr = (GResponse) JSON.deserialize(res.getBody(), mapController.GResponse.class);
                          if(gr.status == 'OK'){
                              LatLng ll = gr.results[0].geometry.location;
                              c.Location__Latitude__s = ll.lat;
                              c.Location__Longitude__s = ll.lng;
                              contactsToUpdate.add(c);
                          } else {
                              ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Geocoding of "' + address + '" failed:' + gr.status));
                          }
                      }catch(Exception e){
                          ApexPages.addMessages(e);
                      }
                  }
                  // Bail out if we've reached limit of callouts (not all contacts might have been processed).
                  if(Limits.getCallouts() == MAX_CALLOUTS_FROM_APEX) {
                      break;
                  }
              }
          }
          if(!contactsToUpdate.isEmpty()) {
              Database.update(contactsToUpdate, false); // some data in Developer editions is invalid (on purpose I think).
              // If update fails because "j.davis@expressl&amp;t.net" is not a valid Email, I want the rest to succeed
          }
      }
      
      // Helper class - template into which results of lookup will be parsed. Some fields are skipped!
      // Visit https://developers.google.com/maps/documentation/geocoding/#Results if you need to create full mapping.
      public class GResponse{
          public String status;
          public GComponents[] results;
      }
      public class GComponents{
         public String formatted_address;
         public GGeometry geometry;
      }
      public class GGeometry {
          public LatLng location;
      }
      public class LatLng{
          public Double lat, lng;
      }
      }
      


    <apex:page controller="mapController" tabStyle="Contact" action="{!find}" id="page">
        <head>
            <style>
                div #map_canvas { height: 400px; }
            </style>
            <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
        </head>
        <apex:sectionHeader title="Hello StackOverflow!" subtitle="Contact full text search + Google Maps integration" />
        <apex:pageMessages />
        <apex:form id="form">
            <apex:pageBlock id="searchBlock">
                <apex:inputText value="{!searchText}" />
                <apex:commandButton value="Search" action="{!find}"/>
                <p>Examples: <a href="/apex/{!$CurrentPage.Name}?q=USA">"USA"</a>, "Singapore", "Uni", "(336) 222-7000". If it works in the global search box, it will work here.</p>
            </apex:pageBlock>
            <apex:pageBlock title="Found {!contacts.size} Contact(s)..." rendered="{!NOT(ISNULL(contacts)) && contacts.size > 0}" id="resultsBlock">
                <apex:pageBlockButtons location="top">
                    <apex:commandButton value="Clear cached locations" title="Click if you want to set 'null' as geolocation info for all these contacts" action="{!clearGeocodedData}" />
                </apex:pageBlockButtons>
                <apex:pageBlockTable value="{!contacts}" var="c" id="contacts">
                    <apex:column headerValue="{!$ObjectType.Contact.fields.Name.label}">
                        <apex:outputLink value="../{!c.Id}">{!c.Name}</apex:outputLink>
                    </apex:column>
                    <apex:column headerValue="Address">
                        {!c.MailingStreet} {!c.MailingCity} {!c.MailingCountry}
                    </apex:column>
                    <apex:column value="{!c.Account.Name}"/>
                    <apex:column headerValue="Location (retrieved from DB or geocoded server-side)">
                        {!c.Location__Latitude__s}, {!c.Location__Longitude__s}
                    </apex:column>
                </apex:pageBlockTable>
                <apex:pageBlockSection columns="1" id="mapSection">
                    <div id="map_canvas" />
                </apex:pageBlockSection>
                <apex:pageBlockSection title="Click to show/hide what was geocoded server-side and passed to JS for further manipulation" columns="1" id="debugSection">
                    <pre>{!debugContactsJson}</pre>
                </apex:pageBlockSection>
                <pre id="log"></pre>
            </apex:pageBlock>
        </apex:form>
        <script type="text/javascript">
        twistSection(document.getElementById('page:form:resultsBlock:debugSection').childNodes[0].childNodes[0]); // initially hide the debug section
    
        var contacts = {!contactsJson};    // Array of contact data, some of them might have lat/long info, some we'll have to geocode client side
        var coords = [];                   // Just the latitude/longitude for each contact
        var requestCounter = 0;
    
        var markers = [];                  // Red things we pin to the map.
        var balloon = new google.maps.InfoWindow(); // Comic-like baloon that floats over markers.
    
        function geocodeClientSide() {
            for(var i = 0; i < contacts.length; i++) {
                if(contacts[i].Location__Latitude__s != null && contacts[i].Location__Longitude__s != null) {
                    coords.push(new google.maps.LatLng(contacts[i].Location__Latitude__s, contacts[i].Location__Longitude__s));
                } else {
                    ++requestCounter;
                    var address = contacts[i].MailingStreet + ' ' + contacts[i].MailingCity + ' ' + contacts[i].MailingCountry;
                    var geocoder = new google.maps.Geocoder();
                    if (geocoder) {
                        geocoder.geocode({'address':address}, function (results, status) {
                            if (status == google.maps.GeocoderStatus.OK) {
                                coords.push(results[0].geometry.location);
                            } else {
                                var pTag = document.createElement("p");
                                pTag.innerHTML = status;
                                document.getElementById('log').appendChild(pTag);
                            }
                            if(--requestCounter == 0) {
                                drawMap();
                            }
                        });
                    }
                }
            }
            // It could be the case that all was geocoded on server side (or simply retrieved from database).
            // So if we're lucky - just proceed to drawing the map.
            if(requestCounter == 0) {
                drawMap();
            }
        }
    
        function drawMap(){
            var mapOptions = {
                center: coords[0],
                zoom: 3,
                mapTypeId: google.maps.MapTypeId.ROADMAP
            };
            var map = new google.maps.Map(document.getElementById("map_canvas"),  mapOptions);
    
            for(var i = 0; i < coords.length; ++i){
                var marker = new google.maps.Marker({map: map, position: coords[i], title:contacts[i].Name, zIndex:i});
    
                google.maps.event.addListener(marker, 'click', function() {
                    var index = this.zIndex;
                    balloon.content = '<b>'+contacts[index].Name + '</b><br/>' + contacts[index].Account.Name + '<br/>' + contacts[index].Email;
                    balloon.open(map,this);
                });
                markers.push(marker);
            }
        }
    
        geocodeClientSide();
        </script>
    </apex:page>
    

    这篇关于如何将Salesforce与Google Maps集成?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆