#syed-confirm-intent

1 messages ยท Page 1 of 1 (latest)

autumn sigil
#

Hi there!

prisma basalt
#

hello ๐Ÿ‘‹ thanks for making the thread

#

hi

autumn sigil
#

Can you try setting the js.stripe.com script as async

prisma basalt
#

yep will do

prisma basalt
autumn sigil
#

I'm not really sure what you mean by that, sorry?

prisma basalt
#

oh sorry, let me clarify. I meant as in how long does it take for a request for to show up on the stripe dashboard.

Forget about that last part though, it seems like adding the async didn't solve the problem. is it fine if i post the part of my application code that I think is broken?

autumn sigil
#

Ah thanks for clarifying. Logs should show up within several seconds.

#

But there can be a short delay.

#

Yes providing your code would be helpful!

prisma basalt
#
// app/views/goals/new.html.erb
<script>
document.addEventListener('DOMContentLoaded', async () => {
  const {publishableKey} = await fetch('<%= ENV['STRIPE_PUBLISHABLE_KEY_TEST'] %>')).then((r) => r.json());
  if (!publishableKey) {
    addMessage(
      'no key'
    );
    alert('add key');
  }

  const stripe = Stripe(publishableKey, {
    apiVersion: '2020-08-27',
  });

  const form = document.getElementById('goal-form');
  let submitted = false;
  
  const url1 = "/goals";
  const url2 = "<%= payment_intent_create_path %>";

  form.addEventListener('submit', async (e) => {
    e.preventDefault();

    if(submitted) { return; }
    submitted = true;
    form.querySelector('button').disabled = true;

    const {error: backendError, clientSecret} = await fetch(
      url2,
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          currency: 'usd',
          paymentMethodType: 'card',
        }),
      }
    ).then((r) => r.json());


  const data = new FormData(form);
  
  if (!form.checkValidity()) return;
  
  const jsonData = {};
  data.forEach((val, key) => {
      jsonData[key] = val;
  })

  const response1 = await fetch(url1, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(jsonData)
  });
  
  const response2 = await fetch(url2, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(jsonData)
    });
  
    if (backendError) {
      addMessage(backendError.message);

      submitted = false;
      form.querySelector('button').disabled = false;
      return;
    }

    addMessage(`Client secret returned.`);

    const nameInput = document.querySelector('#name');

    const {error: stripeError, paymentIntent} = await stripe.confirmCardPayment(
      clientSecret);

//PART 1, CODE DOESN'T FIT IN ONE MESSAGE
#
    if (stripeError) {
      addMessage(stripeError.message);

      submitted = false;
      form.querySelector('button').disabled = false;
      return;
    }

    addMessage(`Payment ${paymentIntent.status}: ${paymentIntent.id}`);
  });
  });
</script>
// PARt 2/END
#

here is my server implementation as well:

# app/controllers/payment_intent_controller.rb
class PaymentIntentController < ApplicationController
  
  def create
    content_type 'application/json'
    data = JSON.parse(request.body.read)
    payment_method_type = data['paymentMethodType']
    currency = data['currency']
    
    intent = {
      payment_method_types: [payment_method_type],
      amount: params[:goal][:money] * 100, 
      currency: currency,
      payment_method: current_user.payment_method_id,
      customer: current_user.stripe_customer_id,
      confirm: true,
    }
    
    begin
      payment_intent = Stripe::PaymentIntent.create(intent)
    rescue Stripe::StripeError => e
      halt 400,
        { 'Content-Type' => 'application/json' },
        { error: { message: e.error.message }}.to_json
    rescue => e
      halt 500,
        { 'Content-Type' => 'application/json' },
        { error: { message: e.error.message }}.to_json
    end
    {
      clientSecret: payment_intent.client_secret,
    }.to_json
  end

end
autumn sigil
#

Can you share your HTML where you are loading https://js.stripe.com/v3/?

prisma basalt
#

yes ofc!

autumn sigil
#

Thanks!

prisma basalt
#
<%# app/views/layouts/application.html.erb %>
<!DOCTYPE html>
<html>
  <head>
    <title>Commitaway</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <script src="https://js.stripe.com/v3/" async></script>
    <link rel="stylesheet" href="https://cdn.simplecss.org/simple.css">
    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
    <%= javascript_importmap_tags %>
  </head>

  <body>
    <p class="notice"><%= notice %></p>
    <p class="alert"><%= alert %></p>
    <% if current_user %>
      <%= button_to "payment info", save_card_save_path, data: { turbo: false } ,method: :post, remote: true %>
      <%= link_to "Log Out", destroy_user_session_path, data: { turbo_method: :delete } %>
      <%= link_to "Go to Home", root_path %>
      <%= link_to "Pricing", pricing_path %>
      <%= button_to "Billing portal", billing_portal_create_path, data: { turbo: false } ,method: :post, remote: true %>
      <br>
      Stripe payment method id: 
      <%= current_user.payment_method_id %>
      <br>
      Stripe Customer id:
      <%= current_user.stripe_customer_id %>
      <br>
      Plan:
      <%= current_user.plan %>
      <br>
      Subscription:
      <%= current_user.subscription_status %>
      <br>
    <% end %>
    <%= yield %>
  </body>
</html>
#

(using rails btw)

autumn sigil
#

Thanks, give me a moment

prisma basalt
#

๐Ÿ‘

autumn sigil
#

Also can you clarify the impact of this error here? Is it stopping you from being able to take payments? You see it in your console as an error or a warning?

#

I'm seeing that this was reported internally once in the past but it wasn't actually nefarious

prisma basalt
#

Impact: when the user creates a goal in my app, I'd like for it to automatically charge their card (which I have saved by following along with these docs https://stripe.com/docs/payments/save-and-reuse?platform=checkout)/ However, it seems the card is never charged since I don't see any payment event pop up on my dashboard..

Yes, it's stopping me from being able to take payments

It seems that this is the only error shown in my console.

autumn sigil
#

Huh interesting. Thanks.

#

Can I reproduce this on my end?

#

As in... can I visit your site and repro?

prisma basalt
autumn sigil
#

Is there test credentials I can use?

#

nvm

#

I just made some test ones

prisma basalt
#

oh alright ๐Ÿ‘

autumn sigil
#

Can you try changing DOMContentLoaded to load?

#

Also let's add some logs to your JS

#

To see if that script is actually running at all and something else is going on

#

Just want to ensure that error is actually breaking things here

prisma basalt
#

sure thing, adding load now

#

pushed to heroku โœ…

#

still no payments being sent thru

#

what other changes would you like me to add?

zenith canyon
#

๐Ÿ‘‹ I'm taking over

#

That error you're seeing is 99% likely to be a red flag

prisma basalt
#

๐Ÿ‘‹ hello!

zenith canyon
#

I read through the exchange but I am really confused overall about what you are really trying to do, why you use Checkout but then do a payment, and where the problem is?

prisma basalt
#

yeah so I used checkout to quickly save the customer's payment info (rather than building out my own flow).

I'm trying to create an accountability app that essentially charges the user when they fail to hit their goal.

The problem is when the user creates a goal, but the card is not charged.

I can go into further detail if this isn't enough to clear things up ๐Ÿ™‚

zenith canyon
#

Okay so that helps. So Checkout works, you get a PaymentMethod pm_123 attached to your customer. Then what?

prisma basalt
#

on my server implementation, I grab the amount of money the user would like to put on the line for the goal (proportional to how important it is) and I charge their card with these parameters. I wasn't sure if I even needed to send the paymentMethodType and the currency since the user's payment_method is saved, but I decided to just go along with the stripe sample just in case it made a difference

    data = JSON.parse(request.body.read)
    payment_method_type = data['paymentMethodType']
    currency = data['currency']
    
    intent = {
      payment_method_types: [payment_method_type],
      amount: params[:goal][:money] * 100, 
      currency: currency,
      payment_method: current_user.payment_method_id,
      customer: current_user.stripe_customer_id,
      confirm: true,
    }
#

(full server implementation is posted earlier in thread)

zenith canyon
#

So what happens when you do that? Does it work? Do you get an error? All of this happens server-side so this has nothing to do with the browser error

#

it's also really strange to use Checkout to collect card and then immediately charge the card, it doesn't make sense. Use Checkout to accept the first payment

prisma basalt
#

the server doesn't seem to throw any error my way and it doesn't seem to work since I don't see the request show up on my stripe dashboard

zenith canyon
#

I mean something must be crashing. did you debug this? Like add logs before/after the request, log what you send, what you get back, etc.?

prisma basalt
#
    begin
      payment_intent = Stripe::PaymentIntent.create(intent)
    rescue Stripe::StripeError => e
      halt 400,
        { 'Content-Type' => 'application/json' },  
        { error: { message: e.error.message }}.to_json
    rescue => e
      halt 500,
        { 'Content-Type' => 'application/json' },
        { error: { message: e.error.message }}.to_json
    end
    {
      clientSecret: payment_intent.client_secret,
    }.to_json
  end
```I have this snippet in my code to catch errors but I didn't do any logs
zenith canyon
#

then you want to add clear logs everywhere to track what's happening