<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nadir Hussain</title>
    <description>The latest articles on DEV Community by Nadir Hussain (@nadirhusaain).</description>
    <link>https://dev.to/nadirhusaain</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1127217%2F44b5d8f6-6514-4fb2-add8-943831a30bc1.jpg</url>
      <title>DEV Community: Nadir Hussain</title>
      <link>https://dev.to/nadirhusaain</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nadirhusaain"/>
    <language>en</language>
    <item>
      <title>I Spent Days Choosing Between Hosted Checkout, Embedded Checkout, and Custom Payment APIs — Here's What I Learned</title>
      <dc:creator>Nadir Hussain</dc:creator>
      <pubDate>Wed, 05 Aug 2026 12:08:43 +0000</pubDate>
      <link>https://dev.to/nadirhusaain/i-spent-days-choosing-between-hosted-checkout-embedded-checkout-and-custom-payment-apis-heres-2d6a</link>
      <guid>https://dev.to/nadirhusaain/i-spent-days-choosing-between-hosted-checkout-embedded-checkout-and-custom-payment-apis-heres-2d6a</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;If you're integrating payments for the first time, don't make the same mistake I did.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first payment integration I worked on wasn't difficult because of the code.&lt;/p&gt;

&lt;p&gt;It was difficult because I had no idea &lt;strong&gt;which integration approach I should choose&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I opened the documentation for a payment provider expecting a simple guide. Instead, I was greeted with multiple options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hosted Checkout&lt;/li&gt;
&lt;li&gt;Embedded Checkout&lt;/li&gt;
&lt;li&gt;Payment Intents&lt;/li&gt;
&lt;li&gt;Custom APIs&lt;/li&gt;
&lt;li&gt;Webhooks&lt;/li&gt;
&lt;li&gt;Client Secrets&lt;/li&gt;
&lt;li&gt;Tokens&lt;/li&gt;
&lt;li&gt;Sessions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a beginner, I kept asking myself:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"Why are there so many ways to charge a customer?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I wasn't confused by JavaScript.&lt;/p&gt;

&lt;p&gt;I wasn't confused by APIs.&lt;/p&gt;

&lt;p&gt;I was confused because &lt;strong&gt;every approach seemed capable of doing the exact same thing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;They all accepted payments.&lt;/p&gt;

&lt;p&gt;So why did they all exist?&lt;/p&gt;

&lt;p&gt;It wasn't until I worked on several real-world payment systems—from simple SaaS subscriptions to platforms supporting multiple payment providers—that everything finally clicked.&lt;/p&gt;

&lt;p&gt;The biggest lesson I learned was this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;There is no "best" payment integration. There is only the right solution for your product.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you're facing the same confusion today, this article will save you hours (or even days) of reading documentation.&lt;/p&gt;

&lt;p&gt;Let's break it down.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Three Ways to Accept Payments
&lt;/h1&gt;

&lt;p&gt;Almost every modern payment provider offers one or more of these integration methods.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fno7uy7k12kwk2ugutci9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fno7uy7k12kwk2ugutci9.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At first glance, they all accomplish the same goal:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Take money from a customer.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But they differ significantly in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security responsibilities&lt;/li&gt;
&lt;li&gt;Development complexity&lt;/li&gt;
&lt;li&gt;User experience&lt;/li&gt;
&lt;li&gt;Customization&lt;/li&gt;
&lt;li&gt;Maintenance&lt;/li&gt;
&lt;li&gt;Scalability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's look at each one.&lt;/p&gt;




&lt;h1&gt;
  
  
  Option 1: Hosted Checkout
&lt;/h1&gt;

&lt;p&gt;This is the simplest way to accept payments.&lt;/p&gt;

&lt;p&gt;Instead of building a payment page yourself, you redirect the customer to a secure checkout page hosted by the payment provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Flow Looks Like
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgm4vhvnp7s9uwu44vggf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgm4vhvnp7s9uwu44vggf.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your application creates a checkout session.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sessions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;payment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;line_items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...],&lt;/span&gt;
  &lt;span class="na"&gt;success_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cancel_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then simply redirect the user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;No card handling.&lt;/p&gt;

&lt;p&gt;No PCI headaches.&lt;/p&gt;

&lt;p&gt;No complex frontend.&lt;/p&gt;

&lt;p&gt;The provider owns the checkout experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Companies Choose It
&lt;/h2&gt;

&lt;p&gt;Hosted checkout is perfect when your priority is getting payments working quickly and securely.&lt;/p&gt;

&lt;p&gt;The provider takes care of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Card validation&lt;/li&gt;
&lt;li&gt;3D Secure authentication&lt;/li&gt;
&lt;li&gt;Fraud prevention&lt;/li&gt;
&lt;li&gt;PCI compliance&lt;/li&gt;
&lt;li&gt;Security updates&lt;/li&gt;
&lt;li&gt;Payment UI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your job is simply to create the checkout session and listen for the result.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Fastest implementation&lt;/li&gt;
&lt;li&gt;Highest level of security&lt;/li&gt;
&lt;li&gt;Minimal maintenance&lt;/li&gt;
&lt;li&gt;Excellent for MVPs&lt;/li&gt;
&lt;li&gt;Very reliable&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Customer leaves your website&lt;/li&gt;
&lt;li&gt;Limited branding&lt;/li&gt;
&lt;li&gt;Less control over the checkout experience&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Option 2: Embedded Checkout
&lt;/h1&gt;

&lt;p&gt;What if you want customers to stay on your website?&lt;/p&gt;

&lt;p&gt;That's where embedded checkout comes in.&lt;/p&gt;

&lt;p&gt;Instead of redirecting users, you embed the provider's secure payment form directly into your application.&lt;/p&gt;

&lt;p&gt;Think of it like renting a secure payment form rather than building one yourself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhtv219qhx0e534iobf66.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhtv219qhx0e534iobf66.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The user never leaves your application.&lt;/p&gt;

&lt;p&gt;Yet the provider still securely handles sensitive payment information.&lt;/p&gt;

&lt;p&gt;With Stripe Elements, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CardElement&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handlePayment&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  Pay Now
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the backend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paymentIntent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentIntents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;usd&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then confirm the payment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;confirmCardPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;payment_method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CardElement&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✅ Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Better user experience&lt;/li&gt;
&lt;li&gt;Customers stay on your website&lt;/li&gt;
&lt;li&gt;More customizable&lt;/li&gt;
&lt;li&gt;Secure&lt;/li&gt;
&lt;li&gt;Professional checkout experience&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;More frontend work&lt;/li&gt;
&lt;li&gt;More backend coordination&lt;/li&gt;
&lt;li&gt;More payment state management&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Option 3: Custom Payment APIs
&lt;/h1&gt;

&lt;p&gt;This is the approach that fascinated me the most when I started.&lt;/p&gt;

&lt;p&gt;I assumed:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"If large companies use custom APIs, then I should too."&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That assumption was wrong.&lt;/p&gt;

&lt;p&gt;Custom APIs give you complete control—but they also give you complete responsibility.&lt;/p&gt;

&lt;p&gt;Instead of relying on hosted pages or embedded components, you build the entire payment experience yourself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F30y7ft60h6t3lzmzy66f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F30y7ft60h6t3lzmzy66f.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your frontend sends a request to your backend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/payment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;paymentMethodId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your backend communicates with the payment provider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paymentIntent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentIntents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;payment_method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;confirm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks simple...&lt;/p&gt;

&lt;p&gt;Until reality kicks in.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Hidden Complexity Nobody Talks About
&lt;/h1&gt;

&lt;p&gt;Charging a customer is only a small part of building a payment system.&lt;/p&gt;

&lt;p&gt;A production-ready payment platform usually includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Webhooks&lt;/li&gt;
&lt;li&gt;Signature verification&lt;/li&gt;
&lt;li&gt;Refund workflows&lt;/li&gt;
&lt;li&gt;Subscription renewals&lt;/li&gt;
&lt;li&gt;Retry logic&lt;/li&gt;
&lt;li&gt;Failed payment recovery&lt;/li&gt;
&lt;li&gt;Transaction history&lt;/li&gt;
&lt;li&gt;Audit logs&lt;/li&gt;
&lt;li&gt;Idempotency&lt;/li&gt;
&lt;li&gt;Fraud detection&lt;/li&gt;
&lt;li&gt;Analytics&lt;/li&gt;
&lt;li&gt;Monitoring&lt;/li&gt;
&lt;li&gt;Multiple payment providers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most developers underestimate how much happens &lt;strong&gt;after&lt;/strong&gt; the payment succeeds.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Most Important Lesson I Learned
&lt;/h1&gt;

&lt;p&gt;The payment page is &lt;strong&gt;not&lt;/strong&gt; your payment system.&lt;/p&gt;

&lt;p&gt;Your payment system is everything that happens before and after the customer clicks &lt;strong&gt;Pay&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbg2i96dt9gc0iydpmvbg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbg2i96dt9gc0iydpmvbg.png" alt=" " width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This realization completely changed how I design payment architectures.&lt;/p&gt;




&lt;h1&gt;
  
  
  Which One Should You Choose?
&lt;/h1&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Project Type&lt;/th&gt;
&lt;th&gt;Recommended Method&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Portfolio Website&lt;/td&gt;
&lt;td&gt;Hosted Checkout&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MVP Startup&lt;/td&gt;
&lt;td&gt;Hosted Checkout&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SaaS&lt;/td&gt;
&lt;td&gt;Embedded Checkout&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E-commerce Store&lt;/td&gt;
&lt;td&gt;Embedded Checkout&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Marketplace&lt;/td&gt;
&lt;td&gt;Embedded + APIs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wallet App&lt;/td&gt;
&lt;td&gt;Custom APIs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Banking App&lt;/td&gt;
&lt;td&gt;Custom APIs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Payment Platform&lt;/td&gt;
&lt;td&gt;Custom APIs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The goal isn't to use the most advanced solution.&lt;/p&gt;

&lt;p&gt;The goal is to use the &lt;strong&gt;simplest solution that meets your business requirements.&lt;/strong&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Lessons I Wish Someone Had Told Me Earlier
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Simplicity Wins
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Don't build a custom checkout just because you can.&lt;/li&gt;
&lt;li&gt;Build one only when your product genuinely needs it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Security Is a Feature
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Every line of payment code you own becomes your responsibility.&lt;/li&gt;
&lt;li&gt;Sometimes less code is actually safer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Never Trust the Frontend
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Always verify payments using webhooks.&lt;/li&gt;
&lt;li&gt;Never unlock premium features based only on a frontend success response.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Idempotency Is Essential
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Users refresh pages.&lt;/li&gt;
&lt;li&gt;Networks fail.&lt;/li&gt;
&lt;li&gt;Browsers retry requests.&lt;/li&gt;
&lt;li&gt;Your payment endpoint must safely handle duplicate requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Design for Failure
&lt;/h2&gt;

&lt;p&gt;Always ask yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What happens if the webhook is delivered twice?&lt;/li&gt;
&lt;li&gt;What if the customer closes the browser?&lt;/li&gt;
&lt;li&gt;What if payment succeeds but my database update fails?&lt;/li&gt;
&lt;li&gt;What if the payment provider is temporarily unavailable?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Great payment systems are built around handling failures—not just successful payments.&lt;/p&gt;




&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;Today, when I start integrating a payment gateway, I don't ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"Which API should I use?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead, I ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"What experience do I want my users to have, and how much complexity is my team willing to own?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That single question has helped me make better architectural decisions every time.&lt;/p&gt;

&lt;p&gt;If you're just getting started with payments, begin with a hosted checkout. Understand how payment sessions, webhooks, and payment states work.&lt;/p&gt;

&lt;p&gt;Once you're comfortable, move to embedded checkout for a better user experience.&lt;/p&gt;

&lt;p&gt;Only choose custom APIs when your business requirements truly demand complete control.&lt;/p&gt;

&lt;p&gt;The best payment integration isn't the most complex one.&lt;/p&gt;

&lt;p&gt;It's the one that's secure, maintainable, and fits your product today while giving you room to grow tomorrow.&lt;/p&gt;




&lt;h2&gt;
  
  
  💬 I'd Love Your Thoughts
&lt;/h2&gt;

&lt;p&gt;Which payment integration approach do you prefer?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hosted Checkout&lt;/li&gt;
&lt;li&gt;Embedded Checkout&lt;/li&gt;
&lt;li&gt;Custom APIs&lt;/li&gt;
&lt;li&gt;A combination of all three&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Share your experience in the comments. I'd love to hear how you've approached payment architecture in your own projects.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Unchecked runtime.lastError: The message port closed before a response was received.</title>
      <dc:creator>Nadir Hussain</dc:creator>
      <pubDate>Wed, 26 Jul 2023 20:20:38 +0000</pubDate>
      <link>https://dev.to/nadirhusaain/unchecked-runtimelasterror-the-message-port-closed-before-a-response-was-received-2377</link>
      <guid>https://dev.to/nadirhusaain/unchecked-runtimelasterror-the-message-port-closed-before-a-response-was-received-2377</guid>
      <description>&lt;p&gt;Solution&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here is video link in  which Error solution is give:&lt;/strong&gt;&lt;br&gt;
 &lt;a href="https://youtu.be/GtqYP1EBly4"&gt;https://youtu.be/GtqYP1EBly4&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here is description of Error Solution&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gNno8Jky--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ydqx4w0lnvbvf0srgpd4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gNno8Jky--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ydqx4w0lnvbvf0srgpd4.jpg" alt="Image description" width="481" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why this error occur?&lt;br&gt;
This error occur because of extensions that don't handle async code correctly and Interactions with other installed extensions can sometimes cause communication issues, leading to this error.&lt;br&gt;
Names of some extensions that cause this error:&lt;br&gt;
• 1password extension&lt;br&gt;
• Color Contrast Analyzer&lt;br&gt;
• Kaspersky browser extension&lt;br&gt;
• Tampermonkey&lt;br&gt;
• MeddleMonkey&lt;br&gt;
• Pinterest extension&lt;br&gt;
• Stay focused&lt;br&gt;
• Piggy – Automatic Coupons &amp;amp; Cash Back&lt;br&gt;
• BuiltWith Technology Profiler&lt;br&gt;
• HonorLock&lt;br&gt;
• Video Downloader Professional&lt;br&gt;
• AdGuard&lt;br&gt;
• Adskill&lt;br&gt;
• Augury&lt;br&gt;
• Automation 360&lt;br&gt;
• Color Contrast Analyzer&lt;br&gt;
• Dark Reader &lt;br&gt;
• Different Adblocker extensions&lt;br&gt;
• DuckDuckGo Privacy Essentials&lt;br&gt;
• Font Scanner&lt;br&gt;
• Free VPN for Chrome - VPN Proxy VeePN&lt;br&gt;
• Ghostery&lt;br&gt;
• Google Publisher Toolbar&lt;br&gt;
• Google Voice&lt;br&gt;
• Google™ Search Keyboard Shortcuts&lt;br&gt;
• HTML Validator&lt;br&gt;
• Norton Safe Search, Norton Safe Web,&lt;br&gt;
• OrangeMonkey&lt;br&gt;
• OurStickys - Sticky Notes&lt;/p&gt;

&lt;p&gt;How can we configure which extension is cause of this error?&lt;br&gt;
Here are some steps to follow:&lt;br&gt;
Step 1: Click on extension icon&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R110DDtw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pc0rpl6z52oy1tm7f0fg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R110DDtw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pc0rpl6z52oy1tm7f0fg.jpg" alt="Image description" width="263" height="323"&gt;&lt;/a&gt;&lt;br&gt;
Step 2: Click on manage extensions&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mPzR0VIR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aa3gtyf0xfl1vz1rpmll.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mPzR0VIR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aa3gtyf0xfl1vz1rpmll.jpg" alt="Image description" width="399" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 3: Disable extension button&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xgWrf85s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ofufzjww92frlcr1pm5i.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xgWrf85s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ofufzjww92frlcr1pm5i.jpg" alt="Image description" width="800" height="207"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5dkJ8oNB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y4h0pms5d8ik5s0cohvx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5dkJ8oNB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y4h0pms5d8ik5s0cohvx.jpg" alt="Image description" width="800" height="209"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 4: Then finally click on F5 button to refresh the tab on which react app is loaded. After disabling extension the error will be removed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2wRfLJZK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6tzxyibr4g9n9aeszp5b.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2wRfLJZK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6tzxyibr4g9n9aeszp5b.jpg" alt="Image description" width="501" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
