Go+ AWS SNSを使ってSMSを送信する

# はじめに
個人開発で作成しているアプリケーションの認証にSMSを使いたかったので、何やらややこしいですが『Go + AWS SNS』という組み合わせで、SMS送信を実現しました。今回はそのまとめです。
実際のコードで確認したい方は[こちら](https://github.com/atEaE/golang-aws-sdk-example)からどうぞ。

# 実行環境
- macOS Catalina 10.15.2
- golang 1.13.0
- Visual Studio Code

# AWS SNSって何？
Amazon Simple Notification Service(Amazon SNS)自体の説明は私の拙文を参考にするよりも、[公式](https://docs.aws.amazon.com/ja_jp/sns/latest/dg/welcome.html)を参考にした方が理解が進むと思いますので、ざっくりと説明します。
読んで字の如く『シンプルな通知機能を提供するサービス』です。私からは『何かしらの通知ができるサービス』というざっくりしたことを覚えておいてもらえれば、今のところはOKです。


# 接続クライアントの生成
まずはSNSと接続するための接続クライアントのインスタンスを生成していきます。
### AWS CLIをインストールしてLOCALのCredentialsを使用する場合
```snssms.go
package snssms

import (
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/sns"
)

// ~/.aws/credentialsの情報を使ってクライアントを生成
func GetClient() (*sns.SNS, error) {   
        sess := session.Must(session.NewSessionWithOptions(session.Options{
            SharedConfigState: session.SharedConfigEnable,
        }))

	return sns.New(sess), nil
}
```

### アクセスキーを明示的に指定して生成
```snssms.go
package snssms

import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/sns"
)

// AWS_ACCESS_KEY(アクセスキー) : acsId
// AWS_SECRET_ACCESS_KEY(シークレットアクセスキー) : secId
// REGION(リージョン) : reg
func GetClient(acsId string, secId string, reg string) (*sns.SNS, error) {
	creds := credentials.NewStaticCredentials(acsId, secId, "")
	sess, err := session.NewSession(&aws.Config{
		Credentials: creds,
		Region:      aws.String(reg),
	})

	if err != nil {
		return nil, err
	}

	return sns.New(sess), nil
}
```
これで接続クライアントの準備はできました。
次にメッセージの生成を行います。

# インプットメッセージの生成
先程と同じ`snssms.go`にインプットメッセージ作成のロジックを追加します。

```snssms.go
package snssms

import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/sns"
)

...
..
.

// 送信メッセージ、送信対象の電話番号を引数にとり、PublishInputのインスタンスを返却する
func CreateInputMessage(msg string, phoneNum string) *sns.PublishInput {
	pin := &sns.PublishInput{}
	pin.SetMessage(msg)
	pin.SetPhoneNumber(phoneNum)
	return pin
}

```
送信メッセージ、送信対象の電話番号を引数にとり、PublishInputのインスタンスを返却するメソッド作成します。
基本的な前準備はこれで終了です。

# 送受信の確認
最後に今まで作成したメソッドを使って、メッセージの送信と受信を確認します。

```main.go
package main

import (
	"fmt"

	snssms "github.com/atEaE/golang-aws-sdk-sample/internal/aws/sns-sms"
)

func main () {
    // まずは接続クライアントの生成
    client, err := snssms.GetClient("AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY_ID", "REGION")
	if err != nil {
		fmt.Errorf("Error: %v", err)
	}

    // ポイントは電話番号入力時に国コードを入力することです。今回は日本を想定して、[+81]を設定します。
    msgIn := snssms.CreateInputMessage("TestMessage", "+81XXXXXXXXXXX")

	result, err := client.Publish(msgIn)
	if err != nil {
		fmt.Errorf("Error: %v", err)
	}

	fmt.Printf("Result: %s", result.String())
}
```

後は実行するだけです。
実行後にTerminalに`Message Id`が表示されます。

```shell
$ go run main.go
Result: {
  MessageId: "28db4394-c8ee-576f-bb6e-15182293a0d8"
}
```
![IMG_0458.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198150/15874748-79df-7930-d1c0-39edf1486a8a.png)

テストメッセージの受信を確認できました！


# 参考・引用
- [AWS SDK for Go API Reference -SNS-](https://docs.aws.amazon.com/sdk-for-go/api/service/sns/)
- [Amazon SNS 開発者ガイド -SMS メッセージの送信-](https://docs.aws.amazon.com/ja_jp/sns/latest/dg/sms_publish-to-phone.html)