生態系のサポート。 Golangでユーザー登録を自動化する

何してるの?


私たちのチームは、REST APIを介してモバイルデバイスに通知を送信するためのソフトウェアプラットフォームを開発しています。 現在、これらはiOSデバイス用のプッシュ通知であり、 Twilioとの統合によるSMSのおかげです。 サポートプロセスとユーザーコミュニティを整理するために、多くの情報システムとサービスが選択されました(下のリストを参照)。これにより、私たちの観点からは、最短時間で最小限の労力で問題を解決することができました。


タスク


次のアクションを自動化します。



使用済みシステム(およびその目的)


次のすべての情報システムとサービスには、タスクを解決できるREST APIインターフェイスがあります。



プロセスの説明


私たちの場合、次のイベントは網羅的です:


  1. ソフトウェア製品をダウンロードする場合、ユーザーリクエストを記録するためにシステムにユーザーを作成する必要があります。また、コミュニティポータルに招待状を送信する必要があります
  2. 商用サポートを有効にする場合、ユーザーをユーザーアピールの適切なグループに追加する必要があります
  3. 商用サブスクリプションの有効期限が切れたら、対応するグループからユーザーを削除する必要があります

実装


まず、上記のすべてのプロセスイベントのソースは、 Paddleプラットフォーム、つまりサブシステムのEvents / Alertsです。 特定のイベントが発生すると、Paddleは(サーバーの)事前に定義されたURLへのPOSTリクエストを開始します。
処理するイベント:



パドル側からのリクエストには、次の情報が含まれます(パドル側からのリクエストの内容は、上記のイベントによって異なる場合がありますが、私たちにとって関心のある要素はどのような場合でも変わりません)。


{ "method": "POST", "data": { "alert_id": "XXXXXX", "alert_name": "subscription_created", "cancel_url": "https://checkout.paddle.com/subscription/cancel?XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "currency": "USD", "email": "name@example.com", "event_time": "2016-08-05 13:26:06", "next_bill_date": "2017-08-05", "passthrough": "", "status": "active", "subscription_id": "XXXXXX", "subscription_plan_id": "XXXXXX", "update_url": "https://checkout.paddle.com/subscription/update?XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "p_signature": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" } } 

応答でHTTP 200 OKが期待されます


 { "http_code": 200, "redirect_url": "", "content_type": "text/plain; charset=utf-8", "total_time": 1.018837 } 

応答がHTTP 200 OKと異なる場合、パドルは1時間に1回の間隔で72時間にわたって2番目の要求をサーバーに送信します。


上記のPaddleからのリクエストでは、情報システムにユーザーを登録するために使用するalert_nameおよびemailパラメーターに興味があります。


パドルからのリクエストの解析


 type Event struct { AlertName string `form:"alert_name" binding:"required"` Email string `form:"email" binding:"required"` Status string `form:"status"` SubscriptionId int `form:"subscription_id"` OrderId string `form:"order_id"` SubscriptionPlanId int `form:"subscription_plan_id"` Country string `form:"country"` Fee float32 `form:"fee"` Currency string `form:"currency"` Psignature string `form:"p_signature"` Passthrough string `form:"passthrough"` PaymentMethod string `form:"payment_method"` PaymentTax float32 `form:"payment_tax"` SaleGross float32 `form:"sale_gross"` Earnings float32 `form:"earnings"` EventTime string `form:"event_time"` NextBillDate string `form:"next_bill_date"` } func (e *Event) ToFields() (fields log.Fields) { fields = make(log.Fields) fields["alert_name"] = e.AlertName fields["email"] = e.Email fields["status"] = e.Status fields["subscription_id"] = e.SubscriptionId fields["order_id"] = e.OrderId fields["subscription_plan_id"] = e.SubscriptionPlanId fields["country"] = e.Country fields["fee"] = e.Fee fields["currency"] = e.Currency fields["p_signature"] = e.Psignature fields["passthrough"] = e.Passthrough fields["payment_method"] = e.PaymentMethod fields["payment_tax"] = e.PaymentTax fields["sale_gross"] = e.SaleGross fields["earnings"] = e.Earnings fields["event_time"] = e.EventTime fields["next_bill_date"] = e.NextBillDate return } 

イベントに応じてリクエストのルーティングを実行します


 func eventPOST(c *gin.Context) { status := []bool{} c.Bind(&event) log.WithFields(event.ToFields()).Info("Processing event") switch event.AlertName { case "subscription_created": status = append(status, InviteToJira(event.Email)) status = append(status, AddToJiraGroup(event.Email)) status = append(status, InviteToSlack(event.Email)) case "payment_succeeded": status = append(status, InviteToJira(event.Email)) status = append(status, InviteToSlack(event.Email)) case "subscription_cancelled": status = append(status, RemoveFromJiraGroup(event.Email)) default: status = append(status, false) log.WithFields(log.Fields{ "event": event.AlertName, }).Error("Unknown event") } for _, s := range status { if s == false { c.String(http.StatusInternalServerError, "not Ok\n") return } } c.String(http.StatusOK, "Ok\n") return } 

さらに、受信したイベントに応じて、それらを適切に処理します。


Slackにユーザーを招待する(コミュニティポータル)


 func InviteToSlack(username string) bool { api := slack.New(Conf.Slack.Token) err := api.InviteToTeam(Conf.Slack.Team, "", "", username) if err != nil { if strings.Contains(err.Error(), "already_in_team") { log.WithFields(log.Fields{ "user": username, "slack_team": Conf.Slack.Team, }).Warn("User already in Slack team") return true } else if strings.Contains(err.Error(), "already_invited") { log.WithFields(log.Fields{ "user": username, "slack_team": Conf.Slack.Team, }).Warn("User already invited to Slack") return true } log.Error(err) return false } log.WithFields(log.Fields{ "user": username, }).Warn("User successfuly invited to Slack") return true } 

Jiraでのユーザーの招待/登録(ユーザーのリクエストの登録システム)


 func InviteToJira(username string) bool { jira := jira.New(Conf.Jira.Host, Conf.Jira.User, Conf.Jira.Password, false) _, err := jira.GetUser(username) if err != nil { if err.Error() == "Not Found" { ok, err := jira.InviteSdUser(username, Conf.Jira.Invite_uri) if ok { log.WithFields(log.Fields{ "user": username, }).Info("Invited user to JIRA") return true } else { log.WithFields(log.Fields{ "user": username, "error": err, }).Error("Invite to JIRA Failed") return false } } else { log.Error(err) return false } } log.WithFields(log.Fields{ "user": username, }).Warn("User already Invited to JIRA") return true } 

ユーザーをJiraグループに追加します(商用サポート)


 func AddToJiraGroup(username string) bool { jira := jira.New(Conf.Jira.Host, Conf.Jira.User, Conf.Jira.Password, false) ok, err := jira.AddToGroup(username, Conf.Jira.Invite_group) if ok { log.WithFields(log.Fields{ "user": username, "group": Conf.Jira.Invite_group, }).Info("Added user to Jira Group") return true } else { log.WithFields(log.Fields{ "user": username, "group": Conf.Jira.Invite_group, "error": err, }).Error("Failed to add user to Jira Group") return false } } 

Jiraグループからユーザーを削除する(商用サポート)


 func RemoveFromJiraGroup(username string) bool { jira := jira.New(Conf.Jira.Host, Conf.Jira.User, Conf.Jira.Password, false) ok, err := jira.RemoveFromGroup(username, Conf.Jira.Invite_group) if ok { log.WithFields(log.Fields{ "user": username, "group": Conf.Jira.Invite_group, }).Info("Removed user from Jira Group") return true } else { log.WithFields(log.Fields{ "user": username, "group": Conf.Jira.Invite_group, "error": err, }).Error("Failed to remove User from Jira Group") return false } } 

使用済みモジュール(基本)



おわりに


上記のソリューションのソースコードはGitHubで入手できます: paddle-endpoint


ご清聴ありがとうございました!



Source: https://habr.com/ru/post/J307344/


All Articles