Skip to content

Commit 9f85c58

Browse files
kitallisclaude
andcommitted
Fetch account contact for subscription events without customer data
subscription.payment.reminder and similar events don't include customer info directly - only an account ID. Now fetches contact details from the /accounts/{id} API when customer email is missing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent a3bbf3f commit 9f85c58

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

main.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ type SubscriptionData struct {
6363
Total any `json:"total"`
6464
TotalDisplay string `json:"totalDisplay"`
6565
Customer Customer `json:"customer"`
66+
Account string `json:"account"`
6667
State string `json:"state"`
6768
Next any `json:"next"`
6869
NextDisplay string `json:"nextDisplay"`
@@ -385,6 +386,15 @@ func handleSubscriptionEvent(event Event, title string, severity string) error {
385386
return fmt.Errorf("failed to parse subscription data: %w", err)
386387
}
387388

389+
// If customer info is missing, fetch from account
390+
if data.Customer.Email == "" && data.Account != "" {
391+
if contact, err := fetchAccountContact(data.Account); err == nil {
392+
data.Customer = contact
393+
} else {
394+
log.Printf("Failed to fetch account contact for %s: %v", data.Account, err)
395+
}
396+
}
397+
388398
message := formatSubscriptionMessage(data, event.Live, title, severity)
389399
return sendSlackNotification(message)
390400
}
@@ -733,6 +743,48 @@ func fetchRecentQuotes() ([]QuoteAPIData, error) {
733743
return result.Embedded.Quotes, nil
734744
}
735745

746+
// AccountResponse represents the Fastspring account API response
747+
type AccountResponse struct {
748+
ID string `json:"id"`
749+
Account string `json:"account"`
750+
Contact struct {
751+
First string `json:"first"`
752+
Last string `json:"last"`
753+
Email string `json:"email"`
754+
Company string `json:"company"`
755+
} `json:"contact"`
756+
}
757+
758+
func fetchAccountContact(accountID string) (Customer, error) {
759+
if accountID == "" {
760+
return Customer{}, nil
761+
}
762+
763+
path := fmt.Sprintf("/accounts/%s", accountID)
764+
resp, err := fastspringAPIRequest("GET", path, nil)
765+
if err != nil {
766+
return Customer{}, fmt.Errorf("failed to fetch account %s: %w", accountID, err)
767+
}
768+
defer resp.Body.Close()
769+
770+
if resp.StatusCode != http.StatusOK {
771+
body, _ := io.ReadAll(resp.Body)
772+
return Customer{}, fmt.Errorf("account %s returned %d: %s", accountID, resp.StatusCode, string(body))
773+
}
774+
775+
var result AccountResponse
776+
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
777+
return Customer{}, fmt.Errorf("failed to decode account %s: %w", accountID, err)
778+
}
779+
780+
return Customer{
781+
First: result.Contact.First,
782+
Last: result.Contact.Last,
783+
Email: result.Contact.Email,
784+
Company: result.Contact.Company,
785+
}, nil
786+
}
787+
736788
func fetchSubscriptionEntries(subscriptionID string) ([]SubscriptionEntry, error) {
737789
path := fmt.Sprintf("/subscriptions/%s/entries", subscriptionID)
738790
resp, err := fastspringAPIRequest("GET", path, nil)

0 commit comments

Comments
 (0)