Home > Blockchain >  Stripe payment incomplete despite payment details being attached?
Stripe payment incomplete despite payment details being attached?

Time:11-22

enter image description here

Using test data I can create a customer and attach a payment method, but all of my subscriptions are left in this state. Here's my code for creating a subscription currently:

// StripeCreateSubscription create a new subscription with fixed price for user
func StripeCreateSubscription(w http.ResponseWriter, r *http.Request) {
    if r.Method != "POST" {
        SendResponse(w, utils.MakeError("you can only POST to the stripe create customer route"), http.StatusMethodNotAllowed)
        return
    }

    // Decode the JSON payload
    type requestPayload struct {
        PaymentMethodID string `json:"paymentMethodId"`
        PriceID         string `json:"priceId"`
    }

    var payload requestPayload
    if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
        sendSystemError(w, fmt.Errorf("decode request payload: %v", err))
        return
    }

    // Get the user from the context of who made the request
    uid := r.Context().Value("user_id").(int)

    u := models.User{}
    if err := u.FindByID(uid); err != nil {
        sendSystemError(w, fmt.Errorf("find user by id: %v", err))
        return
    }
    if u.StripeCustomerID == "" {
        sendSystemError(w, errors.New("no customer for the user"))
        return
    }

    // Attach the payment method to the customer
    paymentParams := &stripe.PaymentMethodAttachParams{
        Customer: stripe.String(u.StripeCustomerID),
    }

    pm, err := paymentmethod.Attach(
        payload.PaymentMethodID,
        paymentParams,
    )

    if err != nil {
        sendSystemError(w, fmt.Errorf("attaching payment method failed: %v", err))
    }

    // Check if the user has any active subscriptions, and cancel the others if they're adding one.
    listParams := &stripe.SubscriptionListParams{
        Customer: u.StripeCustomerID,
        Status:   "all",
    }
    listParams.AddExpand("data.default_payment_method")

    iter := sub.List(listParams)
    subscriptions := iter.SubscriptionList().Data
    if len(subscriptions) > 0 {
        Log.Info(fmt.Sprintf("%v subscriptions found for %v. Cancelling...", len(subscriptions), u.Username))
        for i := 0; i < len(subscriptions); i   {
            if subscriptions[i].Status != "canceled" && subscriptions[i].Status != "incomplete_expired" {
                Log.Info(fmt.Sprintf("Cancelling %v. Status %v", subscriptions[i].ID, subscriptions[i].Status))
                subscription, err := sub.Cancel(subscriptions[i].ID, nil)
                if err != nil {
                    sendSystemError(w, fmt.Errorf("cancel subscription: %v", err))
                    return
                }
                Log.Info(fmt.Sprintf("Cancelled %v", subscription.ID))
            }
        }
        Log.Info("Old subscriptions cancelled.")
        time.Sleep(5 * time.Second)
    }

    // Create subscription
    subscriptionParams := &stripe.SubscriptionParams{
        Customer: stripe.String(u.StripeCustomerID),
        Items: []*stripe.SubscriptionItemsParams{
            {
                Price: stripe.String(payload.PriceID),
            },
        },
        PaymentBehavior:      stripe.String("default_incomplete"),
        DefaultPaymentMethod: stripe.String(payload.PaymentMethodID),
    }
    subscriptionParams.AddExpand("latest_invoice.payment_intent")
    newSub, err := sub.New(subscriptionParams)
    if err != nil {
        sendSystemError(w, fmt.Errorf("new subscription: %v", err))
        return
    }

    // If everything looks good, then send some info back to the user
    output := map[string]interface{}{
        "subscriptionId": newSub.ID,
        "clientSecret":   newSub.LatestInvoice.PaymentIntent.ClientSecret,
    }
    SendResponse(w, output, 200)
}

What do I need to do to get my subscriptions to complete payment?

CodePudding user response:

Using default_incomplete like the fixed-price subscription guide shows explicitly keeps the initial invoice unattempted when you create the subscription. To complete the setup, you need to confirm the payment with the Payment Element (or with the Card Element) using that client secret from the client-side of your application. You already appear to be sending the client_secret back, are you using it?

  • Related