Quantcast
Channel: web pakun
Viewing all 247 articles
Browse latest View live

Salesforceの最新APIのWSC(Web Service Connector)のjarファイルをコンパイルして使用する

$
0
0

以前のエントリ「Salesforceに接続して、オブジェクト加工等を行うEclipseプロジェクトのテンプレート」でご紹介しましたが、SalesforceのAPIをWebService経由でJavaから呼び出すには、Salesforceから取得した WSDLファイルが必要です。

「WSDLファイル」とは、Webサービスの呼び出し情報を定義したXMLファイルで、このファイルからJavaなどのプログラミング言語に応じたクラスを生成して、 そのクラスを使用してAPIの呼び出しを行います。

クラス群の生成は、

“C:\Program Files\Java\jdk1.7.0_79\bin\java” -classpath wsc-23.jar com.sforce.ws.tools.wsdlc partner.wsdl partner.jar

のようなコマンドで生成し、呼び出すAPIごとに生成してjarにまとめ、「enterprise.jar」「partner.jar」「metadata.jar」「tooling.jar」 などを作成して利用します。

さて、上記のコマンドで「wsc-23.jar」とあるのが、クラスファイルを生成するのに必要なライブラリなのですが、 23とはいささか古いですよね。

Salesforceは、常にバージョンアップが行われていて、このエントリを書いた2016年12月はAPIバージョンは38が最新です。 その間に、新しいオブジェクトのタイプが追加されたり、構造が変わったりしているので、WSDLファイルに記述されている内容も変化しています。

つまり、最新のバージョンに対応したwscファイルでクラスファイルを生成しなければ、使えない機能があったり、APIを呼び出しても、エラーに なったりすることがあるということです。

そのため、最新のAPIバージョンでwscを生成する手順をメモしておきます。

 

最新のwsc.jarの作り方

wscのソースファイルをダウンロードしてくる

まずは、最新のバージョンに対応したソースファイルをダウンロードします。 最新のwscは以下のページで公開されています。

https://github.com/forcedotcom/wsc

ここから、gitにてソースを自分のPCにダウンロードします。

Mavenプロジェクトを作成

 

上図の赤囲みのところに、gitのURLが掲載されていますので、それをコピーしてきましょう。

https://github.com/forcedotcom/wsc.git

ダウンロードすると、以下のようなディレクトリ構成になります。 srcフォルダ配下のjavaソースと、pom.xmlは、後ほど使用します。

Mavenプロジェクトを作成

 

Mavenでコンパイルする

落としてきたソースをEclipseのMavenプロジェクトでコンパイルし、jarファイルを作りましょう。さきほど、「pom.xml」というファイルがありましたが、これは、Mavenを使って「コンパイル→jarへのまとめ」を行う設定ファイルです。

そのために、EclipseでMavenプロジェクトを作成しました。

Mavenプロジェクトを作成

 

上記の手順でシンプルなMavenプロジェクトを作ると、以下のようなディレクトリ構成のプロジェクトができます。この、src配下とpom.xmlをgitからダウンロードしたものに置き換えます。

完成したMavenプロジェクト

 

ここまできたら、いよいよコンパイルします。プロジェクトを右クリックし、「Maven build..」を選んで、Goals(ゴール)を「package」に設定します。「Skip Tests」にもチェックを入れておくと良いでしょう。

完成したMavenプロジェクト

 

上記のようなjarファイル群ができていたらOKです。使用するのは、「force-wsc-38.0.4-uber.jar」になりますので、これができていたらOKです。

 

いくつか起こりえるエラー

まぁ、すんなり行けばいいですが、それは、何度もエラーが出るのが世の常。私もいくつかエラーでました。同じことをする方も引っかかるかもしれないので、メモしておきます。

 

Mavenプロジェクトのコンパイルエラー

MavenプロジェクトでMaven buildすると以下のようなエラーが出る場合があります。

[ERROR] COMPILATION ERROR : 
[INFO] -------------------------------------------------------------
[ERROR] No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?
[INFO] 1 error
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.272 s
[INFO] Finished at: 2016-12-01T14:01:03+09:00
[INFO] Final Memory: 7M/17M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project wsc38: Compilation failure
[ERROR] No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?
[ERROR] -> [Help 1]

これは、「コンパイルできないけど、jdkじゃないんじゃないの?」といわれていますね。私の場合は、Eclipse出指定されているjavaのJAVA_HOME\bin配下にjavac.exeがない「jre」を指定していたためでした。同じエラーが出る方は、ちゃんとjdkを指定していて、javacが含まれているかを確認してみましょう。

 

Mavenプロジェクトの最後のパッケージングエラー

Maven buildが最後の最後でエラーになっています。私は、「force-wsc-38.0.4-uber.jar」が出来ていたのでよしとしましたが。。。

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 02:30 min
[INFO] Finished at: 2016-12-01T14:25:03+09:00
[INFO] Final Memory: 23M/367M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-gpg-plugin:1.2:sign (sign-artifacts) on project force-wsc: Cannot obtain passphrase in batch mode -> [Help 1]

なんだか、最後のゴールでこけたみたいですが、すみません。良く調査していないです。回避方法分かった方は教えてください。。。

 


SalesforceのSoqlでlike句が使えるテキスト項目の種類と、使えない場合の代替方法

$
0
0

Salesforceでは、Like句を使って、selectできるデータタイプが限定されています。

SELECT Id, Name from Lead WHERE qTextAreaRitch__c Like ‘aa%’

みたいなsoql文を使って検索すると、

[object Object]: SELECT Id, Name from Lead WHERE qTextAreaRitch__c Like ‘aa%’ ^ ERROR at Row:1:Column:33 field ‘qTextAreaRitch__c’ can not be filtered in query call

といったエラーが出て、検索結果が返ってきません。では、どのデータ型が大丈夫で、どれが大丈夫でないかを表にしてみます。

データ型 データ型詳細 サンプルで作成したカラム名 Like句を使用可能か
テキスト テキスト(255) qText__c
テキストエリア テキストエリア(255) qTextArea__c
テキストエリア (リッチ) リッチテキストエリア(32768) qTextAreaRitch__c ×
ロングテキストエリア ロングテキストエリア(32768) qLongText__c ×

後ろの3つが日本語で「テキストエリア」となっていて分かりにくいのですが、実際には 最初の2つは文字列型で、項目を作成するときに指定できる文字数が255文字以内となっていて、Like句も使用可能です。 後の2つはテキストエリア型で、256文字以上の文字数しか指定できません。Like句も使用不可能です。

ただ、多くの文字が入力される可能性のある項目にはやはり255文字以上を指定したいですよね。

 

テキストエリア型でLike句のような振る舞いをさせる方法

String strKey = ‘ccc*’; List> arrayOfArray = [FIND :strKey IN ALL FIELDS RETURNING Lead(Id, Name)]; List arrayOfAccount = (List)arrayOfArray[0];

FIND {ccc*} IN ALL FIELDS RETURNING Lead(Id, Name)

でSOSL文を使います。

グローバル検索と同じ振る舞いになりますので、インデックスが作られるまで検索対象にならなかったり、検索対象のデータ型のすべての項目が対象になるなど、少しクセはありますが、テキストエリアを含めたカラムが対象になるのは便利だと思います。

特定のカラムに検索対象の文字列が含まれているような振る舞いにするには、検索結果のレコード配列をさらにcontainsで見るなどの工夫をすればいいかもしれませんね。

もうひとつの方法は、レコードを取得した後で必要な項目に対して文字列が含まれているかを判断する方法です。

以下のようなapexコードを書けばいいでしょう。

List leads = new List();
for(Lead lead : [SELECT Id, Name, qText__c, qTextArea__c, qTextAreaRitch__c, qLongText__c FROM Lead]) {
    
    if(lead.qTextAreaRitch__c != '' && lead.qTextAreaRitch__c != null){
        if(lead.qTextAreaRitch__c.contains('ccc')) {
            leads.add(lead);
            system.debug('★added');
        }
    }
}

nullと、空文字の判定をした後出ないと、null pointerのエラーが出る場合があるので、気をつけましょう。

TeraTermでproxy(プロキシサーバ)経由のssh接続を行う設定(ssh over http)

$
0
0

以前、Puttyを利用してproxy経由で外部のサーバにssh接続する方法をお伝えしましたが、今回はTeraTermを使ってみたいと思います。

 

やりたいこと

これで何が実現できるかというと、社内など、proxyサーバを通してしか外部に出ることができない環境で、sshターミナルを使いたい場合があります。

当然のことながら、通常sshで使用する22番ポートは通信が許可されていないため、sshで外部サーバに接続することは出来ません。

そんな場合、sshのターミナルソフトで、プロキシ設定を行ったうえで接続するようにすれば、そのサーバ経由でssh接続されるので、外部のサーバにもつなげるというわけです。

なお、別の記事(ODBCやJDBCからレンタルサーバのDBにSSH経由で接続する方法(ポートフォワード機能))でもご紹介しましたが、sshにはポートフォアードというシンプルだけど強力な機能があるので、これと組み合わせれば、どんな通信でも行うことができます。

 

TeraTermでのプロキシ設定とssh接続の方法

はじめにTeraTermを起動したら、接続先をきくダイアログが開きますが「キャンセル」を押して、閉じます。

その後、メニューの「設定」→「プロキシ」から、プロキシの設定ダイアログを開きます。

image

 

すると以下のようなダイアログが開きますので、前もってメモしておいたプロキシ・サーバの情報を入力します。

image

 

入力したら、「OK」を押して、いよいよ接続です。

ここからは通常の接続をすればOKですので、「ファイル」→「新しい接続」から以下のような接続ダイアログを開いて接続します。

image

 

image

 

salesforceのSOQLで、削除済み、マージ済みのレコードを取得する

$
0
0

salesforceでレコードを削除したり、マージしたりすると、削除されたレコード、マージされて無くなったレコードはゴミ箱に入ります。

通常、SOQLではゴミ箱に入っているレコードは検索対象にならないのですが、以下のようにALL ROWS句を使うと、ゴミ箱も含むすべてのレコードも検索対象となります。なお、ゴミ箱内のレコードを指定するWhere条件には、「IsDeleted = true」を使用します。

System.assertEquals(2, [SELECT COUNT() FROM Contact WHERE AccountId = a.Id ALL ROWS]);

↑ ↑ ↑ 参考(Querying All Records with a SOQL Statement)

なお、ALL ROWSを使ったSOQLはAPEXコード内か、SOAP APIなどのqueryAll()メソッド内で有効で、開発者コンソールから直接SOQLを投げるとエラーになってしまいます。

 

画面からSOQLを指定して簡単に確認するには

そのため、開発者コンソールからSOQLをたたいて簡単に確認したいなーというときには試せません。

そんなときには以前紹介した、Salesforce Workbench(Salesforceのデータを検索・確認できるGUIツール① WorkBench)を使うとクエリの結果に「ゴミ箱のデータを含む/含まない」の指定が画面からできて、便利です。

workbench

 

Workbenchにログインして、画面上部のメニューから「queries」→「SOQL Query」と進むと上記ののような画面になります。

この画面の中央部のテキストエリアにSOQLを入力して「Query」ボタンを押せば結果が表示されるのですが、その結果にゴミ箱およびアーカイブされたデータ(IsDeleted=true または IsArchived=true)のデータも含めるには、「Deleted and archived records:」で「Include」にチェックを入れておきます。

salesforceでマージ後、どのレコードにマージされたのかをSOQLで確認する方法

$
0
0

Salesforceでは、重複するリード(Lead)や取引先責任者(Contact)を同士をマージ(Merge)して一つのレコードにすることができます。
※取引先責任者の場合は同じ取引先属している取引先責任者同士でしかマージできない。

マージするには、複数のレコードを選択して、以下のような画面で、マスタとなるレコード(メインになるレコードで、基本的にはこのレコードに寄せることで複数のレコードを一つにするが、それぞれの項目ごとにどのレコードの値を活かすかは指定可能)を決めます。

merge

 

上記でマスタレコードとしたレコードが残るのですが、マージされたレコードはどうなるかというと、IsDeletedフラグがtrueになって、ゴミ箱に行きます。そして、基本的には15日程度経った後に、完全に物理削除されることになるわけです。

で、このゴミ箱に入ったデータをSOQL等で覗いてみると面白いことが分かります。「MasterRecordId」という項目に、統合されて残ったマスタのレコードのSalesforceIdが入っているのです。

つまり、この項目を確認すれば、「マージされたレコードが、どのレコード(マージ先)にマージされたのか」が分かるというわけです。

そのため、マージされてゴミ箱に行ったデータを確認するときには、

SELECT Id FROM Contact WHERE isDeleted=true and masterRecordId != null 
   AND SystemModstamp > 2006-01-01T23:01:01+01:00

↑ ↑ ↑ 参考(merge())

といったSOQLで見つけることができます。(ただし、開発者コンソールとかからでは確認できず、Apex等を使う必要があるので、簡単に確認する方法については、この記事「salesforceのSOQLで、削除済み、マージ済みのレコードを取得する」を参考にしてください。)

 

実際に確認してみる

マージ前とマージ後の2レコードを比較してみた図

merge

 

上記のように、マージ後のデータには「MaterRecordId」にオブジェクトIdが入っていることが分かります。

ただし、少し覚えておきたいのは、ゴミ箱から復元すると、この項目の値は「空」になってしまいますが、マージ先のデータは元に戻るわけではないため、「どのレコードにマージされたか」が分からなくなってしまうことです。

SalesforceのApexメソッド、Database.query()とDatabase.getQueryLocator()の違いとそれぞれの使いどころ

$
0
0

Salesforceでデータのセレクト結果を返すメソッドに2種類あり、どういうときに使い分けた方が良いのかが「あやふや」だったので調査したことをまとめておきます。

 

Database.Query()とDatabase.getQueryLocator()の違い

 

Database.Query()・・・このメソッドは、実行時に動的に生成したSOQLで検索を行いたいときに使用します。最大50,000件のレコードを取得することができます。もし、BatchApexなどで使用しても、50,000件以上処理することは出来ません。以下のような例でSOQLを動的に組み立てられます。

String fieldName = ',Name,Email';
String dynQuery = 'select Id ' + fieldName + ' From Account';
Database.query(dynQuery);

 

Database.getQueryLocator()・・・ApexBatchとVisualForceページで使用されることが多いですが、使う場所によって扱える件数が異なります。ApexBatchのなかで使用すると、最大5,000万件までのデータを扱うことができます。ただし、一回でまとめて取ってくるわけではなく、指定したバッチサイズの件数(デフォルト200件)ごとに取ってきて、それを繰り返しで処理します。データベースでいうところのカーソルのフェッチみたいな仕組みをイメージすると良いかもしれません。一回で取得する件数を抑えながらも、最終的には大量のデータを扱うことができるので、Batch Apexの処理内で使われるのは納得ですよね。

もうひとつの使いどころは、StandardSetControllerを使ったVisualForcePageで、主にページング処理を実現するのに使用されます。ここで使用するときには、取得できる最大の件数は10,000件に制限されます。

 

VisualForcePageでの使用イメージ

ここで、VisualForcePageのページング処理での使用イメージを載せておきます。

StandardSetControllerのコンストラクタは以下の2種類を持っています。

前者はsObjectのリストを渡す形式、後者はQueryLocatorを渡す形式です。

sObjectのリストを渡す形式

List accountList = [SELECT Name FROM Account LIMIT 20];
ApexPages.StandardSetController ssc = new ApexPages.StandardSetController(accountList);

 

QueryLocatorを渡す形式

ApexPages.StandardSetController ssc = 
new ApexPages.StandardSetController(Database.getQueryLocator([SELECT Name,CloseDate FROM Opportunity]));

さて、StandardSetController のインスタンス化の際に受け取ることの出来るレコード数は10,000件に制限されています。ただし10,000件以上のレコードがHitして、コンストラクタに渡ったときの振る舞いは両者で異なります。

前者のsObjectのリストを渡したときには10,000件でレコードが切り捨てられ、エラーは出ません。しかし、後者のQueryLocatorの場合は、10,001件以上だとエラーになります。(Too many query locator rows)。

なお、ApexではStandardSetControllerを使用することで簡単にページネーション機能を実装することができますが、大量な件数を表示する場合は、ページのプロパティの中に、readOnly=trueを設定します。これで、通常は1000件までのレコード表示が50,000件まで行えるようになります。(でも、上で述べたように、QueryLocatorの場合は、10,001件以上だとエラーになります。)

 

違いを表にまとめると、、、

Database.query() Database.getQueryLocator()
50,000レコードまで扱える 10,000レコードまで扱える
Batch Apexで使ったとしたら、レコード数は50,000レコードまでに制限される Batch Apexで使ったとしたら、レコード数は5千万レコードまで扱える
VFページでread onlyを使わないのであればこちらを使う。 VFページでread onlyを使うのであればこちらを使う。

のようになると思います。

WordPressの記事中(目次下)に広告を挿入する方法

$
0
0

WordPressの記事の中に広告を挿入するにはいくつかの方法があります。

記事を書くたびにその中に広告のタグを入れればいいのですが、そうしてしまうと、広告を貼り換えたいときや、位置をずらしたりしたいときに、すべての記事を編集する必要があるので、大変ですよね。

そうならないようにするには、Wordpressのテーマを編集して、タイトル下や記事後に入れるか、記事内に目次を挿入する「Table of Contents Plus」のようなプラグインを編集することで実現できます。

今回はそのような方法をまとめておきます。(随時追加予定)

 

テーマファイルを編集して実現する方法

テーマのソースファイルは、「<Wordpressインストールディレクトリ>/wp-content/themes/<テーマのディレクトリ>」にあります。FTPソフトやサーバファイルのエクスプローラで見つけることができると思いますので、変更の方法は、そのファイルを編集して、再アップロードすることになります。

そのテーマファイルの中で、記事投稿を表示しているのは「single.php」になりますので、以下の「テーマファイルを編集して実現する方法」では、このファイルを編集していきましょう。

 

タイトル下に挿入する

タイトル下に挿入するには「single.php」の中で、タイトルを表示している箇所を見つけなければいけません。「single.php」を検索して「the_title()」という関数があるところを見つけます。この関数でタイトルが表示されますので、その後ろに広告のコードを貼り付けると、タイトル下に広告が表示されるようになります。

アド

 

アド表示

 

記事下に挿入する

記事下の場合は、記事を表示している関数の部分を探します。「the_content()」の部分です。この領域の下にコードを貼り付けると、記事下に広告が表示されるようになります。

記事下アド

 

プラグインファイルを編集して実現する方法

各プラグインのソースファイルは、「<Wordpressインストールディレクトリ>/wp-content/plugins/<各プラグインのディレクトリ>」にあります。

そのディレクトリにあるファイルの中で、編集しないといけないのはプラグインによって異なりますので、それぞれ記述します。

 

「Table of Contents Plus」で目次下に挿入する

「「Table of Contents Plus」」は記事に目次を自動で表示してくれるプラグインですが、それを利用して、目次下に一律で広告を表示する方法です。

「wp-content/plugins/table-of-contents-plus」に「toc.php」がありますので、それをテキストエディタで開きます。

その中で「

    」という文字列を検索します。これが、目次を挿入している箇所になります。

    目次下アド

     

NPO・NGOの広報/情報発信を資金なし、人なしでも解決する方法を考える

$
0
0

普段関わっているNPOの資金難から、もっと世間への認知度をあげようということで数カ月前から取り組みをしています。

普段はそのNPOの職員ではなく一会員として完全なボランティアで活動しているのですが、やはり活動するには資金が必要です。資金といってもNPOという立場上、非営利ですのでその資金源は限定されています。つまり①助成金 ②会員費 ③寄付です。
ここでは詳しい説明は省きますが、いずれも実績と成果(社会的な貢献)が求められます。しかしなんといってもそのことを知ってもらわなくては始まらないし共感も何もないということで“認知度アップ”=知ってもらうことにたどり着いたわけです。

ではどうするのか?日本では“プロボノ”として知られますが、自分の得意な分野・専門分野で貢献するのです。日本では「ボランティア」というと特別な感じがするのですが、欧米ではボランティアはごく一般的なことです。“できる人ができることをする”のが基本なので、日本のように取り立てて注目もされないですしね。
そこで私はIT系の知識とアフリカでのボランティア、アフリカでの生活・子育ての経験をもとにこの分野でサポートすることにしました。

SNS、ホームページを充実させよう

世間にはいいことやっているのにまったく知られていないNPOやNGOは多くあります。基本的には社会問題を解決するために活動しているので、私達の生活に身近なはずなのですが。。。ということはサポートを必要とする人にアプローチできていないことと同じじゃないか!
よい行いは必ず評価されるとはいっても、必要なときに必要なサポートができなければ、意味ないわけでミッションを掲げても達成されないことになります。

情報発信とアプローチの方法

経験上、問題解決の第一歩は“知ること”です。つまり情報を持つということにつながります。
試みとしてまず考えたのがSNSとWebサイト(ホームページ)の充実を図ることです。これらは、認知度を上げるには最適な方法ですよね。「情報を発信する」というのは知ってもらう、関心をもってもらうということ。
今は大抵の人がスマートフォンを持っているし、情報も連絡もここからのものが多いという潮流を考えてどんどん情報を発信していこう!と、早速行動することに。

目標を少しだけ紹介すると、

  1. SNSはすでにあるので、ここから拡散とホームページへのアクセスを増やす。
  2. 情報の発信を頻繁に行う。
  3. 顔の見える活動をする。

ことです。

組織を知り、活動に応じた見せ方

しかし、ここで問題が発生。そもそもNPOやNGOのホームページはまずきちんとした組織であることの証明、 活動を通じてミッションに共感してもらうことが前提となっています。そう②の情報の発信を頻繁に行う作りではなく、Fixのものが多いこと。
事業の内容やミッションはそうコロコロと変わるものではないですし。。。

そしてこれはNPOやNGOごとのミッションにも関わるので一概には言えませんが、必ずしも実績や成果が目にみえる「もの」や「事」ではないということと、成果のは短期、中期、長期のものがあるということ。
特に具体的なプロジェクトを持っていない、物を支援しない等の活動ではやはりアピール度が低いこと。さらに啓蒙、アドボカシー、ネットワーク形成のような人の考えや制度、教育などは長期的な活動でしか成果が計れないことです。③の顔の見える活動はすなわちカタチとして目にみえる活動ということ。

んー、この不利な条件がそろってる。どうしよう。。。それに加えて資金難。予算をたくさん使うわけにもいかないし。

負担の少ない「フリー」「役割分担」で解決

ここは基本に立ち返って考えよう。「できる人ができることをする」こと。

役割分担で負荷を分散する

そこで考えたのが、関わるNPOの1事業のミッションや活動につながる経験や感じたことをブログ形式で情報発信すること。幸いNPOのイベント企画もしているので、

  • イベント開催の感想や報告を公開する。
  • ミッション達成に関わる ちょっとした情報の公開を一般向けにする。

さらに個々に関わるボランティアの人が情報を持ち寄ることで 1人ひとりの負担を小さくしようと考えました。しかもWeb上でできるので場所と時間を選ばないメリットもあります。これが「役割分担」です。
これなら②の頻繁な情報発信と③の顔の見える(やっていることがわかる)活動も同時に行えるわけです。

資金をかけずに「フリー」を活用する

次に低予算で、あわよくば資金をかけずにSNSとWebサイトの充実を図ること。もともと資金難から始めた企画だしね。

最近はフリーでいろいろなことができるので、基本資金をかけずにやることを前提に考えるとオープンソースのプラットフォームWordprssを使用して1事業だけのサイトを作ることにしました。
WordPressはオープンソースではメジャーだし、その分プラグイン機能も多いとのねらいから採用。メジャーな分、扱いも簡単にできるので特定の人だけではなく、一般のボランティアやインターンでも更新や運用をしやすく(扱いやすく)するためです。

手間がかかるとやること自体億劫になりますし、作業を分散(役割分担)するには“できる”環境を作ってあげればいいわけです。できることが多くなれば、やれる人も多くなるので結果、ボランティア候補も多くなるはず。。。
まあ、完成度は他力本願になってしまいますがそこはボランティアとしてのデメリットになります。

余談ですがこれってインターンがやることで、すごく勉強になると思います。実際に何かプロジェクトに参加することも経験としてよいですが、実際のNPO、NGOの活動は見えないところでの活動(仕事)が組織を支えていることが多いからです。
プロジェクトに参加することは最終的にできあがったイベントに参加するだけです。その前には交渉、調整、段取りなどの実務を積み上げないとプロジェクトにはなりません。それを知ればボランティアの本当の姿、意味についての気づきが多いと思いますよ。

では、次回はいよいよ実践です。


LineのMessaging(Push)APIを使ってWebサービスを作る(環境構築編)

$
0
0

LineのMessagingAPIを使うと、決められた言葉に自動で反応するBotやお客様への一斉配信などが行えるので、ビジネス・シーンでも利用範囲は大きいと思います。

今回はその中でもPushAPIを使ったメッセージ配信を試してみましたので、その過程をご紹介します。

 

利用料金

今回私が試してみたのは「Developer Trial」で、メッセージを受け取ってから一定時間の間に返信することの出来る「Reply API」と能動的なメッセージ配信に使える「Push API」の両方を無料で使うことができます。

ただし、友達に追加できる人数は50人に限定されています。

それ以上の人数に配信する場合には、プロなどの適切なプランを選択する必要がありますが、時期によって条件も変わると思いますので、詳しくは公式ページで確認してください。

Line料金

 

各種アカウント作成

Lineアカウントの作成

MessagingAPIを使うには、まず、Lineのアカウントが必要です。

持っていない人はスマホにLineアプリを入れるなどして作成してください。

作成したら、スマホのLineアプリの設定で「アカウント」→「メールアドレス登録」が「登録完了」になっていて、「ログイン許可」にチェックがあることを確認しておきます。

 

Developer Trialの申込

Lineのアカウントがあることを確認したら、改めて以下のリンクから「Developer Trial」を申し込みましょう。

https://business.line.me/ja/services/bot

Line料金

 

「Developer Trialを始める」ボタンを押すと、以下のログインダイアログが出ます。

Line料金

 

初めてログインするブラウザでは本人確認が必要なので、Lineに番号が届くはずです。

それを入力すると、続行できます。

続行したら、ビジネスアカウントのマネージャの作成が行われます。

ビジネスアカウントは、Lineアカウントとは別の、「Line@」という種類のアカウントを複数持つことができ、マネージャアカウントで管理します。

Line料金

 

マネージャアカウントの作成が終わったら、ひとつのビジネスアカウント(Line@アカウント)を作成します。

アイコンをアップロードし、名前を入力しましょう。

Line料金

 

Line料金

 

できたら、上記の画面で「LINE@MANAGERへ」のボタンを押すと、作成したLine@アカウントの管理画面にいけます。

Line@アカウントの設定

では、Lineメッセージを送信するのに必要な設定を行っていきましょう。

はじめにAPI利用を有効にします。

下記の画面の「Bot設定」で「APIを利用する」ボタンを押します。

Line料金

 

下記のような注意書きが出ますので、よく読んで先に進みましょう。

LINE DevelopersでのChannel設定が必要なようですね。

Line料金

 

API利用を有効にすると以下のような画面になります。

さらに、Webhook送信を「利用する」に変更してください。

このWebhook送信は、このアカウント(Bot)に対して友達申請やメッセージの送信が行われた際に、そのURLに対して、Line側からJSONがPOSTされます。

このJSONから友達になってくれたユーザのMID(ユーザID)などを取得できたり、返信のための情報を取得してWebサービスを作っていくことになりますので、外部に公開されたサーバにWebhook用のプログラムを作って配置し、そこを指定するようにします。(別の記事で詳しく解説します。)

Line料金

 

Webhookを有効にしたら、「LINE Develiper」に移動します。上記のリンクから行くと行きやすいでしょう。

「LINE Develiper」側では、実際のWebhookのURLを設定したり、先ほど出てきたChannelを有効にしたりします。

Webhookはプログラムを作る必要があるので、今はひとまず、Channelを有効にするために、「Channel Access Token」の「ISSUE」ボタンを押しましょう。

すると、「Channel Access Token」が生成されます。(APIの呼び出しに必要なので、覚えておきましょう。)

Line料金

 

TwilioのSMS送信APIの使い方(準備・環境構築編)

$
0
0

Twilioは、スマホなどの携帯機器に対して、音声応答を行ったり、SMS(ショート・メッセージ)を送信したりすることのできるAPIを提供しています。

世界では様々なキャリアや携帯機器が使われていて、そのすべてに対応するとなると非常に大きな工数が必要ですが、それらの環境の違いについてはTwilioが吸収してくれるので、

我々技術者やサービス提供者は、少ない工数で世界のほとんどの携帯機器に音声やメッセージの配信を行うことが可能になります。

そんなTwilioでサービスを作ってみようと思っている方に参考になるよう、私がTwilioを使ったサービスを作ってみたときの過程をメモしておきます。

Twilioを使ってサービスを作成するときには、開発言語としてJavaやPHP、Python、RubyやSalesforceなど、いろいろなものを選べます。

それぞれの言語での開発の仕方は別の記事にまとめますが、今回は、それらに共通の、最初のアカウント登録のやり方とその注意点にフォーカスを当てたいと思います。

なお、以下は無料の開発者アカウントでの作業の過程をご紹介したものですが、実際にサービスを開始する際も、アカウントをアップグレードできますので、ほとんど同じプロセスで可能だと思います。

 

TwilioでWebサービスを作る過程

無料開発アカウントのサインアップ

はじめにアカウントを作成します。

http://twilio.kddi-web.com/

日本では、KDDIがTwilioの代理店なので、日本でアカウントを作っておいた方が、何かと便利だと思います。

KDDI Twilio

 

上記ページにアクセスしたら、右上の「サインアップ」からアカウントを作成します。

AccountTwilio

 

なぜか、「現在アカウントを作成できません。」というエラーになってしまい先に進めませんでしたが、質問に対する回答を変えて何度かトライすると作成できました。

私がOKになったのは、「どのサービスを最初に利用する予定ですか?」→「SMS」、「お作りになるサービス」→「Account Alerts」、「利用言語」→「利用言語がこの中にはない」という選択肢でしたが、この選択肢が良かったのか、何度かトライしたのが良かったのかは定かではありません。

次に表示されるのは、SMSによるアカウントのべリファイです。

入力した電話番号にショートメッセージが送られますので、携帯の番号を入力し、「Verify via SMS」ボタンを押します。

Twilio Verify

 

SMSが届いたら、メッセージに書いてある番号を確認して、下記画面で入力し、「Submit」を押せば、OKです。

Twilio Code add

 

電話番号の取得

さて、アカウントのサインアップが完了すると、以下のような管理コンソールが表示されます。

はじめに行うのは、「電話番号の取得」ではないでしょうか。

サーバやアプリなどのプログラムから電話をかけたり、SMSを送るには、送信元の電話番号が必要になってくるからです。

Twilio tel add

 

「最初のTwilio電話番号を取得」を押すと、日本の電話番号が無作為に選択されます。

ここで注意したいのは、番号によってできることが異なるということです。

下記の図の日本の電話番号の場合、「着信コールを受信および発信」が出来るとありますね。

SMSのメッセージングを行うには、アメリカの電話番号でないといけません。

Twilio call add

 

私は、SMSも行いたかったので、「別の番号を検索する」で、別な番号を選択することにしました。

すると、以下のように用途や国で電話番号を検索できます。

米国の番号ならSMS等が使えるので、そのまま検索すると、、、

Twilio american tell add

 

以下のように結果が表示されます。

「利用可能な機能」のところに、「音声通話」「SMS」「MMS」があるので、取得する電話番号で使いたい機能を使えるかを確認して、「Choose this Number」で選択します。

Twilio american tell add

 

以下のようなダイアログが表示されたら、取得できたということです。

おめでとうございます。

Twilio get tell

 

ダッシュボードのホームにいくと、「ACCOUNT SID」と「AUTH TOKEN」が既に発行されていることが確認できます。

発信元の電話番号とこの「ACCOUNT SID」と「AUTH TOKEN」があれば、プログラムで音声やSMS送信は出来ます。

Twilio auth key

 

無料トライアルでの送信について

無料トライアル期間中は、送信先として指定できるのは、登録に使った認証済みの携帯電話番号のみとなります。

それ以外の電話番号に送信した場合は、APIから「The number +81xxxxxxx is unverified. Trial accounts cannot send messages to unverified numbers; verify +81xxxxxxxxx at twilio.com/user/account/phone-numbers/verified, or purchase a Twilio number to send messages to unverified numbers.」のエラーが返ってきます。

送信できるようにするには、検証済み電話番号に追加する必要があります。

アップグレードすると、この通信制限は解除されます。

 

Twilioの利用料金について

Twilioは、

・発信元の電話番号

・音声やSMSを送信した分だけの利用料

を月々払うだけのシンプルな契約です。

発信元の電話番号は月々、150円程度から使用できますので、お得だと思います。

http://twilio.kddi-web.com/price/

Twilio price

 

SalesforceでRestAPIを自作し、外部からPOST/GETで呼ぶ方法とJson引数の解析

$
0
0

Salesforceでは、自分でREST APIを作成して、それを外部のプログラムから呼ぶことができます。

ここでは、REST APIの作成方法と、GETやPOSTでのCallの仕方、それぞれのメソッドで引数を取得して、それを解析する方法もご紹介します。

作成した自作のRESTを外部から呼ぶ方法については、こちらの記事をご参照ください。ブラウザでの呼び出し方法ですが、同じ様なことをJavaなどのプログラムで行えば、プログラムからも呼び出し可能です。

 

SalesforceでのREST APIの作成

アノーテーション「@RestResource」を使うとRESTサービスを作ることができます。

まずは、例を見てみましょう。

@RestResource(urlMapping='/MyRestServices/*')
global class MyRestController {

	@HttpGet
	global static ReturnObj getAccountInfo() {

		RestRequest req = RestContext.request;
		RestResponse res = RestContext.response;

		// パラメータ取得
		String param1 = req.params.get('param1');

		return '' ;       
	}
    
    
	@HttpPost 
	global static String updateAccountInfo() {

		RestRequest req = RestContext.request;
		RestResponse res = RestContext.response;

		// パラメータ取得
		Map<String, Object> requestParams = (Map<String, Object>)JSON.deserializeUntyped(req.requestBody.ToString());

        	Map<String, Object> resultParam2 = (Map<String, Object>)requestParams.get('param2');
        	String resultParam2_1 = (String)resultParamKokyaku.get('param2_1');

        
        	List<Object> resultParams = (List<Object>)requestParams.get('param3');
        	for (Object obj : resultParams) {
            		Map<String, Object> params = (Map<String, Object>)obj;
            		String eventType = (String)params.get('param3_1');
        	}

		return '';
	}

 }

アノーテーションのプロパティに(urlMapping=’/MyRestServices/*’)とありますが、これは、MyRestServicesというURLで以下のHTTPメソッドを公開するという意味です。

メソッド(GET,POST,PUT,DELETE等)は、1つのRestクラス(ここではMyRestController )で各一つずつ定義することができます。

「*」は、各クラスメソッド名がそのままURLにマッピングされるということになります。

RESTを作成すると、決められたエントリポイントで公開され、たとえば、MyRestController.getAccountInfo()は

https://<SFDCインスタンス>/services/apexrest/MyRestServices/getAccountInfo

でCallすることができます。

 

パラメータの解析

さて、RESTを呼び出すことができるようになったら、HTTPのリクエストで渡された引数を取得することにしましょう。

 

GETパラメータの場合

一つ目はGETパラメータで、<URL>/getAccountInfo?param1=aaaa

のような形で渡ってきます。

この場合は、「 req.params.get(‘param1’)」のように、パラメータ名を引数に取得します。

 

POSTパラメータ(Json)の場合

POSTのパラメータがJson形式でわたってきた場合は、クラスを定義して、MyRestController.updateAccountInfo(定義したクラス)のようにすると、Salesforceで自動でJsonのでシリアライズが行われます。

ただ、この方法だと、インターフェースが変更になった場合にエラーを起こしやすいため、私は、Stringで取得し、Jsonのパースを行った後で、Mapのキー名で取得するようにしています。

Map requestParams = (Map)JSON.deserializeUntyped(req.requestBody.ToString());

の部分ですね。

パースが行われると、Map形式で格納されますので、パラメータ名で簡単に値を取得できます。

上記のサンプルでは、

{“param2”:{“param2_1” : “aaaaa”,”param2_2″ : “bbbbb”},
“param3”:[{“param3_1”: “cccccc”, “param3_2”: “dddddd”},{“param3_1”: “eeeee”, “param3_2”: “fff” }]}

のような、入れ子で、配列の形のJsonから値を取得しています。

SalesforceでのDataloaderでの日付の扱いと、インポート時に一日ずれる件の検証

$
0
0

Salesforceは、複数言語や世界中のタイムゾーンに対応しており、ユーザごとに自由に言語設定やタイムゾーンを設定できます。

便利なのですが、注意しないと、エクスポート/インポート時に思わぬ時刻ずれが発生してしまうことにもなりかねません。

私自身、いろいろな場面であぶないなーと感じていることもあり、ここらへんの振る舞いをまとめておこうと思います。

 

Dataloaderでエクスポートした時のフォーマット

データローダーでエクスポートすると、

日付型項目(2016/09/01)  → 2016-09-01
日時型項目(2017/01/01 1:00)  → 2016-12-31T16:00:00.000Z

のようになります。

形式は、「YYYY-MM-DDThh:mm:ss.SSSZ」の形となっています。

エクスポート時、日時の項目はすべて、GMT(グリニッジ標準時)に変換されて上記のように出力されますが、日付項目は、日付で切り捨てされて出力されます。

ここで、「T」は、時刻の要素が始まりますよという印の文字列で、ISO8601で定義されています。

また、「SSS」はミリ秒、最後の「Z」はGMTをあらわします。

 

Dataloaderのインポート時の問題と振る舞いの整理

ここで、「2016-09-01」の項目をDataloaderでインポートすると、日付が一日前になってしまう問題が知られています。(https://help.salesforce.com/articleView?id=000047804&language=ja&type=1)にも書いてあり、この通りなのですが、ややこしいので、検証して整理してみました。

 

Dataloaderのタイムゾーン指定

前提として、Salesforceの内部では、日付型、日付時間型項目のデータは全てGMT(グリニッジ標準時)に変換され格納される仕様です。

なお、DataloaderのSettingでは、タイムゾーンを指定でき、「Asia/Tokyo」(GMT+9:00)のように設定することができます。(多くの場合、タイムゾーンには「Asia/Tokyo」が設定されていると思います。)

では、「Asia/Tokyo」はタイムゾーンに指定された設定のDataloaderでSalesforceへのインポートを行うと、何が起こるでしょうか。

この場合、「データにタイムゾーンの指定が無ければ、(GMT+9:00)としてインポートを行う」という動きになります。

つまり、「2016-09-01」は、インポート時に「2016-09-01 00:00(GMT+9:00)」と解釈されるため、「2016-08-31 15:00(GMT)」と変換され、日付としては「2016-08-31」が格納されることになります。

ここでキモなのは「タイムゾーンの指定が無ければ」というところで、日付型は時間の指定がないため、暗黙的にDataloaderの設定のタイムゾーンが使われることになりますが、日時型はそれに限りません。

日時型の項目へは、Dataloaderでは以下のようなフォーマットでもインポートができます。

①「YYYY-MM-DDThh:mm:ss.SSSZ」・・・例:2016-12-31T16:00:00.000Z
②「YYYY-MM-DDThh:mm:ssZ」・・・例:2016-12-31T16:00:00Z
③「YYYY-MM-DDThh:mm:ss」・・・例:2017-01-01T09:00:00

①と②の場合はインポート時もGMTとみなされ、SFDC内に格納されるデータは「2016-12-31T16:00:00.000Z」になります。そして、表示時に、ログインしているユーザのタイムゾーン設定に変換されますので、「Asia/Tokyo」のユーザであれば、「2017/01/01 1:00」と表示されることになります。

③は、インポート時に「2017-01-01T09:00:00(GMT+9:00)」と解釈され、SFDC内に格納されるデータは「2017-01-01T00:00:00.000Z」となり、表示は「Asia/Tokyo」のユーザであれば、「2017/01/01 9:00」となります。

 

どの運用が良いか

上記の振る舞いの整理を踏まえて、対処法と注意点を考えてみます。

 

Dataloaderのタイムゾーン設定を「GMT」にする。

運用上、一番間違いが少なさそうなのは、Dataloaderのタイムゾーン設定を「GMT」にすることだと思います。

下記のように日時項目であっても、時刻まで指定したり、一日前の日付を指定するという方法もありますが、エクスポート時に切り捨てられて「2016-09-01」のような形式となってしまうので、それを再度インポートするときにまた一日前に変換しないといけません。

特に、開発時やインポート/エクスポート運用が頻繁な場合は、GMTを指定した方が変換が無く、間違いが少ないと思います。

 

GMT指定でインポートする

日付項目であっても時刻指定の形式でインポートできますので、「2017-01-01T00:00:00.000Z」のようにGMT指定でインポートすることができます。

こうすると、インポート時にGMTとみなされ、変換が発生しないので、内部的にも「2017-01-01」で格納されます。上記で述べたように、エクスポート時に「2017-01-01」となってしまいますので、再インポート時には注意したいですね。

 

9時間足した日時をインポートする

「2017-01-01T09:00:00」のようにタイムゾーンの指定無しでインポートすると、Dataloaderのタイムゾーン設定がいかされますので、「Asia/Tokyo」であれば、変換されて、「2017-01-01T00:00:00」でインポートされます。

このやり方も、エクスポート/インポート時に気をつけたい方法ではあります。

SalesforceからTwilioのAPIを使ってSMSメッセージを送信する

$
0
0

この記事では、SalesforceからTwilioでSMS発信を行うための設定と、Apexソースをご紹介します。

SalesforceでTwilioを使うには、Twilioから提供されている、無料のヘルパークラスを使うと便利です。

APexによるクラスが提供されているので、環境の設定とわずか数行の記述でSMS送信等が実現できます。

https://jp.twilio.com/docs/libraries/salesforce

twilio

 

TWILIO セールスフォースヘルパーライブラリーのセットアップ

ヘルパーライブラリーは2つの方法でSalesforce組織にセットアップできます。

ひとつは、パッケージのインストール・プロセスを利用することが可能で、上記URLの「セルフビルド・パッケージ」をクリックしてSalesforce組織にログインすれば、その組織に自動でインストールできます。

もうひとつは、既にインストールされている場合は、MigrationToolを使って、Githubから取得したソースをAntのビルドプロセスで組織にデプロイできます。(MigrationToolの使い方はこちらの記事を参考に。)

 

Salesforce組織の設定

ヘルパーライブラリーのセットアップができたら、環境設定を行います。

主な設定箇所は以下の2点です。

 

Twilio用カスタム設定を行う

ヘルパーライブラリーのセットアップを行うと、「Twilio Config」というカスタム設定ができています。

「ACCOUNT SID」と「AUTH TOKEN」の設定を、APexではなく、レコードに行えるので、デプロイ時の柔軟性がアップします。

ここにレコードを追加して、前回の記事で確認した「ACCOUNT SID」と「AUTH TOKEN」を設定しておきましょう。

sfdc setting

 

リモートサイト設定

SalesforceのApex内から外部にWebサービスのコールを行うには、リモートサイトを設定して、Calloutを許可しておく必要があります。

TwilioのAPIポイントである「https://api.twilio.com」を適当な名前で追加して、許可しておきましょう。

 

Apexのソース記述例

上記までの設定を行えば、後は、TwilioのAPI呼び出しをApexコードに記述するだけです。

public void SendSMS()
{
    
    System.debug('SendSMS');
    Try{
        textMessage = 'tests';
        FromMobileNumber = '+xxxxxxx';
        ToMobileNumber = '+yyyyyyy';
        
        if(ToMobileNumber != '')
        {
            List<TwilioConfig__c> AdminInfo = TwilioConfig__c.getall().values();
            String ACCOUNT_SID = '';
            String AUTH_TOKEN  = '' ;            
            String SenderMobileNumber = '' ;
            // Informaton getting from custom setting
            if(AdminInfo.size()>0)
            {          
                ACCOUNT_SID             = AdminInfo[0].AccountSid__c;
                AUTH_TOKEN              = AdminInfo[0].AuthToken__c;                
            }            
            TwilioRestClient client = new TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN);
           
            Map properties = new Map {
                        'To'   => ToMobileNumber ,
                        'From' => FromMobileNumber,
                        'Body' => textMessage
                };
            TwilioSMS message = client.getAccount().getSmsMessages().create(properties);
            ApexPages.addMessage(new ApexPages.message(ApexPages.severity.INFO, 'Message has been sent'));
        }
        else
        {
            ApexPages.addMessage(new ApexPages.message(ApexPages.severity.Error, 'Pelase provide valid Mobile Number '));
        }
    }catch(Exception e )
    {
        ApexPages.addMessages(e);      
        return ;
    }
}

使い方はここを参考にできます。

http://twilio-salesforce.readthedocs.io/en/latest/

SalesforceでLineのMessaging(PUSH)APIを使ってみる

$
0
0

この記事では、SalesforeからLineにメッセージを送る方法をご紹介します。

APIを利用して送ること自体はそんなに大変ではないですが、送るための情報を取得する仕組みや、そのためのSalesforce側の設定は少しコツが必要なので、具体的に解説しています。

 

Calloutのためのリモートサイトの設定

まずはSalesforceのApexからLineのMessagingAPIを呼べるようにセキュリティの設定を行っておきます。

Salesforceの管理コンソールの「設定」→「リモートサイトの設定」で、LineAPIのURLを登録して、Calloutできるように許可しておきます。

Line API

 

 

Webhookの設定

次に行うのは、前回の記事にも出てきた、Webhookの設定です。

メッセージ送信を行うLine@アカウントへの友達の申請やメッセージ送信のたびにそのURLにJSONがPOSTされるのでしたね。

そのため、Line側から呼べるURLになっていなければいけません。ここが少しコツのいる部分です。

通常、Salesforce上でApexでWebサービスのエントリポイントを作った場合、それを呼ぶにはログインが必要です。

しかし、Line側はSalesforceのログインIDは知りませんから、ログインできません。

つまり、ログインしないでも呼び出し可能なWebサービス(Webhook)を作成して公開する必要があります。

ApexでWebサービスを作って、匿名呼び出しも可能なように公開する設定については、長くなるので、こちらの記事で詳しく説明しておきます。

Webhook自体はシンプルなものです。下記のようなWebサービスを作成し、上記記事を参考に、匿名で公開しましょう。

@RestResource(urlMapping='/line_webhook_callback')
global with sharing class LineWebHookCallback {
    static String LINE_GET_PROFILE_URI = 'https://api.line.me/v2/bot/profile/';
	static String CH_ACCESS_TOKEN = 'xxxxxxxxxxxxxxxxxxx';
    
    @HttpPost
    global static Map<String,String> doPost(){
        RestRequest req = RestContext.request;
        RestResponse res = RestContext.response;
        
        System.debug('★★req.requestBody.ToString(): ' + req.requestBody.ToString());
        
        Map<String, Object> callbackParams = (Map<String, Object>)JSON.deserializeUntyped(req.requestBody.ToString());
        
        
        List<Object> resultParams = (List<Object>)callbackParams.get('events');
        for (Object obj : resultParams) {
            Map<String, Object> params = (Map<String, Object>)obj;
            String eventType = (String)params.get('type');
            Map sourceParams = (Map<String, Object>)params.get('source');

            if( eventType == 'follow' ){
                String sourceType = (String)sourceParams.get('type');
                String userId = (String)sourceParams.get('userId');

            }else if( eventType == 'message' ){
                String sourceType = (String)sourceParams.get('type');
                String userId = (String)sourceParams.get('userId');

            }

		Contact newCt = new Contact();
                newCt.LastName = displayName;
                insert newCt;
        }
        
        Map m1 = new Map<String, String>();
		m1.put('result', 'success');
        
        
        return m1;
    }

}

https://<サイトURL>/services/apexrest/line_webhook_callback

で呼び出せます。

公開まで出来たら、Line DevelopersのWebhookのところに上記URLを設定します。これで、メッセージが送信された時などにこのURLの情報がPOSTされます。

「userId」という項目を取得してとりあえず取引先に保存していますが、これが、メッセージをPushAPIなどで送信する際にToに設定するIDになります。スマホの設定で確認できるLineのIDではなく、MIDと呼ばれるLine内部の識別子なので、注意してください。

また、このMIDはユーザごとに一意ではありません。

Line@アカウントが異なれば、同じLineユーザであっても識別するMIDが異なるので、Bot(Line@アカウント)ごとに友達申請してもらって、取得する必要があります。

 

友達追加

ここで、友達追加をしてもらう方法をメモしておきます。

LINE@MANAGERの「アカウント設定」→「基本設定」に、QRコードや友達追加ボタンのコードがあるので、サイトに貼り付けたりすると、簡単にこのLine@アカウントを追加できます。

Line API

 

 

メッセージ送信(Push API)

HttpRequest req = new HttpRequest();
req.setHeader('Content-Type', 'application/json');
req.setHeader('Authorization', 'Bearer '+ CH_ACCESS_TOKEN);
req.setEndpoint(LINE_PUSH_URI);
req.setMethod('POST');
req.setBody('{"to": "取得したuserId(MID)","messages":[{"type":"text", "text":"Hello, world"}, { "type":"text", "text":"ハロー、ワールド" } ]}');


Http http = new Http();
HTTPResponse res;

try {
	res = http.send(req);
	System.debug('★★★HTTP Response Code: ' + res.getStatusCode());
	System.debug('★★★Response Body: ' + res.getBody());

} catch (Exception e) {
	System.debug('★★★★Callout Error:' + e.getMessage());            
}

なお、APIのドキュメントは

https://devdocs.line.me/ja/

を参考にしましょう。

素人でも簡単にお店のホームページを作成できる「Goope(グーペ)」で、できることを試してみた

$
0
0

私は、将来は日本か海外で小さなお店をやるのが夢なのですが、店舗運営やデザインは全くの素人なので、今から勉強しておこうと思います。

お店をオープンしたら、お店の顔、ホームページを作りたいですよね。

ホームページにほしい情報としては、

  • オープン時間や住所などのショップの基本情報を公開したい。
  • メニューや価格、料理の写真を載せて、にぎやかでおしゃれな感じを伝えたい。
  • 料理や店内の運営に時間をかけたいので、ホームページの更新はなるべく簡単なほうが良い。
  • FacebookやTwitterなどのSNSも使ってみたい。
  • スマホを使っている人も多いので、スマホで見てもきれいに見れるサイトであること。
  • 運営に余裕が出てきたら、予約なんかもネットから受け付けられるといいかな。

なんてことを考えています。

こんなホームページを作って運営するには、レンタルサーバを借りて、そこにサイトを作ったり、Wordpressのようなブログをインストールする方法もありますが、記事や写真のアップなど、初心者には難しいことも多いです。そんな初心者のために、今ではいろいろなサービスがあり、契約すれば月々1000円程度で、難しい設定や操作を極力しないで、自分のショップのサイトを運営することができます。

サービスによって使い勝手やできることに特徴があるようなので、いくつか実際に使ってみました。

今回は、その中でも「初心者にも簡単な操作で、数分で自分のサイトを作成できる」ことが売りの「Goope(グーペ)」を使ってみました。

 

グーペは本当にお店のサイトが「1分でできる」の?

グーペのサイトに行くと、「あなただけのホームページが1分でできます」とあります。口コミにも「初心者向き」という評価が多いので、「そんなに簡単なの?」と期待が膨らみますが、簡単なだけでおしゃれじゃなかったり、できることが少ないと本末転倒ですし、長い目で見ると、多少操作に慣れないといけなくても、拡張性があったり、基本料金でできることが多い方がいい場合もあります。

 

goope

 

まずは、カスタマイズをあまりしないで、登録したばかりの素の状態でどれくらいのことができるか試してみました。Goope(グーペ)は「15日間無料お試し」があるので、気軽にためせていいですね。

 

ログインIDの申込

初めに行うのは、ログインIDとパスワード、連絡用のメールアドレスを登録することです。

ログインIDとパスワード、連絡用のメールアドレスを入力 ↓ ↓ ↓ goope login

 

上の画面で入力して「利用規約に同意して申し込む」ボタンを押すと、下の画面になります。

goope 完了

 

会員登録はこれで終わりですが、上記で入力したメールアドレス宛に「本人確認」用のメールが届いているはずですので、そのメールにあるURLをクリックして、本人確認を終わらせておきます。申請したメールアドレスがちゃんと本人のものなのかを確認するステップですので、忘れずに行っておきましょう。

以上で登録は完了です。1分足らずで終わりました。もう、あと少しで最初のホームページができます。

 

初めてのホームページのための初期の設定

ようこそ画面 ↓ ↓ ↓ goope login

 

会員登録が終わると、上記のようこそ画面に行きます。やることはないので、そのまま次の「初期設定」に進みましょう。初期設定でやることは2つ、「お客様情報」と「ホームページ情報」を設定するだけです。この2つに情報を入力すると、ホームページができちゃいます。

お客様情報を入力する ↓ ↓ ↓ goope お客様情報

 

この画面では「お客様情報」を入力します。自分以外の人には公開されない情報なので、自分の情報を入れましょう。あとから変更も可能です。

 

ホームページの情報を入力する ↓ ↓ ↓ goope お客様情報

 

さて、自分のはじめてのホームページ作成に一番重要なのはこのページで設定する内容です。ホームページのタイトルやお店の電話番号や住所などの情報を入力します。

ここで入力した内容で、自動でホームページができあがります。入力内容は、ホームページを公開した後もいつでも変更できますし、ここで入力した以外の情報も後で追加することができます。ショップ・お店のホームページとして必要最小限の情報を入力する画面といったところでしょうか。

「ジャンル」を設定するところがありますが、ここで選択したジャンルによって、自動でホームページの背景写真が設定されますので、ぴったりとはいかないまでも、女性向け、飲食向けなど、自分のお店のジャンルに近いものを選ぶことをお勧めします。(※もちろん後で変更可能です。)

できちゃった! ↓ ↓ ↓ goope 完成

 

 

自分だけのホームページができた!かかった時間は数分。

以上で終わりです。これで、必要最小限のホームページが完成しました。公開までにかかった時間は、1分とまではいきませんでしたが、それでも数分くらいでここまで来ることができました。

サイトの構成も、複数ページになっていて、トップページや店舗の基本情報のページが自動で出来上がっています。背景の写真は、選択したジャンルによって、自動で設定してくれます。

 

トップページ ↓ ↓ ↓ goope トップページ

 

ジャンルとして焼き肉屋さんを選んだので、少し大人な感じの黒を基調とした写真が背景に設定されていますね。美容室や女性向けのジャンルを選ぶと、もっとかわいらしい感じになるのでしょう。

 

店舗情報と地図のページ ↓ ↓ ↓ goope 店舗情報

 

お店の電話番号や住所などの店舗の基本情報のページも生成されています。入力した住所から、Googleマップの地図も出来上がっているので、お客様は自分で場所を確認しやすいですよね。

 

スマホでみたトップと店舗情報ページ ↓ ↓ ↓ goope 店舗情報

 

スマホで確認してみましたが、ちゃんとスマホ対応のレイアウトになっていました。自動でスマホ用の表示にしてくれるのは、あまり詳しくない私からすると、非常にうれしい機能です。

 

今回実際に使ってみて分かったことと、もう少し試してみたいこと

さて、今回、最初のホームページを作ってみて感じたことは、「ホントに簡単にホームページを作成することができる」ということです。わずかな入力で、ある程度デザインもされたホームページが出来上がるのは、忙しくて、サイト運営の知識もあまりない店舗経営者にとってはありがたいです。

まずは必要最小限のホームページを作りたいというニーズに合っていると感じました。

通常、プロの業者にホームページを作ってもらうとサイトの作成に15~40万円かかるだけでなく、維持、運営、サイト更新などの費用が月1~3万円くらい必要ですが、Goope(グーペ)なら月々たった1,000円(税抜)です。

もちろん、プロの会社にその金額を払えば、自分だけのホームページを自分の好きなように作成してくれますし、記事や情報の更新もお願いできますので、手間はかかりません。

それに対して、Goope(グーペ)などの格安ホームページ運営サービスでは、ある程度決まったテンプレートを使い、自由度が制限されている中であれば、自分のお店のホームページを安く運営できます。もちろん、記事などの更新を行うのは自分でしなければいけませんので、、その手間をどれだけ簡単にできるか、どれだけのカスタマイズが可能かが各格安ホームページ作成サービスの差、選ぶポイントになってきます。

Goope(グーペ)の詳細

NPO・NGOのサイト運営を低コストで始めるコツ(実践編)

$
0
0

今やNPO・NGOの広報に欠かすことのできないWebサイトやSNSなどの情報発信ツールですが、あまり資金をかけられないというのがちょっとした悩みだったりします。SNSは無料で使えるものがほとんどですが、知名度を上げたり活動を伝えるのにはやはりホームページが欠かせません。

そこをなんとか低予算でできないものかと考えているのですが、それを解決するのはやはりオープンソースのWordpressがいいかな、と思います。(詳しくは➜➜こちらで

誰でも扱い易いし、カスタマイズ度が高いというのがその理由です。“扱い易い”というのは一つの重要な要素で、携わる人材を確保しやすいということです。
特にNPO・NGOはメインで活動に従事できる人は限られていますので、多くの人の手を借りながら運営することが ほとんどです。そこにボランティアやインターンという形で参加するので、やれる業務があればおまかせできるわけです。

また人の入れ替わりもあるため、すぐに習得できる業務のほうが作業分担にもなるので運営も助かるというもの。このような理由から『Wordpress』を使っての広報(情報発信)大作戦です。

サイトを構築するための環境を整える

サイト(ホームページ)を立ち上げるには最低限必要なものがあります。

サーバーのレンタルとドメインを取得する

通常、新規でホームページを立ち上げる際は“サーバー”と“ドメイン”は必須です。年に数千円程度の出費でできますのでここは経費として確保しましょう。

今回は母体NPOのホームページがあるので新規にドメインの取得はやらないで、1事業だけのスピンオフサイトの位置づけでサブドメインとして行います。既存のドメインが使える上に関連性もあるので、双方のメリットがあると考えました。またドメインはその組織を表すURLになるのでよく考えて付けます。

会員のそれほど多くないNPOや設立してまだ浅いNPOはそこまで情報量が多くないと思われるので「個人向け」のレンタルサーバーで十分です。

レンタルサーバーを選択するときに気を付けたいのが、Wordpressに対応しているかどうかです。各レンタルサーバーのホームページで確認することができます。
最近はレンタルサーバーと同時に独自ドメインを取得できるお得なプランがあります。サーバーは各社それぞれのプランによっても出来ることが違ってきますので予算を考えて決めます。

おすすめのサーバーは実績と安定性、サポート、そしてコストを考えて決定します。以下に筆者のすすめるレンタルサーバーを一覧にしました。全てWordpressに対応しているプランです。

サーバー名 プラン 月額 初期費用 ディスク容量 マルチドメイン数
バリューサーバー まるっと

12か月1727円(年契約のみ)

無料 25GB 3
エコ 180円~ 1080円 50GB 25
お名前.com SD-11 900円~ 無料 200GB 無制限

WordPressをインストールする

サーバーとドメインだけでは見せるサイトがない空箱の状態なので、ここでWordpressのインストールが必要になります。

WordPressに対応しているサーバーであればすぐにできます。サーバーによってやり方は多少違うので、 各サーバーのインストール手順に従ってください。
不安のある人はサイト作成に知見のある人にやってもらったほうが無難です。

ホームページ(サイト)の“顔”を考える

WordPressのテーマを決める

WordPressでいうテーマとはサイトデザインのことです。これでサイトの印象がまったく違ってきますのでいわば「顔」とも言うべきものです。

伝えたいことや情報量、サイトの利用の仕方で違ってきます。一概に“凝った”ものがいいかといえばそうとも言えません。

NPOやNGOのサイト目的は伝えたいことが簡単にわかる、欲しい情報がすぐに手に入ることです。
盛り込みすぎても何の活動を行っているのか分かりずらかったり、逆に器(デザイン)だけ大きくて内容がなければ極端なはなし活動実態を疑いかねません。その時の状況に合わせて刷新していくのがいいですね。そうすれば情報の整理にもなりますし、実績の振り返りにもなります。

WordPressはその変更が比較的やり易く、安価でできるので後々のことを考えても使い勝手がいいです。 しかも無料で機能にも優れたテーマが多くあります。

テーマを決める時に考えること

今回テーマを選ぶにあたって参考にしたサイトをご紹介します。

    1. WordPress.ORG日本語サイトです。無料のものも豊富にあります。
      >>> https://ja.wordpress.org/themes/
    2. 2016年に人気のテーマを集めたサイト
      >>> https://www.webtoolnavi.com/blog-wordpress-theme-2016/
    3. 海外で人気のテンプレートを日本語対応にしたものを集めています。
      >>> http://wpthemejp.com/

あまり候補が多すぎても選ぶのが大変ですので、基本のレイアウトデザインは決めておいたほうが良いです。またWordpressでも日本語に対応しているものとしていないものがあるので、初心者は「日本語対応」の WordPressが使いやすいかと思います。

NPOやNGOの場合、活動の報告やイベントの告知も頻繁に行う可能性が高いので、始めはブログ型で 情報発信を行う方法がよいですね。恐らくサイト更新も人手が足りないことが予想されるので、シンプルに更新できることを優先させます。

Goope(グーペ)の通常プランでできること –お知らせ機能を使ってみる

$
0
0

Goope(グーペ)には「通常プラン」と「DXプラン」があり、それぞれ1000円/月、1500円/月と月額に差があります。

でも、うれしいのは、1年契約だとどちらも12000円で同じ料金になるということですね。月額1000円というと、一般的なレンタルサーバと同じくらいの料金ですが、レンタルサーバに必要な記事のアップロードやドメインの管理など、難しい管理作業がいらず、わかりやすい画面から写真をアップしたり、記事を投稿したりできるので、初心者でも続けやすいことはメリットだと思います。

張り切ってホームページを公開したのに、更新は最初の数回だけ、、、というのでは、公開しない方がマシとも言えます。

さて、今回は、ホームページの更新に役立ちそうな機能、「お知らせ更新」の機能を解説します。

 

Goope(グーペ)の「お知らせ更新」機能ってどんなの?

Goope(グーペ)のお知らせ機能は、その名の通り、お知らせを簡単に更新できます。

投稿する画面は、下のような感じで、グーペの管理画面から入力できます。

お知らせ編集画面

 

文章を入力するところは、ワード(Word)のような感じで、文字に色を付けたり、大きさを変えたりすることはもちろん、写真を貼るのも簡単にできました。

また、デザインに詳しい人なら、HTMLというタグを使って入力することもできるので、細かい調整を行うこともできます。

投稿したら、すぐに、下のようにホームページの中の「インフォメーション」のページに反映されていました。

お知らせ画面

 

なんだか、「HTMLでページを作成してアップロード」みたいな手順がいらないので、更新は非常に楽になると感じます。

ちなみに、お知らせをアップすると、トップページにも

TOP画面

 

こんな感じでリンク付きで表示されます。

 

携帯やスマホからもお知らせ記事が更新可能

Goope(グーペ)のいいところは、「携帯投稿設定」というものがあって、携帯メールを登録しておくと、その携帯メールから記事を書いて特定のメアドに送信すれば、そのまま「お知らせ記事」として投稿されます。パソコンが手元や店舗にない場合でも更新できるってことですね。もちろん、iPadやスマホ、タブレットからも更新できますので、更新の手段には困らないと思います。

 

TwitterやFacebookにもお知らせ記事が更新可能

店舗やショップで、TwitterやFacebookページを持っている場合は、これらのアカウントを登録しておくと、お知らせに投稿した内容をTwitterやFacebokkにも投稿できます。また、ホームページにTwitterやFacebookのアカウントを掲載して、ホームページからSNSを経由してお客様の反応を広げていくことも可能だと思います。

Goope(グーペ)の詳細

Salesforceのトリガでのoldとnewの使い方

$
0
0

Salesforceの開発を行っていると、トリガを作る機会が多くあります。

作るたびに調べたりするのですが、oldやnewの使い方や使いどころなどを一旦きちんとまとめておいた方が自分でも迷わないと思い、まとめておくことにしました。

 

実行のタイミング

まずは、基本的な実行のタイミングから。

 

beforeトリガ

レコードがDBに格納される前のタイミングで起動されます。DBに保存する前に何か前処理を行いたい場合に使うことが多いです。例えば、入力チェックなどが多いですね。

 

afterトリガ

レコードがDBに保存された後に起動されます。ObjectIdや自動採番などが振られた状態になりますので、それらの値が決定してからの処理を行うのに適しています。ただ、まだコミットされていないとはいえ、DBに格納されているのと同じ状態なので、その値を変更するには、DML文を使う必要があります。

 

実際に実行のタイミングをデバッグして確かめてみる

実際に、以下のようなApex文を用いて、どのような値が入っているのか、どういう操作をしたらどのようなエラーが出るのかを確かめてみました。

trigger testAccountTrigger on Account  (before update, after update, before insert, after insert) {
    if (Trigger.isBefore) {
        System.debug('********トリガーの値isBefore***********');
        System.debug('***SFDC: Trigger.old は: ' + Trigger.old);
        System.debug('***SFDC: Trigger.oldMap は: ' + Trigger.oldMap);
        System.debug('***SFDC: Trigger.new は: ' + Trigger.new);
        System.debug('***SFDC: Trigger.newMap は: ' + Trigger.newMap);
    }
   
    if (Trigger.isAfter) {
        System.debug('********トリガーの値isAfter***********');   
        System.debug('***SFDC: Trigger.old は: ' + Trigger.old);
        System.debug('***SFDC: Trigger.oldMap は: ' + Trigger.oldMap);
        System.debug('***SFDC: Trigger.new は: ' + Trigger.new);
        System.debug('***SFDC: Trigger.newMap は: ' + Trigger.newMap);
    }
}

上記のようなコードでデバッグしてみると、oldとnewには以下のような値が入ります。

基本的に、トリガーの中で用いられるoldとnewは、変更前の値と変更後の値が入るのですが、isBeforeなのか、isAfterなのかのタイミングによって、変更できるか、変更できるとしてもその方法が異なります。

 

insert系

では、Insertの場合は、oldとnewには何が入っているでしょうか。beforeとafterで確認してみると、以下のようになります。なお、before insertの場合のみ、Trigger.newとTrigger.newMapで結果が異なりました。

ちなみに、Trigger.newはList配列で、順番に処理するのに適していますが、Trigger.newMapはMap配列型で、順番は保証されません。

before insertの場合

Trigger.old・・・null
Trigger.oldMap・・・null
Trigger.new・・・新規登録する直前のオブジェクト(ただしDB格納後に決定する、Id=null,自動採番系=null,CreatedById等のシステム系=null)
Trigger.newMap・・・null

Apex上で、oldの値を変更すると、
execution of BeforeInsert caused by: System.NullPointerException: Attempt to de-reference a null object: ()
が発生します。
newは変更可能です。

 

after insertの場合

Trigger.old(oldMap)・・・null
Trigger.new(newMap)・・・新規にDBに登録されたオブジェクト(ただしDB格納後に決定する、Id=あり,自動採番系=あり,CreatedById等のシステム系=あり)

Apex上で、newの値を変更すると

execution of AfterInsert caused by: System.FinalException: Record is read-only: ()
が発生します。
oldを変更すると、
execution of AfterInsert caused by: System.NullPointerException: Attempt to de-reference a null object: ()
となります。

なので、after insertではDML文で変更必要があります(変更可)。ただし、条件を if (Trigger.isInsert && Trigger.isAfter)のように変更しないと、

execution of AfterInsert caused by: System.DmlException: Update failed. First exception on row 0 with id 00128000018cHWpAAM; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, testAccountTrigger: maximum trigger depth exceeded Account trigger event AfterInsert for [xxxxx] Account trigger event AfterUpdate for [xxxx] Account trigger event AfterUpdate for [xxxxxxx] Account trigger event AfterUpdate

のようなエラーになります。

これは、Insertの後、Updateが行われ、その後、さらにUpdateのトリガが走ってしまうので、無限ループになってしまうためです。

 

update系

before updateの場合

Trigger.old(oldMap)・・・新規登録する直前の、変更前のオブジェクト(DBに格納されている)
Trigger.new(newMap)・・・新規登録する直前の、変更予定のオブジェクト

oldを変更すると、
execution of BeforeUpdate caused by: System.FinalException: Record is read-only:
のエラーになり、変更できません。
newは変更可能で、その後、その値でDBにupdateされることになります。

 

after updateの場合

Trigger.old(oldMap)・・・変更前のオブジェクト(すでに変更されている)
Trigger.new(newMap)・・・DBに登録された、変更後のオブジェクト(コミット前)

oldを変更すると、

execution of AfterUpdate caused by: System.FinalException: Record is read-only

になります。newを変更すると、

execution of AfterUpdate caused by: System.FinalException: Record is read-only
となります。ただし、DMLでは値の変更が可能です。でも、Updateのトリガなので、うまく考えないと、無限ループになってしまいます。

「うまく」というのは、条件にフラグ項目を入れ、そこが変わればトリガを発動させないなどの工夫をする必要があるということです。

エラーの回避例

List listAcc=new List();
    for (Account a : Trigger.new) {

        Account updacc=[select id,Name,Fax from account where id = :a.id];
        
        if(a.<フラグ項目>!='22442222'){
            updacc.<フラグ項目>='22442222';
            listAcc.add(updacc);
        }
        
    }
    update listAcc;
}

のように、フラグ項目を持たせ、一旦変更されたら、変更されたことを検知して、それ以降、Updateは行わないようにするというようなことです。

SalesforceからGoogleCalendarを設定する方法(指定ログイン情報を利用した連携)

$
0
0

SalesforceとGoogleCalendarのサービスを連携する方法についてメモしておきます。

今回は、Calendarを例にしていますが、原理は同じなので、これができれば、Googleのほかのサービスや、Googel以外のWebサービスとの連携も可能になります。

最初に、その原理について簡単に説明します。

 

原理

SalesforceからGoogleCalenderの操作(イベントや予定の追加・変更・削除・予定の参照)を行うには、GoogleCalendarAPIを利用します。

もちろん、誰でもそのAPIを利用できてはセキュリティ上よろしくないので、APIを利用するには、認証を経なければいけません。

最近では、その認証をOAuth方式で行うWebサービスが多くなってきていますが、GoogleもそのOAuth方式の認証を行えます。

一方、Salesforce側にも「指定ログイン情報」という便利な仕組みがあり、「GoogleAPIを使うためのログイン、認証情報を定義」しておくことができます。

さらに、この「指定ログイン情報」には、一度認証してしまえば、認証済み情報を保存しておくこともでき、それをApexコード内などから「指定ログイン情報名」で使用することが出来ます。

 

SalesforceとGoogleCalendarの連携設定手順

Step1 Googleのデベロッパーコンソールで、クライアントの定義を行う。

はじめに、GoogleAPIの設定を行います。

Googleのアカウントにログインした状態で https://console.developers.google.com/?hl=JA

に行きます。

ここで、そのユーザが使用できるAPIを有効化したり、ログイン認証情報の生成等を行うのですが、はじめに、分かりやすさのために、この連携用のプロジェクトを作成しておきましょう。

「プロジェクトを作成」をクリック ↓ ↓ ↓
プロジェクトを作成

 

プロジェクト名を入力 ↓ ↓ ↓
プロジェクト名を入力

 

プロジェクトの作成が終わったら、このプロジェクトで使用できるAPIを有効化します。今回は、GoogleCalendarAPIを有効化しました。

Google calendarの有効化 ↓ ↓ ↓
GoogleCalendarAPIを有効

 

APIの有効化ができたら、次に、このAPIの認証を担うクライアントを設定します。OAuthで認証させたいので、「認証情報を作成」ボタンを押し「OAuthクライアントID」を選択します。

「認証情報を作成」から「OAuthクライアントID」を作成 ↓ ↓ ↓
OAuthクライアントID

 

「Webアプリケーション」を選ぶ ↓ ↓ ↓
Webアプリケーション

 

上記の「ウェブアプリケーションの種類」では、形式は「ウェブアプリケーション」を選択し、適宜名前をつけて作成します。

後ほど、「認証済みのリダイレクトURI」をセットすることになりますが、この時点ではまだ分からないので、空白のまま作成します。

ウェブアプリケーション

 

作成すると、「クライアントID」と「クライアントシークレット」が発行され、下記のようなダイアログが表示されます。両方ともメモしておきましょう。

※後ほど、SFDCの画面で入力することになる。

 

Step2 SFDCの管理コンソールに行き、「認証プロバイダ」の作成を行う。

次に、SFDC側の設定を行います。SFDCの管理画面に行って、「認証プロバイダ」を「OpenID」形式で作成します。

※選択肢にGoogle形式もありますが、私が試したときにはうまく動きませんでした。OpenID形式の方が汎用性がある気がします。Google以外のサービスでも使えると思います。

「認証プロバイダ」の作成 ↓ ↓ ↓
OpenID

 

認証プロバイダ

 

新規作成時の入力画面では、先ほどメモした「クライアントID」と「クライアントシークレット」をそれぞれ「コンシューマ鍵」、「コンシューマの秘密」にセットします。他の入力項目は、以下のように入力しました。

  • 認証エンドポイント・・・https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force
  • トークンエンドポイント・・・https://accounts.google.com/o/oauth2/token
  • デフォルトの範囲・・・https://www.googleapis.com/auth/calendar

上記を入力して保存すると、下に「Salesforce設定」が表示されるので、このなかで「コールバックURL」をメモしておきます。

コールバックURL

 

メモしたコールバックURLは、GoogleAPIConsoleの以下のところ(「承認済みのリダイレクトURI」)に入力して保存します。

承認済みのリダイレクトURI

 

 

Step3 SFDCの管理コンソールに行き、「指定ログイン情報」の作成を行う。

「指定ログイン情報」の作成

 

先ほどSFDCの管理画面で作成した「認証プロバイダ」をここにセットします。

「保存時に認証フローを開始」にチェックしておくと、このレコードを作成(保存)したときに、OAuth認証も同時に行い、保存しておくことができます。

その他の入力項目は以下の通りです。

  • URL・・・https://www.googleapis.com/calendar/v3
  • 範囲・・・https://www.googleapis.com/auth/calendar

上記で保存ボタンを押すと、同時に認証が行われるので、以下のようなOAuth認証画面になります。

OAuth認証画面

 

認証すると、、、、

認証

 

「認証済み」で指定ログイン情報が作成され手いることが分かります。

 

Step4 SFDCの管理コンソールに行き、「リモートサイト」を作成

さて、いよいよ、ApexからGoogleCalendarAPIを呼ぶコードを書いていきますが、デフォルトでは、Salesforceでは、外部URLへのAPIコールが許可されていません。 そのため、リモートサイトの作成で、googleのサイトを登録し、Apexからのコールを許可するようにします。

リモートサイトの作成

 

 

Step5 作成した「指定ログイン情報」を利用して、ApexからGoogleにAPIを発行

 

使用例:
【検索】
String reqPath = 'callout:MyCalLogin(作成した指定ログイン情報名)/users/me/calendarList';
        
        System.debug(reqPath);
        
        HttpRequest req = new HttpRequest();
        req.setEndpoint(reqPath);
        req.setMethod('GET');

【イベント登録】
String reqPath = 'callout:MyCalLogin/calendars/<カレンダーID>/events';
        
        System.debug(reqPath);
        
        HttpRequest req = new HttpRequest();
        req.setEndpoint(reqPath);
        req.setMethod('POST');
         req.setHeader('Content-Type', 'application/json');
        req.setBody('{ "end": {  "dateTime": "2016-04-27T10:00:00+09:00" }, "start": {  "dateTime": "2016-04-27T10:00:00+09:00" }, "description": "sssq3333ss", "summary": "ddvddvdvdd"}');

 

ちなみに上記のコード例で出てくる「カレンダーID」の確認方法ですが、以下のように、Googleカレンダーの画面で確認できます。

Google calendarを開く

 

Google calendarIDの場所

 

【図解でわかりやすく】正規表現のまとめ その①基本メタキャラクタ編

$
0
0

パソコンを使っていると、ワードやノードパッドなどのエディタやそれ以外のアプリで、検索や置換をやったことある人は多いと思います。例えば、長い文章の中で、自分の指定した単語を一気に変えることができたりして、ほんとうに便利ですよね。

でも、たまに、特定の行の先頭に「・」を入れたいとか、郵便番号は「数字3桁-数字4桁」になっているかを確認したいとか、完全に文字が一致するのではなく、もう少しあいまいな、「こんな感じ」ということを表現したいことがあります。

パソコンでは、このようなことを「正規表現」といいます。何が「正規」なのかはそれこそあいまいですが、英語では、「Regular Expression」と言いますから、それを直訳したような表現ですね。正規表現にあまりなじみのない方も、「*」(ワイルドカード)という言葉は聞いたことがあるのではないでしょうか。トランプのジョーカーのように、何にでもマッチすることを意味して、「か*」であれば、「かに」でも「かき」でも当てはまるといった感じです。

「*」は正規表現の中でも代表的なものですが、それ以外にもいろいろな表現があり、それらをある程度マスターすると、パソコンを使う上で様々な作業で使えます。

あなたがもし、Webデザイナーやプログラマーの方であれば、入力チェックや、データのクレンジングなど、業務にも使える場面が多いことでしょう。

私も様々な場面でお世話になっている「正規表現」ですが、はじめに体系的に理解していないと、毎回Webで検索したものをコピペで使い、その意味を理解していない感じでした。なので、これから数回にわたって正規表現をしっかり理解し、自由に使いこなせるようにまとめたいと思います。

 

正規表現を使ってみるには

今どきのテキストエディタの多くは、検索や置換のオプションに「正規表現」が指定できるようになっています。私のよく使うのは、秀丸やサクラエディタ、EmEditorなどですが、いずれもそのようなオプションを持っています。下記はサクラエディタの置換のオプションですが、「正規表現」というのがありますね。ここにチェックが入っていると、通常の完全に一致する文字を検索してきて、置換ではなく、正規表現を使った検索に変更することができます。

検索や置換のオプション

 

お使いのテキストエディタにこのようなオプションがある場合は、オンにすると、いろいろ正規表現を試すことができますので、是非、試してみてください。慣れれば慣れるほど、便利さを実感できると思います。

 

基本的なメタキャラクタ

正規表現では、「メタキャラクタ」という特別な文字を使います。上で出てきた「*」のような文字です。それ以外にもいくつかありますが、初めにきちんと押さえておけば、『^[a-zA-Z0]』こんなのを見た場合でもなんとなく理解できるようになります。

『^』・・・「行頭」 もしくは 「否定」

はじめに押さえておきたいのは、『^』です。山形とも呼ばれることがありますが、使いどころによって2つの意味があります。一つは、「行頭」、もう一つは「否定」の意味です。

行頭・・・単独で使われた場合

行頭

 

『^』が[]と組み合わされずに単独で使われると「行頭」の意味になります。『^』だけ使うとすべての行がマッチしますが、例のように『^T』と指定すると行頭にTのあることろ(図の黄色いところ)がマッチすることになります。

否定・・・[ ]の中で文字の前に使われた場合

否定

ややこしいことに、『^』にはもう一つの意味があります。[](ブラケット)の中で使われると、「^に続けて指定した以外の文字」という否定の意味になるのです。下でも述べますが、[]の中で文字のリストを指定すると、「指定された文字リストのうちのどれか」という意味になりますが、そこに『^』を指定することで、「指定された文字リスト以外の文字のうちのどれか」という意味になります。例でいうと、[a-z]はa~zの英文字のいずれかという意味なので、[^a-z]は、a~zの英文字以外の文字のいずれかという意味になります。そのため、英文字以外のところがすべてヒットして黄色くなっているわけです。すこしややこしいですが、『^』は頻出するため、これを覚えておくと、混乱しないです。

 

『$』・・・行末

前述の『^』と対で覚えておくと便利なのが『$』です。ドル記号ですが、意味は「行末」となります。

行末を表す

行末

 

『$』は概念的な行の末尾を表しますので、そのままだと、すべての行の末尾が当てはまります。そのため、例のようにほかの文字と組み合わせて使うと、特定の文字で終わる行を特定することができます。『^』と『$』を組み合わせると、特定の文字列をタグ(など)で囲むといったことも簡単にできるようになります。

 

『.』・・・「任意の一文字」

『.』はピリオドで、任意の一文字を表します。この任意の文字の中には、英文字、数字、スペース、記号など全部入りますので、「なんでもいいけど、文字数が2文字」みたいなことを簡単に「..」で表現できます。例えば「..c」と表現すると「abc」や「ccc」はヒットしますが「ac」などはヒットしません。

任意の一文字

 

例は、「…e」と指定したので、「任意の3文字の後にeが続く所」がヒットして黄色くなっています。スペースも任意の一文字に数えられることに注意しましょう。

 

『*』・・・「直前の文字の0回以上の繰り返し」

minmax

『*』は正規表現では、単独では用いられません。「直前に指定された文字の0回以上の繰り返し」を表現します。よくWindowsとかで使用するワイルドカードとしての意味ではないので、混乱してしまいますが、正規表現で使用する場合には、直前の文字とセットで初めて意味があると覚えておきましょう。例えば、「a*」は、直前の文字「a」の0回以上の繰り返しを表すので、「」、「a」、「aa」、「aaaaaaaa」のどれにもヒットします。注意したいのは、aがなくてもヒットするということですね。なので、「Apple*」と指定すると、最後の「e」の0回以上の繰り返しなので、「Appl」「Apple」「Appleeeee」等にヒットします。

直前の文字があってもなくてもいいが、ある場合は何個続いてもよい

直前の文字の0回以上の繰り返し

 

例では「p*l」を指定したので、pが0回以上続いた後にl(エル)が続く所がヒットして黄色くなっています。

 

『?』・・・「直前の文字の0回または1回の繰り返し」

minmax『?』は疑問文でもよく目にすることが多いので、混乱しやすいメタキャラクタの一つです。このクエスチョンマークも正規表現では、単独では用いられません。「直前に指定された文字の0回または1回の繰り返し」を表現します。例えば、「a*」は、直前の文字「a」がの0回または1回の繰り返しを表すので、「a」または「aa」のいずれかにヒットします。『*』との違いを分かりやすくするために「Apple?」とすると、「Appl」「Apple」だけにヒットします。最後の文字があいまいなんだけど。。というようなシチュエーションで使える、結構重宝する表現です。要は、「最後の文字はあってもなくてもいいだけど」というようなあいまいな指定ができます。

直前の文字の0回または1回の繰り返しを表す

直前の文字の0回または1回の繰り返し

 

例では「apple?」を指定したので、appleの最後のeが0回または1回続くところがヒットして黄色くなっています。

 

『+』・・・「直前の文字の1回以上の繰り返し」

minmax

『+』は「直前に指定された文字の1回以上の繰り返し」を表現します。つまり、「直前の文字を必ず含むこと!」ということが表現できるわけです。例えば「Apple+」とすると、「Apple」や「Appleeee」にヒットしますが「Appl」にはヒットしません。最後が必ずeで終わるというときの表現です。

直前の文字の1回以上の繰り返しを表す

直前の文字の1回以上の繰り返し

 

例では「apple+」を指定したので、appleの最後がeで終わる単語がヒットします。「allp」はヒットしないので黄色くなっていませんね。

 

『-』・・・「前後の文字の範囲」

minmax『-』はこの前後に指定された範囲の文字すべてを表します。例えば数字1文字を表す正規表現は[0123456789]とも書けますが[0-9]と書いた方が簡潔ですよね。同様に[a-z]は任意の英数字一文字を表現します。すこし注意したいのは、「範囲」を表すのは前後に文字があるときだけで、[-0]や[09-]、-[]、[]- などは通常の「マイナス」という文字を表し、正規表現ではないということです。[ ]の中で文字に挟まれているときだけ、正規表現のメタキャラクタとして認識されると覚えておきましょう。

前後の文字の範囲を表す

前後の文字の範囲

 

例では「apple[0-9]」を指定したので、appleの最後が数字で終わる単語がヒットします。「allpe」は数字なしなのでヒットせず、黄色くなっていませんね。

 

『[ ]』・・・「[ ]の間に記述された文字のうちどれか一文字」

minmax『[』と『]』はブラケットといい、組み合わせて使います。この[ ]の中に文字を羅列すると、その文字のいずれか1つを表現できます。この中には任意の文字を何個でも書けますが、意味するのは、このうちの1字です。つまり、『[abcd]』と書いてあっても、ヒットするのは「a」か「b」か「c」か「d」かです。『[ab]c』と書くと、「ac」または「bc」にヒットするということですね。『[ ]』を理解すると、正規表現の幅がずっと広がります。前述した『-』は『[]』内で範囲を表すのでしたね。つまり、『[a-zA-Z0-9]』と書けば、大文字と小文字の英文字または数字全部のうちの一文字を表現していることになります。注意したいのは、最初に出てきた『^』は、『[]』の中で使われるときだけ、「否定」の意味になるということでした。それ以外のメタキャラクタは、ほとんど、ブラケットの中では単なる文字として認識されます。これをうまく使うと、『[]』で囲ってしまえば、特殊な文字も文字として指定できるということになります。つまり、『[!#$%&’_`/=~]』こんなのが出てきたとしても、「この文字のうちのどれか一文字」を表現しているにすぎません。

前後の文字の範囲を表す

前後の文字の範囲

 

例では「p[ep]」を指定したので、peまたはppにヒットしています。

 

『|』・・・「|の前後に記述された文字のうちどれか一方」

minmax『|』は前後に指定された文字列のどちらかにマッチします。例えば『a|b』は「a」または「b」のどちらか一方だということです。注意したいのは、前後の文字が1文字でも複数文字でもそれ全体がヒットするということです。つまり、『ap|ple』は、「ap」または「ple」にヒットするということです。では、一文字だけを指定したい場合はどうすればいいのでしょうか。正規表現では、効果の範囲をしてするのに、『()』を使います。例えば、『k(o|a)ito』とすると、「koito」または「kaito」にマッチすることになります。

前後の文字のどれか一方を表す

前後の文字のどれか一方

 

例では「Apple|pen」を指定したのでappleまたはpenにヒットしています。

 

『()』・・・「()の間の正規表現をひとまとまりとしてとらえる(グループ化)」

『(』と『)』はこれらに囲まれた正規表現を一つのまとまりとして定義する場合に使われます。よく使われるのは、上で出てきた『|』の前後に指定された文字列の範囲を指定する場合や、後方参照とよばれるプログラムの中です。

グループ化

グループ化

 

例では「A(pple|)pen」を指定したので、「pple」または「空文字」のいずれかとなるので、ApplepenまたはApenにヒットしています。

 

『\b』・・・「単語境界」

『\b』は単語の境界を表します。例えば、「This is a pen.」という文章があった場合、単純に「is」を指定すると、「This」と「is」の両方の「is」にマッチしてしまいますね。後者の「is」だけを指定したい場合には、どうすればいいでしょうか。そんな時に使えるのが『\b』です。単語と単語の間の空白を意味しますので、「\bis」と指定したら、後者の「is」だけにマッチすることになります。

単語境界

単語境界

 

解説したのと同様、Thisのisにはヒットせず、後ろのisが黄色くなっているのが分かります。

 

『{min,max}』・・・「繰り返し数の範囲」

minmax上で『+』が出てきたとき、「一回以上の繰り返し」ということでした。1回以上ということですので、100回でも1000回でもマッチするのですが、さすがにそこまでの一致は少ない場合が多いでしょう。『{min,max}』を使うとその繰り返しの回数を指定できます。例えば、『a{3,5}』と指定すると、aの3回から5回までの繰り返しにマッチします。なお、minとmaxは必ずしも両方指定する必要はありません。また、一方だけ指定した時、カンマを付けるかつけないかで意味が変わってきます。例を挙げると、『a{2}』は「aの2回の繰り返し」にマッチします。『a{2,}』は「aの2回以上の繰り返し」という意味になります。『a{,2}』だと、0回以上、2回までの繰り返しになるというわけです。

繰返し範囲

繰返し範囲

 

例では『ap{2,3}le』と指定したので、pが2または3つある単語にヒットしてるのが分かりますね。

 

基本メタキャラクタまとめ

メタキャラクタ 読み方 意味
^ キャレット,山形 「行頭」 もしくは 「否定」
$ ドルマーク 行末
. ピリオド 任意の一文字
* アスタリスク 直前の文字の0回以上の繰り返し
? クエスチョンマーク 直前の文字の0回または1回の繰り返し
+ プラス 直前の文字の1回以上の繰り返し
マイナス 前後の文字の範囲
[] ブラケット [ ]の間に記述された文字のうちどれか一文字
| 縦一文字 |の前後に記述された文字のうちどれか一方
() カッコ ()の間の正規表現をひとまとまりとしてとらえる(グループ化)
\b 円マークとb 単語境界
{min,max} 繰り返し数の範囲
Viewing all 247 articles
Browse latest View live