Skip to content

Commit

Permalink
Add support for prorated stripe subs
Browse files Browse the repository at this point in the history
  • Loading branch information
jveski committed Dec 1, 2023
1 parent 4129f27 commit e98f064
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 1 deletion.
24 changes: 24 additions & 0 deletions keycloak/keycloak.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package keycloak
import (
"context"
"encoding/csv"
"encoding/json"
"errors"
"fmt"
"io"
Expand Down Expand Up @@ -143,6 +144,23 @@ func (k *Keycloak) GetUser(ctx context.Context, userID string) (*User, error) {
user.StripeCancelationTime, _ = strconv.ParseInt(safeGetAttr(kcuser, "stripeCancelationTime"), 10, 0)
user.StripeETag = safeGetAttr(kcuser, "stripeETag")

if js := safeGetAttr(kcuser, "paypalMigrationMetadata"); js != "" {
s := struct {
Price float64
TimeRFC3339 string
}{}
err := json.Unmarshal([]byte(js), &s)
if err != nil {
return nil, err
}

user.LastPaypalTransactionPrice = s.Price
user.LastPaypalTransactionTime, err = time.Parse(time.RFC3339, s.TimeRFC3339)
if err != nil {
return nil, err
}
}

kuserlogins, err := k.Client.GetUserFederatedIdentities(ctx, token.AccessToken, k.env.KeycloakRealm, *kcuser.ID)
if err != nil {
return nil, err
Expand Down Expand Up @@ -245,6 +263,9 @@ func (k *Keycloak) UpdateUserStripeInfo(ctx context.Context, customer *stripe.Cu
return nil
}

// Always clean up any old paypal metadata
attr["paypalMigrationMetadata"] = []string{sub.ID}

if active {
attr["stripeID"] = []string{customer.ID}
attr["stripeSubscriptionID"] = []string{sub.ID}
Expand Down Expand Up @@ -410,6 +431,9 @@ type User struct {
StripeSubscriptionID string
StripeCancelationTime int64
StripeETag string

LastPaypalTransactionPrice float64
LastPaypalTransactionTime time.Time
}

func safeGetAttrs(kcuser *gocloak.User) map[string][]string {
Expand Down
18 changes: 17 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,8 @@ func newStripeCheckoutHandler(env *conf.Env, kc *keycloak.Keycloak, pc *stripeut
Quantity: stripe.Int64(1),
}}
checkoutParams.SubscriptionData = &stripe.CheckoutSessionSubscriptionDataParams{
Metadata: map[string]string{"etag": etag},
Metadata: map[string]string{"etag": etag},
BillingCycleAnchor: calculateBillingCycleAnchor(user),
}
}
s, err := session.New(checkoutParams)
Expand Down Expand Up @@ -388,6 +389,21 @@ func calculateDiscount(user *keycloak.User, priceID string, pc *stripeutil.Price
return nil
}

func calculateBillingCycleAnchor(user *keycloak.User) *int64 {
if user.LastPaypalTransactionPrice == 0 {
return nil
}

// Annual
if user.LastPaypalTransactionPrice > 41 {
ts := user.LastPaypalTransactionTime.Add(time.Hour * 24 * 365).Unix()
return &ts
}

ts := user.LastPaypalTransactionTime.Add(time.Hour * 24 * 30).Unix()
return &ts
}

// getUserID allows the oauth2proxy header to be overridden for testing.
func getUserID(r *http.Request) string {
user := r.Header.Get("X-Forwarded-Preferred-Username")
Expand Down
10 changes: 10 additions & 0 deletions templates/profile.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ <h3 class="panel-title">Payment</h3>
<a href="/profile/cancel" role="button" class="btn btn-default">Cancel Membership</a>
</div>
{{- end }} {{- else }}
{{- if .user.LastPaypalTransactionTime }}
<div class="alert alert-info" role="alert">
We found a Paypal payment associated with your email address from {{
.user.LastPaypalTransactionTime.Format "01/02/2006" }}. Your account will be prorated accordingly when
signing up with Stripe.<br><br>
After signing up, you can cancel your existing Paypal subscription using a link in your latest Paypal
receipt
email.
</div>
{{- end }}
<div class="btn-group" role="group" aria-label="...">
{{- range .prices }}
<a href="/profile/stripe?price={{ .ID }}" role="button" class="btn btn-default">{{ .ButtonText }}</a>
Expand Down

0 comments on commit e98f064

Please sign in to comment.