Salesforce OpenCTIのおためし

OpenCTIを使って、Salesforce外部のシステムからSalesforceのレコードをポップアップさせるサンプルです。

http://www.salesforce.com/us/developer/docs/api_cti/Content/sforce_api_cti_sample_js.htm
に沿って、
http://blogjp.sforce.com/2012/12/post-1889.html
を参考にしながら試します。
外部システムは、localhostに設置します。

# コールセンターの登録

「コールセンター」＝ 連携相手のSalesforce外部システムですので、Salesforceと連携するシステムのURLを登録します。今回は、https://localhost/openctitest.html とします。http://localhost ではダメです。

## XMLファイルを作る

（なぜか）GUIからコールセンターは新規作成できないので、XMLファイルを作る必要があります。http://www.salesforce.com/us/developer/docs/api_cti/Content/sforce_api_cti_call_def_file_sample.htm
からコピペして作りましょう。canvasは使わないので、関連する定義はコメントアウトしておきます。


```xml:callcenter.xml
<!--
     All sections and items whose name value begins with "req" are
     required in a valid call center definition file. The sortOrder
     and label attributes can be changed for all required sections
     and items except reqGeneralInfo, reqInternalName, and
     reqDisplayName, in which only the label attribute can be altered.

	  Note that the value for the reqInternalName item is limited to
     40 alphanumeric characters and must start with an alphabetic
     character. reqInternalName must be unique for all call centers
     that you define.
-->
<callCenter>
   <section sortOrder="0" name="reqGeneralInfo" label="General Information">
    <item sortOrder="0" name="reqInternalName" label="InternalNameAAA">DemoAdapter</item>
    <item sortOrder="1" name="reqDisplayName" label="Display Name">Demo Call Center Adapter</item>
    <item sortOrder="2" name="reqAdapterUrl" label="CTI Adapter URL">https://localhost/openctitest.html</item>
    <item sortOrder="3" name="reqUseApi" label="Use CTI API">true</item>
    <item sortOrder="4" name="reqSoftphoneHeight" label="Softphone Height">300</item>
    <item sortOrder="5" name="reqSoftphoneWidth" label="Softphone Width">500</item>
<!--     <item sortOrder="6" name="reqCanvasNamespace" label="Canvas Namespace">mm</item>
    <item sortOrder="7" name="reqCanvasApiName" label="Canvas API Name">Hello_World</item> -->
   </section>
   <section sortOrder="1" name="reqDialingOptions" label="Dialing Options">
    <item sortOrder="0" name="reqOutsidePrefix" label="Outside Prefix">9</item>
    <item sortOrder="1" name="reqLongDistPrefix" label="Long Distance Prefix">1</item>
    <item sortOrder="2" name="reqInternationalPrefix" label="International Prefix">01</item>
   </section>
</callCenter>
```

## コールセンター定義ファイルのインポート

Salesforceにて カスタマイズ -> コールセンター から「インポート」を押して作った定義ファイルをインポートします。インポートしたらGUIから編集できるようになります。

## コールセンターユーザの追加

インポートしたコールセンター「DemoAdapter」を選択し、「コールセンターユーザの管理」ボタンを押します。
「ユーザの追加」ボタンを押して、ユーザを追加します。

# ローカルWebサーバの準備

https://localhost を立ち上げます。今回試した環境がWin8.1だったんで、IIS8を使いました。お使いの環境でhttpsがホスティングできるようにしてくださいませ。

http://www.pcandtablet.com/windows-8-software/595/how-to-turn-windows-8-to-a-web-server-for-my-testing-purposes.html

オレオレ証明書を作ると、https をバインドできるようになります。

http://www.tama200x.com/blog/?p=786

# ローカルアプリケーション（ただのhtmlファイル）の配置

http://www.salesforce.com/us/developer/docs/api_cti/Content/sforce_api_cti_sample_js.htm を参考に作成して、https://localhost/openctisample.html でアクセスできるよう配置してください。

```html:openctitest.html
<html>
<head>
      <META charset="UTF-8">
      <!-- Imports Open CTI JavaScript library. It should point to a valid Salesforce domain. -->
      <script src="https://ap.salesforce.com/support/api/31.0/interaction.js"></script>
      <script type="text/javascript">
             // Callback of API method: isInConsole
             var isInConsoleCallback = function (response) {
                  // Returns true if method is executed in Salesforce console, false otherwise.
                  if (response.result) {
                      alert('SoftPhone is in Salesforce console.');
                  } else {
                      alert('SoftPhone is not in Salesforce console.');
                  }
              };
              // Invokes API method: isInConsole
              function isInConsole() {
                       sforce.interaction.isInConsole(isInConsoleCallback);
              }
              // Callback of API method: getCallCenterSettings
              var getCallCenterSettingsCallback = function (response) {
                     // Result returns call center settings as a JSON string.
                     if (response.result) {
                            alert(response.result);
                     } else {
                            alert('Error retrieving call center settings ' + response.error);
                     }
               };
               // Invokes API method: getCallCenterSettings
               function getCallCenterSettings() {
                        sforce.interaction.cti.getCallCenterSettings(getCallCenterSettingsCallback);
               }
               // Callback of API method: setSoftphoneHeight
               var setSoftphoneHeightCallback = function (response) {
                        // Returns true if SoftPhone height was set successfully, false otherwise.
               if (response.result) {
                       alert('Setting SoftPhone height to 300px was successful.');
               } else {
                      alert('Setting softphone height failed.');
               }
               };
               // Invokes setSoftphoneHeight API method.
               function setSoftphoneHeight() {
                       sforce.interaction.cti.setSoftphoneHeight(300, setSoftphoneHeightCallback);
               }
               // Callback of API method: getPageInfo
               var getPageInfoCallback = function (response) {
                      if (response.result) {
                             alert(response.result);
                      } else {
                             alert('Error occured while trying to get page info: ' + response.error);
                      }
               }
               // Invokes API method getPageInfo
               function getPageInfo() {
                       sforce.interaction.getPageInfo(getPageInfoCallback);
               }

               function openPaticularRecord() {
                       sforce.interaction.searchAndScreenPop('Stella','','inbound');
                       //sforce.interaction.searchAndScreenPop('(212) 842-5500','','inbound');
               }

              // Callback of API method: inboundCallDemo
              var inboundCallDemoCallback = function (response) {
                     // Result returns call center settings as a JSON string.
                     if (response.result) {
                            alert(response.result);
                     } else {
                            alert('Error retrieving data ' + response.error);
                     }
               };
               // Invokes API method: inboundCallDemo
               function inboundCallDemo() {
                         sforce.interaction.searchAndScreenPop('(212) 842-5500','','inbound',inboundCallDemoCallback);
               }

      </script>
</head>
<body>
      <button onclick="isInConsole();">isInConsole</button></br>
      <button onclick="getCallCenterSettings();">getCallCenterSettings</button></br>
      <button onclick="setSoftphoneHeight();">setSoftphoneHeight(300)</button></br>
      <button onclick="getPageInfo();">getPageInfo</button></br>
      <button onclick="openPaticularRecord();">Stella で検索</button></br>
      <button onclick="inboundCallDemo();">(212) 842-5500から着信</button>
</body>
</html>

```


# ローカル側の確認
https://localhost/openctitest.html をたたきましょう。オレオレSSL証明書なので、ブロックされますが、アクセスできるようにしてください。

![スクリーンショット 2014-09-03 02.52.39.png](https://qiita-image-store.s3.amazonaws.com/0/53358/d7099456-e17d-8d69-ff75-ef2915f3abd2.png)

# Salesforce側の確認

画面左側のサイドバーに https://localhost/openctitest.html
が埋め込まれていたら、うまくいっています。実案件ならソフトウエアフォンが埋まるんだと思います。

![スクリーンショット 2014-09-03 02.56.11.png](https://qiita-image-store.s3.amazonaws.com/0/53358/56bc4179-41a5-a5ab-4d5d-b47f739f114b.png)

## ポップアップさせてみましょう。

「Stella で検索」を押すとStellaを探して1レコードが特定できるなら自動で画面が切り替わります。![スクリーンショット 2014-09-03 02.58.13.png](https://qiita-image-store.s3.amazonaws.com/0/53358/b3ee8d83-a5a6-ab55-bdc0-8e5ba05efc0b.png)

「(212) 842-5500から着信」の場合は、(212) 842-5500のレコードが複数あるので、JSONで返してくれます。実案件では、外部システム側で1レコードに絞り込んで、再度searchAndScreenPopさせるような処理が必要です。

![スクリーンショット 2014-09-03 03.00.19.png](https://qiita-image-store.s3.amazonaws.com/0/53358/c1f8aa1e-de59-4ebf-a621-7728eb0769dd.png)

# まとめ
APIドキュメントのサンプルをなぞっただけですが、実案件ですぐに活用できそうな気持ちになるOpenCTIでした。