PHPでMailChimpAPIを使用する

# MailChimpとは

[MailChimp](https://mailchimp.com)
メールの一斉送信系のタスクを全般的に行うことができるクラウド型サービスです。
特徴としては、

- GUIが充実しているので非エンジニアでも容易に操作可能（ただ英語）
- well-formedなHTMLメールをGUI上で簡単に作成可能
- 一斉送信について、条件を用いた細かいグループ作成やスケジューリングが可能
- もちろんメールの開封状況やコンバージョンはトラッキング可能！

といいことづくめです。そして何と言っても

- APIが充実しており、既存のWebシステムとの連携が可能

というのが大きい。つまり、 **今まで自社サービス上で自前で作成していたメール一斉送信系の仕組みが、丸ごとMailChimpに任せられる** ということです！これは入れない手はありませんね。

参考：
[無料から使えるメール配信サービスMailChimpが本当に凄い](http://www.loftwork.jp/column/2013/20131010_mailchimp.aspx)
[Developer | MailChimp](https://developer.mailchimp.com)

今回は、PHP+CakePHP3環境でMailChimpの連携を実際に行いましたので、その際のポイントなどをまとめます。CakePHPで実装していますが、内容的にはPHP環境共通で使えるものかと思います。

# 公式Composerライブラリ

PHPでMailChimpAPIを使用する場合は、MailChimp公式でComposerライブラリが出ているので、こちらを使うのがオススメです。それなりに完成度も高く、今のところはメンテされている印象です。

[mailchimp/mailchimp](https://packagist.org/packages/mailchimp/mailchimp)

このライブラリ自体のドキュメントはなさげなのですが、Githubリポジトリにサンプルプログラムがあるので、これを参考にしてね！とのこと。
[mailchimp/mcapi2-php-examples](https://github.com/mailchimp/mcapi2-php-examples)

# 実際に使ってみた

## やること
今回は、

- **既存Webサービスの登録ユーザー情報を、MailChimpのList(メールグループ)として1日一回バッチ連携する**

という処理を行います。


## APIキーを作成する

MailChimpのコンソールから
右上のユーザーアイコン　→　Profile → Extras -> ApiKey 
からAPIキーが発行できます。

## Listを作成し、Listのユニークキーをチェック
今回はサービスと連携するList作成自体はコンソール上から行います。
グローバルメニューの[List]->右上の[CreateList]
からダイアログに従ってリストを作成します。

List作成後、作成されたListの▼メニューから
[Settings] → [List name & defaults] 
を選択すると、画面右側の[ListID]という項目内に

> Typically, this is what they want: **********.

という項目があるので、**********部分がそのListを表すキーになります。

## ListのFieldsを作成する

連携情報の核となるのはもちろんメールアドレスですが、メールアドレス以外にも、ユーザーの氏名や登録日なども付加情報として連携したいですよね。

作成したListの画面から
[Settings] -> [List fields and \*|MERGE|\* tags]
を選択します。

追加フィールドの編集画面が表示されるので、

<img width="1239" alt="スクリーンショット 2017-02-08 11.38.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/130321/fc0e61cd-a4d7-c40b-2fb8-01e9a863df70.png">

こんな感じで関連情報を登録します。
ポイントは[Put this tag in your content]の部分で、ここに入力された情報が、APIで付加情報を入力する際のキー文字列になります。

これでコンソール上の設定は終わり。次はいよいよPHP側の実装です。

## PHP上からライブラリ経由でAPIを叩く

以下、サンプルコードです。（実際はwrapperクラスをComponentで作っていますが、わかりやすいように手続き型コードに書き換えています。）

```php:mailchimpShell.php
namespace App\Shell;

use Cake\Console\Shell;
use Mailchimp;

class mailchimpShell extends Shell
{
    public function main() 
    {
        $mailchimp = new MailChimp("##API KEY##");
        $user = $this->Users->find()->first(); // ユーザー情報を取得
        
        $res = $mailchimp->lists->batchSubscribe(
            "##LIST KEY##", //作成したLISTのキーを指定
            [
                [
                    "email" => [
                        'email' => $user->email,
                    ],
                    'email_type' => 'text',
                    'merge_vars' => [
                        'USER_ID' => $user->id,
                        'NAME_SEI' => $user->name_sei,
                        'NAME_MEI' => $user->name_mei,
                        'CREATED' => $user->created->format('m/d/Y')
                    ]
                ]
                /* 以下、繰り返せば複数メアドを登録可能 */
            ],
            false, // double_optin
            true // update_existing         
        );
        
        // エラーがあった場合はログ出力
        if($res['error_count'] > 0){
            Log::error($res['errors']);
        }

        return true;
    }

}

```


以下、実装に当たっての細かいポイントです。

- useのエイリアス指定は`mailchimp/mailchimp`ではなく`mailchimp`でOK
- APIは `Mailchimp::[リソース名]::[アクション]()` の順番で指定する
  - リソース名ごとにサブクラスがあります。Listであれば `vendor/mailchimp/mailchimp/src/mailchimp/Lists.php` に実装されているpublicメソッドがそのまま使えるエンドポイントです。
  - このメソッド名が[公式APIリファレンス](https://developer.mailchimp.com/documentation/mailchimp/reference/overview/)　に書かれているエンドポイントと微妙に異なっているのが非常にわかり難い。
- 第3引数(double_optin)は基本的にfalseにする
  - デフォルト値はtrueで、その場合は登録したメールアドレス宛に、Mailchimpからリスト登録承認メールが飛んでしまいます。しかも英語です。
- 第4引数(update_existing)をtrueにした場合、メールアドレスをキー情報として、すでに登録されているメールアドレスに対しては更新処理が行われる(いわゆるupsert処理)
  - ただし、コンソール上やユーザー側からの配信停止依頼によって`unsubscribe(配信停止)` ステータスになっているメールアドレスに対しては、今回のAPI呼び出しによって**再度配信可能になることはない**
- 項目として日時設定を送る場合は、Fields作成時に指定した書式(今回はMM/DD/YYYY)に合わせる

などなどです。
API呼び出しパターンはかなり汎用的に作られているので、今回のコードを応用するれば、コンソールで行える操作はことはシステム側からでも制御できることになります。夢が広がりますね！