Custom button text on Stripe Form

When collecting credit card information using stripe.checkout.get_token(), the button text is labeled Pay (possibly with an amount included if it is specified). This makes good sense for a one-time payment, but if this form is used to start a subscription or to change a default credit card source, this text may not make sense to the end user.

See this post for additional context: https://anvil.works/forum/t/change-stripe-subscription-default-payment-method/2855

It would be nice to have the ability to customize the text displayed on this button to something like Update Card or Start Subscription instead of just Pay.

6 Likes

yes please this has caused many confused customers. does anyone know of a css workaround?

1 Like

@meredydd do you know of a quick workaround for changing the text of the checkout.get_token() widget?

1 Like

Running into the same issue. I was just curious if there have been any updates on this request?

A follow-up - does anyone know of any documentation or python way of finding out all the function arguments to stripe.checkout.charge? I couldn’t get the inspect module to work within Anvil for this case.

Or is the example from the docs all inclusive?

charge = stripe.checkout.charge(currency="GBP",
                                amount=999,
                                title="Acme Store",
                                description="3 Widgets",
                                zipcode=True,
                                icon_url=anvil.server.get_app_origin + "/_/theme/icon.png",
                                billing_address=True)
1 Like

The API docs for that function suggest there is also shipping_address

2 Likes

Has there been an update on this? !!

1 Like

I can’t believe this has not been taken care of for so many years. I’ve been testing stripe to see if it’s the right choice for me, but this might be a deal braker.

I won’t set up a subscription for my customers with a misleading button label.

I thought the same thing, but a quick fix is to use a payment link, this directs the user to a nice up-to-date Stripe website, which you can customize to your needs. Then, after payments you can, instead of going to the standard checkout page you can redirect your user back to your webapp with a session_id, from that you can extract all the user information and subscription status.

In stripe you type in

https://yourwebsite.com/#checkout?session_id={CHECKOUT_SESSION_ID}

as your payment link redirect after payment.

Use the following code to create a page:

from anvil_extras import routing
@routing.route('checkout', url_keys=['session_id'])

class StripeSuccess(StripeSuccessTemplate):
  def __init__(self, **properties):
    # Set Form properties and Data Bindings.
    self.init_components(**properties)
    self.session_id = self.url_dict['session_id']


  def form_show(self, **event_args):
    result = anvil.server.call_s('stripe_success', self.session_id)

On the serverside:

@anvil.server.callable
def stripe_succes(session_id):
  import anvil.secrets
  import stripe
  import anvil.stripe
  stripe.api_key = anvil.secrets.get_secret('stripe_key_live')
  checkout_session = stripe.checkout.Session.retrieve(session_id)
  customer_id = checkout_session.customer
  customer = anvil.stripe.get_customer(customer_id)
  subscription_ids = customer.get_subscription_ids()

Then you check if you price plan id ‘price_…’ is in subscription_ids.

I read somewhere that it is not super safe and that it would be better to use a webhook or something. But for small apps, it could work.

3 Likes

You can also redirect to an HTTP endpoint, and then return an HTTP redirect from that endpoint to get the user’s browser to where you want in the client, to help with the security aspect.

Can you let me know how that is safer?

No code in the client is executed to handle the Stripe redirect. So there’s no opportunity for someone to manipulate the form code that is making the server call. Instead, the browser calls the HTTP endpoint directly via the URL you gave to Stripe, sending the Stripe session id to the HTTP endpoint. The HTTP endpoint executes on the Anvil server, which is in a secure environment.

When you return the HTTP redirect from the HTTP endpoint, the Anvil client starts up on the page you specify. But that’s well after the Stripe redirect has been handled on the server.

Can’t they simply manipulate the url? Wouldn’t that be the same thing as changing the form?

If on the server is checked if the redirect is coming from stripe. Then I think it is safe?

It depends. We’re deep into a rabbit hole of hypotheticals here. In general, the fewer sensitive tasks you carry out on the client, the better. The less sensitive data that passes through the client, the better.

In both situations a malicious user could intercept the Stripe redirect and change the Stripe session id that gets passed to the server. Does that actually benefit them? I doubt it, but I’m not an expert in that area.

None of this really has anything to do with changing the button text on the Stripe form, though. Your suggestion of using Stripe checkout instead of the built-in Anvil integration is the right answer for that, since what Anvil uses is really designed for one-off payments. For subscriptions, the Stripe provided forms are going to look better and be more customizable.

1 Like