Skip to content

Commit adc9f03

Browse files
committed
Add support for webhooks
1 parent 940d432 commit adc9f03

13 files changed

Lines changed: 633 additions & 31 deletions

File tree

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ You make a request to the API which it triggers your android phone to send an SM
99

1010
Quick Start Guide 👉 [https://docs.httpsms.com](https://docs.httpsms.com)
1111

12-
1312
<img width="1115" alt="header" src="https://user-images.githubusercontent.com/4196457/194767449-f12d84a0-22f1-4787-afb2-17398fb459f6.png">
1413

1514
## Why?
@@ -49,6 +48,11 @@ sending and receiving SMS messages.
4948

5049
## Features
5150

51+
### Webhook
52+
53+
If you want to build advanced integrations, we support webhooks. The httpSMS platform can forward SMS messages received
54+
on the android phone to your server using a callback URL which you provide.
55+
5256
### Back Pressure
5357

5458
In-order not to abuse the SMS API on android, you can set a rate limit e.g 3 messages per minute. Such that even if you

api/pkg/entities/webhook.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ type Webhook struct {
1313
UserID UserID `json:"user_id" example:"WB7DRDWrJZRGbYrv2CKGkqbzvqdC"`
1414
URL string `json:"url" example:"https://example.com"`
1515
SigningKey string `json:"signing_key" example:"DGW8NwQp7mxKaSZ72Xq9v67SLqSbWQvckzzmK8D6rvd7NywSEkdMJtuxKyEkYnCY"`
16-
Events pq.StringArray `json:"events" example:"[message.phone.received]" gorm:"type:string[]"`
16+
Events pq.StringArray `json:"events" example:"[message.phone.received]" gorm:"type:text[]" swaggertype:"array,string"`
1717
CreatedAt time.Time `json:"created_at" example:"2022-06-05T14:26:02.302718+03:00"`
1818
UpdatedAt time.Time `json:"updated_at" example:"2022-06-05T14:26:10.303278+03:00"`
1919
}

api/pkg/handlers/webhook_handler.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func (h *WebhookHandler) RegisterRoutes(app *fiber.App, middlewares ...fiber.Han
5757
// @Param skip query int false "number of webhooks to skip" minimum(0)
5858
// @Param query query string false "filter webhooks containing query"
5959
// @Param limit query int false "number of webhooks to return" minimum(1) maximum(20)
60-
// @Success 200 {object} responses.Ok[entities.Webhook]
60+
// @Success 200 {object} responses.WebhooksResponse
6161
// @Failure 400 {object} responses.BadRequest
6262
// @Failure 401 {object} responses.Unauthorized
6363
// @Failure 422 {object} responses.UnprocessableEntity
@@ -133,7 +133,7 @@ func (h *WebhookHandler) Delete(c *fiber.Ctx) error {
133133
// @Accept json
134134
// @Produce json
135135
// @Param payload body requests.WebhookStore true "Payload of the webhook request"
136-
// @Success 200 {object} responses.Ok[entities.Webhook]
136+
// @Success 200 {object} responses.WebhookResponse
137137
// @Failure 400 {object} responses.BadRequest
138138
// @Failure 401 {object} responses.Unauthorized
139139
// @Failure 422 {object} responses.UnprocessableEntity
@@ -177,7 +177,7 @@ func (h *WebhookHandler) Store(c *fiber.Ctx) error {
177177
// @Produce json
178178
// @Param webhookID path string true "ID of the webhook" default(32343a19-da5e-4b1b-a767-3298a73703ca)
179179
// @Param payload body requests.WebhookUpdate true "Payload of webhook details to update"
180-
// @Success 200 {object} responses.PhoneResponse
180+
// @Success 200 {object} responses.WebhookResponse
181181
// @Failure 400 {object} responses.BadRequest
182182
// @Failure 401 {object} responses.Unauthorized
183183
// @Failure 422 {object} responses.UnprocessableEntity
@@ -198,7 +198,7 @@ func (h *WebhookHandler) Update(c *fiber.Ctx) error {
198198
if errors := h.validator.ValidateUpdate(ctx, request.Sanitize()); len(errors) != 0 {
199199
msg := fmt.Sprintf("validation errors [%s], while updating user [%+#v]", spew.Sdump(errors), request)
200200
ctxLogger.Warn(stacktrace.NewError(msg))
201-
return h.responseUnprocessableEntity(c, errors, "validation errors while updating user")
201+
return h.responseUnprocessableEntity(c, errors, "validation errors while updating webhook")
202202
}
203203

204204
user, err := h.service.Update(ctx, request.ToUpdateParams(h.userFromContext(c)))

api/pkg/repositories/gorm_webhook_repository.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func (repository *gormWebhookRepository) LoadByEvent(ctx context.Context, userID
6969
defer span.End()
7070

7171
webhooks := make([]*entities.Webhook, 0)
72-
err := repository.db.WithContext(ctx).Where("user_id = ?", userID).Where("? = ANY(events)", event).Find(webhooks).Error
72+
err := repository.db.Raw("SELECT * FROM webhooks WHERE user_id = ? AND CAST(? as TEXT) = ANY(events)", userID, event).Scan(&webhooks).Error
7373
if err != nil {
7474
msg := fmt.Sprintf("cannot load webhooks for user with ID [%s] and event [%s]", userID, event)
7575
return nil, repository.tracer.WrapErrorSpan(span, stacktrace.Propagate(err, msg))
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package responses
2+
3+
import "github.com/NdoleStudio/httpsms/pkg/entities"
4+
5+
// WebhookResponse is the payload containing entities.Webhook
6+
type WebhookResponse struct {
7+
response
8+
Data entities.Webhook `json:"data"`
9+
}
10+
11+
// WebhooksResponse is the payload containing []entities.Webhook
12+
type WebhooksResponse struct {
13+
response
14+
Data []entities.Webhook `json:"data"`
15+
}

0 commit comments

Comments
 (0)