wyyerd / stripe-rs

Rust API bindings for the Stripe HTTP API.
Apache License 2.0
219 stars 88 forks source link

How to CheckoutSession? #178

Open mikeumus opened 3 years ago

mikeumus commented 3 years ago

I've been reading through the source trying to figure it out. Got stuck on the stripe::CheckoutSessionItem::id:

    let checkout_sesh = stripe::CheckoutSession {
        success_url: format!("{:?}/success.html?session_id={{CHECKOUT_SESSION_ID}}", domain),
        cancel_url: format!("{:?}/canceled.html", domain),
        payment_method_types: vec!["card".to_string()],
        mode: serde::__private::Some(stripe::CheckoutSessionMode::Subscription),
        line_items: vec![
            stripe::CheckoutSessionItem {
                // id: stripe::CheckoutSessionItemId { 0: 1234 },
                // id: None,
                // id: "val".into(),
                id: "val".to_string(),
                amount_total: None,
                amount_subtotal: None,
                description: "description".to_string(),
                taxes: None,
                // currency: "USD".to_string(),
                currency: stripe::Currency::USD,
                price: json.get("Price").unwrap(),
                quantity: Some(u64::from(1)),
            },
            // data: {
            //     "Price" = json.get("price").unwrap(),
            //     "Quantity": u64::from(1)
            // },
            // has_more: true,
            // total_count: serde::__private::Some(u64::from(1)),
            // url: "test_url".to_string(),

        ]
    };

I found this: https://github.com/wyyerd/stripe-rs/blob/624c97259a07547afc4c2e70adaeb7ce4c25b9b2/src/ids.rs#L487

👆 in the source typed as a String but trying to set a String as the id above gives:

expected struct `stripe::CheckoutSessionItemId`, found struct `std::string::String`

Any insight would be greatly appreciated. Thank you 🙇🏻‍♂️

arlyon commented 3 years ago

Hi! Yes, it is a string but CheckoutSessionItemId uses the newtype pattern to provide type safety.

See here: https://docs.rs/stripe-rust/0.12.3/src/stripe/ids.rs.html#121

Luckily CheckoutSessionItemId implements FromStr (so does all the rest of the macro-derived string newtypes here) so you should be able to do the following:

CheckoutSessionItem {
    id: CheckoutSessionItemId::from_str("val"),
    ...
}

This is so we can provide errors when you provide an invalid ID for certain types, as some have required prefixes.

dzervas commented 2 years ago

My problem with CheckoutSession is actually the id field. I'm creating it so how will I know ahead of time what the id will be?

    let client = stripe::Client::new(dotenv!("STRIPE_SECRET"));
    let price = Price::retrieve(&client, &PriceId::from_str(dotenv!("STRIPE_PRICE_ID"))?, &[]).await.unwrap();

    let mut line_items = List::default();
    line_items.data.push(CheckoutSessionItem {
        amount_total: None,
        amount_subtotal: None,
        currency: Currency::EUR,
        description: "Subscription".to_string(),
        id: CheckoutSessionItemId::from_str("yearly")?,
        price,
        quantity: Some(1),
        taxes: None,
    });

    let session = CheckoutSession {
        billing_address_collection: None,
        cancel_url: "/api/v1/payment/cancel".to_string(),
        client_reference_id: Some(user.id),
        customer: None,
        customer_email: Some(user_obj.email),
        display_items: None,
        id: None,
        line_items,
        livemode: false,
        locale: None,
        metadata: Metadata::new(),
        mode: Some(CheckoutSessionMode::Subscription),
        payment_intent: None,
        payment_method_types: vec!["card".to_string()],
        setup_intent: None,
        shipping: None,
        shipping_address_collection: None,
        submit_type: None,
        subscription: None,
        success_url: "/api/v1/payment/success".to_string(),
    };
barlindhaug commented 2 years ago

It looks like the CheckoutSession is not completely implemented, you are missing the create function which normally takes a CreateCheckoutSession struct as input.

As an example, see how the PaymentIntent works: https://docs.rs/stripe-rust/0.12.3/stripe/struct.PaymentIntent.html#method.create

or the CheckoutSession in the async-stripe fork: https://docs.rs/async-stripe/latest/stripe/struct.CheckoutSession.html