Amazon API Gateway + AWS Lambdaで、iOSでの定期購読をリアルタイムでSlackへ投稿する


2017年7月18日のnewsで、[自動更新登録を含むすべてのレシートに、カスタマーの登録のステータスに関するリアルタイムの情報が含まれるように](https://itunespartner.apple.com/jp/apps/news/45333106?sc_cid=ITC-AP-ENREC)、なったためリアルタイムでslack通知するためにサクッと作りました。
Amazon API Gateway + AWS Lambda のレシピ用意されてて簡単だったので、ぜひ :roller_coaster: 

## 構成

![server-notifications.jpeg](https://qiita-image-store.s3.amazonaws.com/0/61340/775bb7b6-d12e-3946-b5ba-f9ebfdd5beba.jpeg "server-notifications.jpeg")

1. iTunes Connect 
	- Server notifications for auto-renewable subscriptions
2. Amazon API Gateway
3. AWS Lambda
4. Slack

## Lambda 準備
Amazon API Gateway + AWS Lambda の構成はレシピ用意されている。
今回は、python3.6のfunctionを利用（node.js・python2.7も用意されている）

## Lambda code

Webhook URLを取得して以下のコード
http://qiita.com/vmmhypervisor/items/18c99624a84df8b31008

```
import json
import urllib.request
import time

print('Loading function')

def respond(err, res=None):
    return {
        'statusCode': '400' if err else '200',
        'body': err.message if err else json.dumps(res),
        'headers': {
            'Content-Type': 'application/json',
        },
    }
    
class Receipt:
    def __init__(self, params):
    	 # 必要に応じて追加する
        self.notification_type = params['notification_type']
        self.product_id        = params['latest_receipt_info']['product_id']
        self.bid               = params['latest_receipt_info']['bid']

def send_slack(channel, receipt): 
    # slack webhook URLは入れ替え 
    url = 'https://hooks.slack.com/services/xxxxxxxxx/xxxxxxxxxxx'
    attachments = [
            {
                "fallback": "iOS Subscription Report",
                "color": "#36a64f",
                "author_name": "mikan",
                "author_link": "http://mikan.link",
                "author_icon": "http://flickr.com/icons/bobby.jpg",
                "title": "購読レポート",
                "text": "App: " + receipt.bid,
                "fields": [
                    {
                        "title": "購読",
                        "value": receipt.notification_type,
                        "short": False
                    },
                    {
                        "title": "商品id",
                        "value": receipt.product_id,
                        "short": False
                    }
                ],
                "image_url": "http://my-website.com/path/to/image.jpg",
                "thumb_url": "http://example.com/path/to/thumb.png",
                "footer": "Server notifications for auto-renewable subscriptions",
                "footer_icon": "https://platform.slack-edge.com/img/default_application_icon.png",
                "ts": time.time()
            }
        ]
    params = {"channel": channel, "username": "dekopon", "attachments": attachments}
    params = json.dumps(params).encode("utf-8")
    req = urllib.request.Request(url, data=params, method="POST")
    res = urllib.request.urlopen(req)

def lambda_handler(event, context):
    params = json.loads(json.dumps(event))
    body = params['body']
    receipt = Receipt(json.loads(body))
    send_slack("playground", receipt)
    return respond(None, "Post slack successfully!")
```

## 処理できるかテスト
以下のような方法で、jsonをPOSTしてみてテスト
sample jsonは記事下部に掲載しておきました。

- Lambdaでテストイベントを設定して実行
- curlやDHCでPOST実行

## Subscription Status URL を設定
iTunes ConnectのMy Appsから、対象アプリを選択して、Subscription Status URLに作成したAPI GateWayのエンドポイントを指定
`App Store` → `App Information` → `Subscription Status URL`


https://help.apple.com/itunes-connect/developer/#/dev0067a330b


## あとは購読してもらえるものを作り込みましょう :rocket: 

## sample json

```
{
    "body": {
        "auto_renew_product_id": "link.mikan.sub.sample", 
        "auto_renew_status": "true", 
        "environment": "PROD", 
        "latest_receipt": "xxxxxxxxx", 
        "latest_receipt_info": {
            "app_item_id": "xxxxxxxxx", 
            "bid": "link.mikan.sample", 
            "bvrs": "1", 
            "expires_date": "123456", 
            "expires_date_formatted": "2017-09-05 22:19:54 Etc/GMT", 
            "expires_date_formatted_pst": "2017-09-05 15:19:54 America/Los_Angeles", 
            "item_id": "xxxxxxxxx", 
            "original_purchase_date": "2017-08-05 22:19:56 Etc/GMT", 
            "original_purchase_date_ms": "1501971596000", 
            "original_purchase_date_pst": "2017-08-05 15:19:56 America/Los_Angeles", 
            "original_transaction_id": "730000169590752", 
            "product_id": "link.mikan.sub.sample", 
            "purchase_date": "2017-08-05 22:19:54 Etc/GMT", 
            "purchase_date_ms": "1501971594000", 
            "purchase_date_pst": "2017-08-05 15:19:54 America/Los_Angeles", 
            "quantity": "1", 
            "transaction_id": "xxxxxxxxx", 
            "unique_identifier": "xxxxxxxxx", 
            "unique_vendor_identifier": "xxxxxxxxx", 
            "version_external_identifier": "xxxxxxxxx", 
            "web_order_line_item_id": "xxxxxxxxx"
        }, 
        "notification_type": "INITIAL_BUY", 
        "password": "xxxxxxxxx"
    }
}
```


## 参考

[Lambda 関数を公開するための API を作成する](http://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/getting-started.html)
[Amazon API Gatewayを使ってAWS LambdaをSDKなしでHTTPS越しに操作する](http://dev.classmethod.jp/cloud/aws/lambda-restful-api-by-using-api-gateway/)
[Advanced StoreKit - WWDC 2017 - Videos - Apple Developer](https://developer.apple.com/videos/play/wwdc2017/305/)