github.com/plutov/paypal/v4@v4.7.1/webhooks.go (about) 1 package paypal 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "errors" 8 "fmt" 9 "io" 10 "net/http" 11 ) 12 13 // CreateWebhook - Subscribes your webhook listener to events. 14 // Endpoint: POST /v1/notifications/webhooks 15 func (c *Client) CreateWebhook(ctx context.Context, createWebhookRequest *CreateWebhookRequest) (*Webhook, error) { 16 req, err := c.NewRequest(ctx, http.MethodPost, fmt.Sprintf("%s%s", c.APIBase, "/v1/notifications/webhooks"), createWebhookRequest) 17 webhook := &Webhook{} 18 if err != nil { 19 return webhook, err 20 } 21 22 err = c.SendWithAuth(req, webhook) 23 return webhook, err 24 } 25 26 // GetWebhook - Shows details for a webhook, by ID. 27 // Endpoint: GET /v1/notifications/webhooks/ID 28 func (c *Client) GetWebhook(ctx context.Context, webhookID string) (*Webhook, error) { 29 req, err := c.NewRequest(ctx, http.MethodGet, fmt.Sprintf("%s%s%s", c.APIBase, "/v1/notifications/webhooks/", webhookID), nil) 30 webhook := &Webhook{} 31 if err != nil { 32 return webhook, err 33 } 34 35 err = c.SendWithAuth(req, webhook) 36 return webhook, err 37 } 38 39 // UpdateWebhook - Updates a webhook to replace webhook fields with new values. 40 // Endpoint: PATCH /v1/notifications/webhooks/ID 41 func (c *Client) UpdateWebhook(ctx context.Context, webhookID string, fields []WebhookField) (*Webhook, error) { 42 req, err := c.NewRequest(ctx, http.MethodPatch, fmt.Sprintf("%s/v1/notifications/webhooks/%s", c.APIBase, webhookID), fields) 43 webhook := &Webhook{} 44 if err != nil { 45 return webhook, err 46 } 47 48 err = c.SendWithAuth(req, webhook) 49 return webhook, err 50 } 51 52 // ListWebhooks - Lists webhooks for an app. 53 // Endpoint: GET /v1/notifications/webhooks 54 func (c *Client) ListWebhooks(ctx context.Context, anchorType string) (*ListWebhookResponse, error) { 55 if len(anchorType) == 0 { 56 anchorType = AncorTypeApplication 57 } 58 req, err := c.NewRequest(ctx, http.MethodGet, fmt.Sprintf("%s%s", c.APIBase, "/v1/notifications/webhooks"), nil) 59 q := req.URL.Query() 60 q.Add("anchor_type", anchorType) 61 req.URL.RawQuery = q.Encode() 62 resp := &ListWebhookResponse{} 63 if err != nil { 64 return nil, err 65 } 66 67 err = c.SendWithAuth(req, resp) 68 return resp, err 69 } 70 71 // DeleteWebhook - Deletes a webhook, by ID. 72 // Endpoint: DELETE /v1/notifications/webhooks/ID 73 func (c *Client) DeleteWebhook(ctx context.Context, webhookID string) error { 74 req, err := c.NewRequest(ctx, http.MethodDelete, fmt.Sprintf("%s/v1/notifications/webhooks/%s", c.APIBase, webhookID), nil) 75 if err != nil { 76 return err 77 } 78 79 err = c.SendWithAuth(req, nil) 80 return err 81 } 82 83 // VerifyWebhookSignature - Use this to verify the signature of a webhook recieved from paypal. 84 // Endpoint: POST /v1/notifications/verify-webhook-signature 85 func (c *Client) VerifyWebhookSignature(ctx context.Context, httpReq *http.Request, webhookID string) (*VerifyWebhookResponse, error) { 86 type verifyWebhookSignatureRequest struct { 87 AuthAlgo string `json:"auth_algo,omitempty"` 88 CertURL string `json:"cert_url,omitempty"` 89 TransmissionID string `json:"transmission_id,omitempty"` 90 TransmissionSig string `json:"transmission_sig,omitempty"` 91 TransmissionTime string `json:"transmission_time,omitempty"` 92 WebhookID string `json:"webhook_id,omitempty"` 93 Event json.RawMessage `json:"webhook_event,omitempty"` 94 } 95 96 // Read the content 97 var bodyBytes []byte 98 if httpReq.Body != nil { 99 bodyBytes, _ = io.ReadAll(httpReq.Body) 100 } else { 101 return nil, errors.New("Cannot verify webhook for HTTP Request with empty body.") 102 } 103 // Restore the io.ReadCloser to its original state 104 httpReq.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) 105 106 verifyRequest := verifyWebhookSignatureRequest{ 107 AuthAlgo: httpReq.Header.Get("PAYPAL-AUTH-ALGO"), 108 CertURL: httpReq.Header.Get("PAYPAL-CERT-URL"), 109 TransmissionID: httpReq.Header.Get("PAYPAL-TRANSMISSION-ID"), 110 TransmissionSig: httpReq.Header.Get("PAYPAL-TRANSMISSION-SIG"), 111 TransmissionTime: httpReq.Header.Get("PAYPAL-TRANSMISSION-TIME"), 112 WebhookID: webhookID, 113 Event: json.RawMessage(bodyBytes), 114 } 115 116 response := &VerifyWebhookResponse{} 117 118 req, err := c.NewRequest(ctx, "POST", fmt.Sprintf("%s%s", c.APIBase, "/v1/notifications/verify-webhook-signature"), verifyRequest) 119 if err != nil { 120 return nil, err 121 } 122 123 if err = c.SendWithAuth(req, response); err != nil { 124 return nil, err 125 } 126 127 return response, nil 128 } 129 130 // GetWebhookEventTypes - Lists all webhook event types. 131 // Endpoint: GET /v1/notifications/webhooks-event-types 132 func (c *Client) GetWebhookEventTypes(ctx context.Context) (*WebhookEventTypesResponse, error) { 133 req, err := c.NewRequest(ctx, http.MethodGet, fmt.Sprintf("%s%s", c.APIBase, "/v1/notifications/webhooks-event-types"), nil) 134 q := req.URL.Query() 135 136 req.URL.RawQuery = q.Encode() 137 resp := &WebhookEventTypesResponse{} 138 if err != nil { 139 return nil, err 140 } 141 142 err = c.SendWithAuth(req, resp) 143 return resp, err 144 }