-
Notifications
You must be signed in to change notification settings - Fork 459
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into latest-codegen-master
- Loading branch information
Showing
11 changed files
with
373 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
80.0.0 | ||
80.2.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
// meter_event_stream.go - use the high-throughput meter event stream to report create billing meter events. | ||
// | ||
// This example uses the rawrequests module to make calls to /v2 APIs. | ||
// | ||
// In this example, we: | ||
// - create a meter event session and store the session's authentication token | ||
// - define an event with a payload | ||
// - post the event to /v2/billing/meter_event_stream to create an event stream that reports this event | ||
// | ||
// This example expects a billing meter with an event_name of 'alpaca_ai_tokens'. If you have | ||
// a different meter event name, you can change it before running this example. | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"os" | ||
"time" | ||
|
||
stripe "github.com/stripe/stripe-go/v80" | ||
rawrequest "github.com/stripe/stripe-go/v80/rawrequest" | ||
) | ||
|
||
var sessionAuthToken string = "" | ||
var sessionAuthExpiresAt string = "" | ||
|
||
func refreshMeterEventSession(client rawrequest.Client) (err error) { | ||
currentTime := time.Now().Format(time.RFC3339) | ||
// Check if session is null or expired | ||
if sessionAuthToken == "" || sessionAuthExpiresAt <= currentTime { | ||
// Create a new meter event session in case the existing session expired | ||
rawResp, err := client.RawRequest(http.MethodPost, "/v2/billing/meter_event_session", "", nil) | ||
if err != nil { | ||
return err | ||
} | ||
if rawResp.StatusCode != 200 { | ||
return fmt.Errorf(rawResp.Status) | ||
} | ||
|
||
var resp map[string]interface{} | ||
err = json.Unmarshal(rawResp.RawJSON, &resp) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
sessionAuthToken = resp["authentication_token"].(string) | ||
sessionAuthExpiresAt = resp["expires_at"].(string) | ||
|
||
fmt.Println("Meter event session created!") | ||
} | ||
return nil | ||
} | ||
|
||
func sendMeterEvent(client rawrequest.Client, eventName string, stripeCustomerID string, value string) (err error) { | ||
// Refresh the meter event session if necessary | ||
refreshMeterEventSession(client) | ||
|
||
if sessionAuthToken == "" { | ||
err = fmt.Errorf("Unable to refresh meter event session") | ||
return | ||
} | ||
|
||
b, err := stripe.GetRawRequestBackend(stripe.MeterEventsBackend) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
sessionClient := rawrequest.Client{B: b, Key: sessionAuthToken} | ||
|
||
params := map[string]interface{}{ | ||
"events": []interface{}{ | ||
map[string]interface{}{ | ||
"event_name": eventName, | ||
"payload": map[string]interface{}{ | ||
"stripe_customer_id": stripeCustomerID, | ||
"value": value, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
contentBytes, err := json.Marshal(params) | ||
if err != nil { | ||
return | ||
} | ||
|
||
content := string(contentBytes) | ||
_, err = sessionClient.RawRequest(http.MethodPost, "/v2/billing/meter_event_stream", content, nil) | ||
return | ||
} | ||
|
||
func main() { | ||
|
||
apiKey := "{{API_KEY}}" | ||
customerID := "{{CUSTOMER_ID}}" | ||
|
||
b, err := stripe.GetRawRequestBackend(stripe.APIBackend) | ||
if err != nil { | ||
fmt.Println(err) | ||
os.Exit(1) | ||
} | ||
|
||
client := rawrequest.Client{B: b, Key: apiKey} | ||
|
||
err = sendMeterEvent(client, "alpaca_ai_tokens", customerID, "25") | ||
if err != nil { | ||
fmt.Println(err) | ||
os.Exit(1) | ||
} | ||
fmt.Println("Meter event sent successfully!") | ||
} |
106 changes: 106 additions & 0 deletions
106
example/v2/thinevent_webhook_handler/thinevent_webhook_handler.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
// thinevent_webhook_handler.go - receive and process thin events like the | ||
// v1.billing.meter.error_report_triggered event. | ||
// | ||
// This example uses the rawrequests module to make calls to /v2 APIs. | ||
// | ||
// In this example, we: | ||
// - parse the incoming thin event payload and get the event id | ||
// - get the full event from /v2/core/events/ with the event id from the thin event | ||
// - if the full event is a v1.billing.meter.error_report_triggered, use the | ||
// billing/meter package to retrieve the Billing Meter object associated with the | ||
// event. | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io/ioutil" | ||
"net/http" | ||
"os" | ||
|
||
"github.com/stripe/stripe-go/v80" | ||
billingMeters "github.com/stripe/stripe-go/v80/billing/meter" | ||
"github.com/stripe/stripe-go/v80/rawrequest" | ||
webhook "github.com/stripe/stripe-go/v80/webhook" | ||
) | ||
|
||
var apiKey = "{{API_KEY}}" | ||
var webhookSecret = "{{WEBHOOK_SECRET}}" | ||
|
||
func main() { | ||
b, err := stripe.GetRawRequestBackend(stripe.APIBackend) | ||
if err != nil { | ||
fmt.Println(err) | ||
os.Exit(1) | ||
} | ||
|
||
client := rawrequest.Client{B: b, Key: apiKey} | ||
|
||
http.HandleFunc("/webhook", func(w http.ResponseWriter, req *http.Request) { | ||
const MaxBodyBytes = int64(65536) | ||
req.Body = http.MaxBytesReader(w, req.Body, MaxBodyBytes) | ||
payload, err := ioutil.ReadAll(req.Body) | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "Error reading request body: %v\n", err) | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
err = webhook.ValidatePayload(payload, req.Header.Get("Stripe-Signature"), webhookSecret) | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "Error reading request body: %v\n", err) | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
var thinEvent map[string]interface{} | ||
|
||
if err := json.Unmarshal(payload, &thinEvent); err != nil { | ||
fmt.Fprintf(os.Stderr, "Failed to parse thin event body json: %v\n", err.Error()) | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
eventID := thinEvent["id"].(string) | ||
|
||
var event map[string]interface{} | ||
|
||
resp, err := client.RawRequest(http.MethodGet, "/v2/core/events/"+eventID, "", nil) | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "Failed to get pull event: %v\n", err.Error()) | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
if err := json.Unmarshal(resp.RawJSON, &event); err != nil { | ||
fmt.Fprintf(os.Stderr, "Failed to parse pull event body json: %v\n", err.Error()) | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
// Unmarshal the event data into an appropriate struct depending on its Type | ||
switch t := event["type"].(string); t { | ||
case "v1.billing.meter.error_report_triggered": | ||
relatedObject := event["related_object"].(map[string]interface{}) | ||
meter, err := billingMeters.Get(relatedObject["id"].(string), nil) | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "Failed to get related meter object: %v\n", err.Error()) | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
meterID := meter.ID | ||
fmt.Printf("Success! %s\n", meterID) | ||
// Verify we can see event data | ||
fmt.Println(fmt.Sprint(event["data"])) | ||
default: | ||
fmt.Fprintf(os.Stderr, "Unhandled event type: %s\n", t) | ||
} | ||
|
||
w.WriteHeader(http.StatusOK) | ||
}) | ||
err = http.ListenAndServe(":4242", nil) | ||
if err != nil { | ||
fmt.Println(err) | ||
os.Exit(1) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.