#michaelcrilly-paymentlink

1 messages ยท Page 1 of 1 (latest)

umbral stirrup
#

the easiest way is probably to include those information as metadata on your payment link. The metadata associated with this Payment Link will automatically be copied to checkout sessions created by this payment link.

main valve
#

I've attached metadata to the product, if that's what you mean? What object types do I need to get from the API to retrieve the metadata? Right now I'm looking at Charge objects.

umbral stirrup
main valve
umbral stirrup
main valve
#

Correct. I have three - two are deactivated and a third is active and is the one I sent above.

umbral stirrup
#

so if you click into the active one

#

you'll see the above in the page

main valve
#

Indeed. I see that!

umbral stirrup
#

this is one option to include details about what you're selling

main valve
#

So I've attached some metadata to that active link. Are you saying I need to work with the payment_links API instead of working with the charges API?

umbral stirrup
#

you don't necessarily need to create a Payment Link via the API. There're several ways to retrieve the information that you want. More importantly though, you should retrieve the Checkout Sessions instead of the PaymentIntents or Charges

main valve
#

I'll just create Payment Link(s) via the console. All I want to do here is get the successful Checkout Sessions, but I cannot work out how-to do that without an existing session object.

umbral stirrup
#

actually onesec, you don't need to use metadata

main valve
#

i := session.List(params) - this is literally impossible

#

Because I don't have a session object, nor is there a (Go) package called session or sessions. At least, I cannot go get ... one.

#

Yeah, i shouldn't need metadata if I can retrieve the Checkout Session as it'll likely have everything I need, but it's this session.* object I'm struggling to understand. I don't know where/how I go about making or retrieving that object.

umbral stirrup
#

are you using the stripe-go library?

main valve
#

Yes.

#

v72

#

session.New(...), perhaps?

umbral stirrup
main valve
umbral stirrup
#

this works for me

import (
    "fmt"
    "github.com/stripe/stripe-go/v72"
    "github.com/stripe/stripe-go/v72/checkout/session"
)

func main() {
    stripe.Key = "sk_test_..."

    params := &stripe.CheckoutSessionListParams{}
    params.Filters.AddFilter("limit", "", "3")
    i := session.List(params)
    for i.Next() {
        s := i.CheckoutSession()
        fmt.Println(s)
    }
main valve
#

And for me. So I didn't need to create a Session object.

#

OMG... it has everything I need... I feel like crying... it only took days to get here lol

umbral stirrup
main valve
#

Indeed. Thank you.

#

OK... so .LineItems is always nil

#

Ah hang on, I might be accessing the wrong thing.

#

Hmm, I'm trying .LineItems and .PaymentLink.LineItems, and they're both always null (nil).

umbral stirrup
main valve
#

Thanks you for your patience, Alex.

#

[ERROR] Request error from Stripe (status 400): {"status":400,"message":"This property cannot be expanded (customer). You may want to try expanding 'data.customer' instead.","request_id":"req_3zb54YCkiOMyv9","type":"invalid_request_error"}

#

I'm taking deep breathes...

#

And no, data.customer doesn't work neither.

umbral stirrup
#

params.AddExpand("data.line_items")

main valve
#

This is referring to the customer.

#

I've tried both.

#

Both work, but the .Customer object on the Session is nil, again.

umbral stirrup
#

i'm a bit confused, aren't you trying to retrieve the line_items data?

main valve
#

OK, I see. Stripe Link has, somehow, taken payments without creating a customer object: +--------------------------+--------+-----+------------+ | CUSTOMER | CHARGE | PID | PRODUCT(S) | +--------------------------+--------+-----+------------+ | ..............@gmail.com | $29.00 | | N/A | | ..............@gmail.com | $29.00 | | N/A | | ........@gmail.com | $29.00 | | N/A | | ........@gmail.com | $29.00 | | N/A | | ........@gmail.com | $29.00 | | N/A | | ........@gmail.com | $29.00 | | N/A | | ....@opsfactory.com.au | $3.00 | | N/A | +--------------------------+--------+-----+------------+

#

So if I skip over CheckoutSessions that have a nil .Customer attribute, I get what I'm after... but not everything

#

I cannot get the LineItems now the PyamentLink.LineItems - they're always nil or empty.

#

Despite expanding them.

#

I can share my code, but you deleted it from the thread last time, hence why I haven't shared it so far.

#

None of the data I'm working with here is production or private.

umbral stirrup
#

it'd be better if you didn't share emails here since this is a public channel

main valve
#

Sure. I understand. They're my email addresses, but I'll refrain from doing that.

umbral stirrup
#

sure, go ahead and paste your code here

main valve
#
    stripe.Key = "sk_test_..."

    table := tablewriter.NewWriter(os.Stdout)
    table.SetHeader([]string{"Customer", "Charge", "PID", "Product(s)"})

    params := &stripe.CheckoutSessionListParams{}
    params.AddExpand("data.customer")
    params.AddExpand("data.line_items")
    i := session.List(params)

    for i.Next() {
        s := i.CheckoutSession()

        if s.Customer == nil {
            continue
        }

        deets := []string{
            s.Customer.Email,
            fmt.Sprintf("$%.2f", float64(s.AmountTotal/100)),
            s.ClientReferenceID,
            "",
        }

        if s.PaymentLink.LineItems != nil && s.PaymentLink.LineItems.TotalCount > 0 {
            for _, li := range s.PaymentLink.LineItems.Data {
                deets[3] = fmt.Sprintf("%s, %s", deets[3], li.Product.ID)
            }
        } else {
            deets[3] = "N/A"
        }

        table.Append(deets)
    }

    table.Render()
}```
#

I've tried s.LineItems. and s.PaymentLink.LineItems.

umbral stirrup
#

i'd suggest referring to the documentation to see how the object is structured

#

have you tried s.line_items

main valve
#

The CheckoutSession object has no such attribute.

umbral stirrup
#

๐Ÿ‘€

main valve
#

It has .LineItems, but it's always nil/empty.

#
+----------+--------+-----+---+------------+
| CUSTOMER | CHARGE | PID | # | PRODUCT(S) |
+----------+--------+-----+---+------------+
| ignored  | $29.00 |     | 0 | N/A        |
| ignored  | $29.00 |     | 0 | N/A        |
| ignored  | $29.00 |     | 0 | N/A        |
| ignored  | $29.00 |     | 0 | N/A        |
| ignored  | $29.00 |     | 0 | N/A        |
| ignored  | $29.00 |     | 0 | N/A        |
| ignored  | $3.00  |     | 0 | N/A        |
+----------+--------+-----+---+------------+```
#

# = s.LineItems.TotalCount.

#

Is it because it's a PaymentLink?

umbral stirrup
#

onesec, let me test it out

main valve
#

Awesome, thanks.

#

I'm trying this: params := &stripe.CheckoutSessionListParams{} params.AddExpand("data.customer") params.AddExpand("data.line_items") params.AddExpand("data.payment_link") params.AddExpand("data.payment_link.line_items")

umbral stirrup
#

s.LineItems.Data

#

LineItems isn't nil/empty

main valve
#

It is for me.

$ go run .
+----------+--------+--------------------+---+----------------------------------------+
| CUSTOMER | CHARGE |        PID         | # |               PRODUCT(S)               |
+----------+--------+--------------------+---+----------------------------------------+
| REDACTED | $29.00 | cus_LaClexI99IwQ3z | 0 | s.LineItems=nil / .TotalCount==0, Alex |
| REDACTED | $29.00 | cus_LaCi98m23pZMxD | 0 | s.LineItems=nil / .TotalCount==0, Alex |
| REDACTED | $29.00 | cus_LaCQwiFPrOOTXx | 0 | s.LineItems=nil / .TotalCount==0, Alex |
| REDACTED | $29.00 | cus_LaAhvfm1HYPZMT | 0 | s.LineItems=nil / .TotalCount==0, Alex |
| REDACTED | $29.00 | cus_LaAdij5RoFrzUE | 0 | s.LineItems=nil / .TotalCount==0, Alex |
| REDACTED | $29.00 | cus_La8Md3PcHVSWMD | 0 | s.LineItems=nil / .TotalCount==0, Alex |
| REDACTED | $3.00  | cus_K0stWrFLr5YFVc | 0 | s.LineItems=nil / .TotalCount==0, Alex |
+----------+--------+--------------------+---+----------------------------------------+

Based on the following code:

params := &stripe.CheckoutSessionListParams{}
    params.AddExpand("data.customer")
    params.AddExpand("data.line_items")
    params.AddExpand("data.payment_link")
    params.AddExpand("data.payment_link.line_items")
    i := session.List(params)

    for i.Next() {
        s := i.CheckoutSession()

        if s.Customer == nil {
            continue
        }

        deets := []string{
            // s.Customer.Email,
            "REDACTED",
            fmt.Sprintf("$%.2f", float64(s.AmountTotal/100)),
            s.Customer.ID,
            fmt.Sprintf("%d", s.LineItems.TotalCount),
            "",
        }

        if s.LineItems != nil && s.LineItems.TotalCount > 0 {
            for _, li := range s.LineItems.Data {
                deets[4] = fmt.Sprintf("%s, %s", deets[3], li.Product.ID)
            }
        } else {
            deets[4] = "s.LineItems=nil / .TotalCount==0, Alex"
        }

        table.Append(deets)
    }```
#

We're so close, Alex. So, so close. I'm doing something wrong. If we can identify that, we've nailed it.

umbral stirrup
#

can you log the Checkout Session id that is returning nil for LineItems

main valve
#

I sure can, one moment...

#
+--------------------------------------------------------------------+----------+--------------------+--------+----------------------------------------+------------+
|                        CHECKOUT SESSION ID                         | CUSTOMER |        PID         |  $$$   |                   #                    | PRODUCT(S) |
+--------------------------------------------------------------------+----------+--------------------+--------+----------------------------------------+------------+
| cs_test_a15KNLEvJdWv1Ml5Jq2k2Zt4JpclpDbdRIAuJHpqQlJLjukhKLrFRlnmwh | REDACTED | cus_LaClexI99IwQ3z | $29.00 | s.LineItems=nil / .TotalCount==0, Alex |            |
| cs_test_a1gVWv4zf74xvMX6MGgZ3oPHJ1QPxnvLwKspNfOrFwqgcWFrBGihNrNDMF | REDACTED | cus_LaCi98m23pZMxD | $29.00 | s.LineItems=nil / .TotalCount==0, Alex |            |
| cs_test_a1sRzxSpUy3TJh8MUavYXuBITNiscHg4Z0foa2dUDC8xkATXPTYsjVwvXP | REDACTED | cus_LaCQwiFPrOOTXx | $29.00 | s.LineItems=nil / .TotalCount==0, Alex |            |
| cs_test_a12vz1r6WSHsXY6QEjpDamfif3HGUqMeJuDwVE4ZNWCfPn2RgeMRGRlLoS | REDACTED | cus_LaAhvfm1HYPZMT | $29.00 | s.LineItems=nil / .TotalCount==0, Alex |            |
| cs_test_a1CeB639XiiNhv1kFJo4cOR3rfy5mb4rr19yvxVllXEzwVR40udjCE1aCD | REDACTED | cus_LaAdij5RoFrzUE | $29.00 | s.LineItems=nil / .TotalCount==0, Alex |            |
| cs_test_a1bpZN8fogA63ruODXJySy37KdGBY1IYk1S0CAYVo1NQL9hLTDZ2IoWN28 | REDACTED | cus_La8Md3PcHVSWMD | $29.00 | s.LineItems=nil / .TotalCount==0, Alex |            |
| cs_test_NPgfBinxJkkt3j6U8m78a27nCSy22vA5dQCe3S3AMQjgIRuwV53WJbxX   | REDACTED | cus_K0stWrFLr5YFVc | $3.00  | s.LineItems=nil / .TotalCount==0, Alex |            |
+--------------------------------------------------------------------+----------+--------------------+--------+----------------------------------------+------------+```
#

It's messy, sorry

#

I'm not sure if cs_* IDs are meant to be searchable, but I cannot find these in the UI when using the built-in search function (/)

umbral stirrup
#

you can't find them in the Dashboard Search, you need to search using the PaymentIntent id

main valve
#

Right. I can find the PIDs fine. Makes sense.

umbral stirrup
#

lets test this against a single Checkout Session. If you retrieve cs_test_a15KNLEvJdWv1Ml5Jq2k2Zt4JpclpDbdRIAuJHpqQlJLjukhKLrFRlnmwh and expand data.line_items, then log s.LineItems -> what do you get?

main valve
#

Sure thing. One moment...

#

OK, so the issue was I was checking to see if TotalCount was > 0, but it seems it's always 0, which is obviously useful and logical... /s

If I ignore that and, instead, just check the len(s.LineItems.Data) > 0, then it works: $ go run . +---------------------+----------+--------------------+--------+---+------------------------------------------+ | CHECKOUT SESSION ID | CUSTOMER | PID | $$$ | # | PRODUCT(S) | +---------------------+----------+--------------------+--------+---+------------------------------------------+ | IGNORED | REDACTED | cus_LaClexI99IwQ3z | $29.00 | 1 | $29.00, Test Course Access | | IGNORED | REDACTED | cus_LaCi98m23pZMxD | $29.00 | 1 | $29.00, Test Course Access | | IGNORED | REDACTED | cus_LaCQwiFPrOOTXx | $29.00 | 1 | $29.00, Test Course Access | | IGNORED | REDACTED | cus_LaAhvfm1HYPZMT | $29.00 | 1 | $29.00, Test Course Access | | IGNORED | REDACTED | cus_LaAdij5RoFrzUE | $29.00 | 1 | $29.00, Test Course Access | | IGNORED | REDACTED | cus_La8Md3PcHVSWMD | $29.00 | 1 | $29.00, Test Course Access | | IGNORED | REDACTED | cus_K0stWrFLr5YFVc | $3.00 | 1 | $3.00, End to End DevOps Earlier Adopter | +---------------------+----------+--------------------+--------+---+------------------------------------------+

So we're even closer now, thank you... but I cannot look at lineitem.Product.* as .Product is nil and I cannot expand it (I tried data.line_items.data.product, but the API rejected that.)

#

So now I just need to work out how-to either expand the Product information, or just take the ID and do a straight product lookup using the API.

umbral stirrup
#

i'd suggest that you log the data of the object that you've retrieved. Right now the problem is that you're making assumptions but not looking at the actual object structure.

main valve
#

I have the object structure. That's easy to find as I'm looking at the actual code itself...

umbral stirrup
#

alright, so if you log s.LineItems.Data - > this should be an array

main valve
#

This is the literal struct{} that will be available to me.

#

It is, yes. And I can loop over that just fine.

#

The object for which is: // A line item. type LineItem struct { APIResource // Total discount amount applied. If no discounts were applied, defaults to 0. AmountDiscount int64 `json:"amount_discount"` // Total before any discounts or taxes are applied. AmountSubtotal int64 `json:"amount_subtotal"` // Total tax amount applied. If no tax was applied, defaults to 0. AmountTax int64 `json:"amount_tax"` // Total after discounts and taxes. AmountTotal int64 `json:"amount_total"` // Three-letter [ISO currency code](https://www.iso.org/iso-4217-currency-codes.html), in lowercase. Must be a [supported currency](https://stripe.com/docs/currencies). Currency Currency `json:"currency"` Deleted bool `json:"deleted"` // An arbitrary string attached to the object. Often useful for displaying to users. Defaults to product name. Description string `json:"description"` // The discounts applied to the line item. Discounts []*LineItemDiscount `json:"discounts"` // Unique identifier for the object. ID string `json:"id"` // String representing the object's type. Objects of the same type share the same value. Object string `json:"object"` // The price used to generate the line item. Price *Price `json:"price"` // The ID of the product for this line item. // // This will always be the same as `price.product`. Product *Product `json:"product"` // The quantity of products being purchased. Quantity int64 `json:"quantity"` // The taxes applied to the line item. Taxes []*LineItemTax `json:"taxes"` }

umbral stirrup
#

if you get s.LineItems.Data[0] -> what do you see?

main valve
#

&{APIResource:{LastResponse:<nil>} AmountDiscount:0 AmountSubtotal:2900 AmountTax:0 AmountTotal:2900 Currency:usd Deleted:false Description:Test Course Access Discounts:[] ID:li_1Kt2LaFI0bgZdvZj2qqGIDve Object:item Price:0xc00011f600 Product:<nil> Quantity:1 Taxes:[]}

umbral stirrup
#

to get the Product id : s.LineItems.Data[0].Price.Product.ID

#

line_items.data.product is clearly not going to work

main valve
#

No, but .Product is an object that is not being expanded. It must have some use. However, I can totally work with .Price.Product.ID, for sure.

umbral stirrup
#

i don't understand what you mean by Product is an object that is not being expanded, what are you trying to retrieve here?

main valve
#

Product:<nil> == // The ID of the product for this line item. // // This will always be the same as `price.product`. Product *Product `json:"product"

*Product == type Product struct { ... }

#

I'm just saying, I was trying to access lineitem.Product but it's nil and I cannot expand it in the parameters. It's just unusual that it's nil and I cannot use it directly. But I can totally work with Price.Product as I know a Price is an object in the Stripe API too.

umbral stirrup
main valve
#

The Product.ID is all I needed, though. Now I can simply "hard code" that and my code and understand that is, indeed, the product that's been bought.

#

Thanks A LOT Alex.

#

If there's a customer satisfaction survey or something I can fill out, please tell me how I go about doing that.

umbral stirrup
#

we don't have one on Discord but the thought is enough. I'm glad we managed to figure things out ๐Ÿ˜„