🔧 AI Nachrichten Debian is Voting on Whether to Allow AI-Assisted Contributions(23.08.2026 um 09:34 Uhr)
🔧 AI Nachrichten The Linux Kernel Is Approaching 2,000 CVEs Per Release(29.08.2026 um 20:00 Uhr)
⚠️ Malware / Trojaner / VirenCitrix Adds a Linux-Powered Escape Hatch For Compromised Windows PCs(30.08.2026 um 17:34 Uhr)
🔧 AI Nachrichten Debian is Voting on Whether to Allow AI-Assisted Contributions(23.08.2026 um 09:34 Uhr)
🔧 AI Nachrichten The Linux Kernel Is Approaching 2,000 CVEs Per Release(29.08.2026 um 20:00 Uhr)
⚠️ Malware / Trojaner / VirenCitrix Adds a Linux-Powered Escape Hatch For Compromised Windows PCs(30.08.2026 um 17:34 Uhr)

🔧 Programmierung 🕛 vor 1 Jahr 26 Min Lesezeit
0

Creating and Paying a Freight Invoice with the Rapyd API and FX

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

By: Kevin Kimani



A guaranteed refund system allows users to subscribe to a service with an assurance that they can cancel within a specified time frame if they're dissatisfied and receive a full refund. This not only builds trust but also encourages potential subscribers to take the plunge, knowing they have an exit strategy if the service does not meet their expectations.



and . In this scenario, you'll assume that you're a service provider offering a subscription-based service with a weekly billing of $1.99. Your customer in the US can subscribe using the "us_debit_visa_card" payment method, as per the available options and account

  • .

  • Access to the to the Rapyd API.






  • Cloning the Starter Template



    To make it easy to follow along, you can clone and build on the premade starter template. To clone it to your local machine, execute the following:




    CODE
    git clone --single-branch -b starter-template https://github.com/kimanikevin254/rapyd-guaranteed-refund-system.git






    This will create a folder named rapyd-guaranteed-refund-system. Execute the commands below to cd into the project folder, install the project dependencies, and run the Next.js application:




    CODE
    cd rapyd-guaranteed-refund-system && npm i && npm run dev






    Once all the dependencies have been installed and the Next.js server is running, navigate to http://localhost:3000/ on your browser, and you should see the login page.





    This dashboard contains hard-coded data that shows your current subscription. It also allows you to log out.



    To build on this starter template and implement a guaranteed refund system with the Rapyd API, you'll do the following:




    1. Create a service and a plan.

    2. Create a customer with a payment method and simulate 3DS authentication.

    3. Create a subscription for a customer.

    4. Enable the customer to cancel the subscription and request a refund.






    Creating a Service and a Plan



    In Rapyd, a service is a type of that defines the pricing structure for the service. To create a service, you'll use the Rapyd Postman collection. Once you import the collection into Postman, you should have something similar to this:



    under "Get Your API Keys". Make sure you save the changes. After setting up your environment, you should end up with something like this:



    .

  • If the customer is successfully created on Rapyd, you will store their credentials in the SQLite database. This makes it possible to retrieve the Rapyd customer ID from the database when a user logs into your site.

  • After you store the details in the database, you will then on Rapyd before storing the credentials in the SQLite database. Once a customer is successfully created on Rapyd, their credentials are stored in the database and the code returns a response with some data. In the returned data is card_auth_link, which contains a link used to simulate 3DS authentication. This link is extracted from the response received from the Rapyd API after creating the customer.






    Passing the Necessary Props for 3DS Authentication



    Now you need to update the app/page.js file to include a state that will store the 3DS authentication link returned from the API call and pass it down to the Signup component via the FormSwitcher component. The 3DS authentication link also needs to be passed down to the Dashboard component so that the 3DS authentication page can be displayed to users who have not authenticated their cards.



    Add the following state to the app/page.js file:




    CODE
    // Set the link to perform 3DS auth
    const [cardAuthLink, setCardAuthLink] = useState(null)






    You also need to modify the JSX as shown below to pass the state to the appropriate components:




    CODE
    <div className='p-4 h-screen w-screen overflow-hidden'>
    {
    !user ?
    <FormSwitcher checkUserInfo={checkUserInfo} setCardAuthLink={setCardAuthLink} /> :
    <Dashboard checkUserInfo={checkUserInfo} cardAuthLink={cardAuthLink} setCardAuthLink={setCardAuthLink} />
    }
    </div>






    Open the components/FormSwitcher.js file and make sure you are destructuring the new props that you just passed down in the previous step:




    CODE
    function FormSwitcher({ checkUserInfo, setCardAuthLink }) {
    // Rest of the code






    In the same file, make sure you are passing the setCardAuthLink function to the Signup component.




    CODE
    <Signup checkUserInfo={checkUserInfo} setCardAuthLink={setCardAuthLink} />






    Next, you need to modify the components/Signup.js file to use the setCardAuthLink function to update the cardAuthLink state with the 3DS authentication link received from the API call. In the components/Signup.js file, destructure all the props passed to this component as shown below:




    CODE
    function Signup({ checkUserInfo, setCardAuthLink }) {






    In the createCustomer function, add the following code above the localStorage.setItem('user_info', JSON.stringify(data.user)) line of code:




    CODE
    // cardAuthLink state update
    if (data.user.card_auth_link) {
    setCardAuthLink(data.user.card_auth_link)
    }







    This code accesses the 3DS authentication link from the response and updates the cardAuthLink state.






    Checking If a Customer's Card Is Authenticated



    You need to implement an API endpoint that you will use to confirm if the customer's card has been authenticated. Create a new file retrievecustomer/route.js in the app/api/auth folder and add the following code:




    CODE
    import { makeRequest } from "@/utils/makeRequest";

    export async function POST(req, res){
    const { customer_id } = await req.json()

    try {
    const result = await makeRequest('GET', `/v1/customers/${customer_id}`);

    const next_action = result.body.data.payment_methods.data[0].next_action

    return new Response(
    JSON.stringify({
    message: next_action,
    }),
    {
    headers: { "Content-Type": "application/json" },
    status: 200,
    }
    );
    } catch (error) {
    console.error("Error completing request", error);
    // Return an error
    return new Response(
    JSON.stringify({
    error: "Unable to retrieve the customer",
    }),
    {
    headers: { "Content-Type": "application/json" },
    status: 400,
    }
    );
    }
    }






    This code extracts a customer_id from the request body and makes an HTTP GET request to the Rapyd API to retrieve information related to the customer. From the response received, it extracts the next_action and then returns the appropriate response based on the success or failure of the request.






    Updating the Login Logic



    You need to update the login logic so that a customer can log in to your application and retrieve the subscriptions. To do this, open the app/api/auth/login/route.js file and replace the locate the following code:




    CODE
    return new Response(JSON.stringify({
    user: {
    id: existingUser.id,
    name: existingUser.name,
    email: existingUser.email,
    }
    }), {
    headers: { 'Content-Type': 'application/json' },
    status: 200
    })






    Replace it with the following:




    CODE
    return new Response(JSON.stringify({
    user: {
    id: existingUser.id,
    name: existingUser.name,
    email: existingUser.email,
    rapyd_cust_id: existingUser.rapyd_cust_id
    }
    }), {
    headers: { 'Content-Type': 'application/json' },
    status: 200
    })






    The new code returns rapyd_cust_id as part of the response, which is saved to the browser's local storage in the Login component. This makes it easy to retrieve the customer's details from Rapyd when the customer logs in to your application.






    Creating a Subscription



    You've now implemented the logic for creating a customer and simulating 3DS authentication, so the next step is to create a subscription for the customer.



    To do this, create a new folder named subscriptions in the app/api folder. In the newly created folder, create the file create/route.js and add the code below:




    CODE
    import { makeRequest } from "@/utils/makeRequest";

    export async function POST(req, res) {
    const { customer_id } = await req.json();

    try {
    const body = {
    customer: customer_id,
    billing: "pay_automatically",
    cancel_at_period_end: true,
    days_until_due: 0,
    simultaneous_invoice: true,
    subscription_items: [
    {
    plan: "<your-plan-id>",
    quantity: 1,
    },
    ],
    };
    const result = await makeRequest(
    "POST",
    "/v1/payments/subscriptions",
    body
    );

    return new Response(
    JSON.stringify({
    message: "Subscription created successfully",
    }),
    {
    headers: { "Content-Type": "application/json" },
    status: 200,
    }
    );
    } catch (error) {
    console.error("Error completing request", error);

    return new Response(
    JSON.stringify({
    error: "Unable to create subscription.",
    }),
    {
    headers: { "Content-Type": "application/json" },
    status: 400,
    }
    );
    }
    }






    This code retrieves the customer's ID from the request body and attempts to create a subscription for the customer. Remember to replace <your-plan-id> with the plan ID that you copied from Postman earlier.



    In the JSON object that you pass to Rapyd, customer defines the ID of the customer you want to create a subscription for. billing determines the billing method at the end of the billing cycle. It is set to pay_automatically, which instructs Rapyd to create a payment object and attempt to make a payment using the designated payment method. cancel_at_period_end indicates that the subscription is canceled at the end of the current billing period. subscription_items defines the plans that the user is subscribing to and the quantity.



    The code returns a response with the message "Subscription created successfully" if the request is successful. If an error is encountered, the code returns a response with the error message.






    Retrieving Subscriptions



    To retrieve a customer's subscriptions, create a new file list/route.js in the app/api/subscriptions folder and paste in the code below:




    CODE
    import { makeRequest } from "@/utils/makeRequest";

    export async function POST(req, res) {
    const { customer_id } = await req.json();

    try {
    const result = await makeRequest(
    "GET",
    `/v1/payments/subscriptions?customer=${customer_id}`
    );

    return new Response(
    JSON.stringify({
    subscriptions: result.body.data,
    }),
    {
    headers: { "Content-Type": "application/json" },
    status: 200,
    }
    );
    } catch (error) {
    console.error("Error completing request", error);

    return new Response(
    JSON.stringify({
    error: "Unable to fetch the subscriptions data.",
    }),
    {
    headers: { "Content-Type": "application/json" },
    status: 400,
    }
    );
    }
    }






    This code retrieves the customer's subscriptions using the provided customer ID and returns the result of this operation. In case an error is encountered, the code returns a response with the error message.






    Canceling a Subscription and Requesting a Full Refund



    To allow users to cancel a subscription and request a full refund, create the new file cancelandrefund/route.js in the app/api/subscriptions folder and paste in the code below:




    CODE
    import { makeRequest } from "@/utils/makeRequest";

    export async function POST(req, res) {
    const { subscription_id } = await req.json();

    // Retrieve the subscription from Rapyd
    try {
    const result = await makeRequest(
    "GET",
    `/v1/payments/subscriptions/${subscription_id}`
    );

    // Retrieve the subscription creation date
    const subscription_creation_date = result.body.data.created_at;

    // Check if the customer is eligible for a refund
    let epoch_seconds = Math.floor(new Date().getTime() / 1000);
    let days_since_creation =
    (epoch_seconds - subscription_creation_date) / (24 * 60 * 60);

    // For users who are not eligible for a refund,
    // the subscription will be canceled at the end of the billing cycle
    if (days_since_creation > 7) {
    try {
    const result = await makeRequest(
    "DELETE",
    `/v1/payments/subscriptions/${subscription_id}`,
    {
    cancel_at_period_end: true,
    }
    );

    return new Response(
    JSON.stringify({
    message: "Subscription canceled successfully",
    }),
    {
    headers: { "Content-Type": "application/json" },
    status: 200,
    }
    );
    } catch (error) {
    console.error("Error completing request", error);

    return new Response(
    JSON.stringify({
    error: "Unable to cancel subscription",
    }),
    {
    headers: { "Content-Type": "application/json" },
    status: 400,
    }
    );
    }
    }

    // For users who are eligible for a refund,
    // the subscription will be canceled immediately
    // and a refund will be issued.
    else {
    // Cancel subscription
    try {
    const result = await makeRequest(
    "DELETE",
    `/v1/payments/subscriptions/${subscription_id}`
    );

    // Retrieve the payment associated with the subscription
    try {
    const result = await makeRequest(
    "GET",
    `/v1/payments?subscription=${subscription_id}`
    );

    let subscription_payment_id = result.body.data[0].id;

    // Create a refund
    try {
    const body = {
    payment: subscription_payment_id,
    reason: "Subscription canceled within allowed timeframe.",
    };
    const result = await makeRequest(
    "POST",
    "/v1/refunds",
    body
    );

    return new Response(
    JSON.stringify({
    message:
    "Subscription canceled and refund issued successfully!",
    }),
    {
    headers: { "Content-Type": "application/json" },
    status: 200,
    }
    );
    } catch (error) {
    console.error("Error completing request", error);
    }
    } catch (error) {
    console.error("Error completing request", error);
    }
    } catch (error) {
    console.error("Error completing request", error);
    }
    }
    } catch (error) {
    console.error("Error completing request", error);

    return new Response(
    JSON.stringify({
    error: "Unable to retrieve the subscription.",
    }),
    {
    headers: { "Content-Type": "application/json" },
    status: 400,
    }
    );
    }
    }






    The code extracts the subscription_id from the request body and uses it to fetch subscription details from the Rapyd API. It gets the creation date and stores it in the variable subscription_creation_date. The code then calculates the days since creation and checks eligibility for a refund. If more than seven days have passed, the user is not eligible for a refund and the subscription is set to cancel at the billing cycle's end. For eligible customers, it immediately , extracts the payment ID associated with the subscription, and



    Fill out 123456 in the input box and select Continue, and the page will display a message indicating that the details are being authenticated. In the background, the app is making a request to the Rapyd API to check if your card has been authenticated.





    Click the Subscribe Now button to subscribe to the "CineView Unlimited - Weekly Plan". The page will show the loading message and then display your current subscription.





    Click the OK button on the alert, and the status of the subscription will be indicated as "Canceled". This means that the subscription has been canceled by the customer but remains in the Rapyd database.



    to confirm that the refund was issued successfully.



    .

    Vollständiger Original-Bericht
    Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
    ↗ Original-Artikel auf dev.to lesen
  • Wie bewertest du diesen Beitrag?
    1 Klick Feedback
    Teilen mit Netzwerk & Team:

    Community-Analysen & Experten-Meinungen 0

    Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
    Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
    Community Pulse: Relevanz-Einschätzung
    1 Klick Experten-Votum
    🔴 Akute Relevanz 0%
    🟡 In Evaluierung 0%
    🟢 Keine Auswirkung 0%
    Spannende Innovation 0%
    Verwandte Story-Cluster & Quellen (Vektor-KI)
    Port 8095 Engine
    1 Quelle
    Debian is Voting on Whether to Allow AI-Assisted Contributions
    1 Quelle
    The Linux Kernel Is Approaching 2,000 CVEs Per Release
    1 Quelle
    Citrix Adds a Linux-Powered Escape Hatch For Compromised Windows PCs
    Ähnliche Beiträge
    🔍 Verwandte News

    Auch interessante Nachrichten Creating and Paying a Freight Invoice with the Rapyd API and FX

    Thematisch verwandte Begriffe: Creating, Paying, Freight, Invoice · 6 Treffer

    Laden...

    Videos werden geladen ...

    Laden...

    Beiträge werden geladen ...

    Laden...

    Videos werden geladen ...

    Laden...

    Beiträge werden geladen ...

    Laden...

    Videos werden geladen ...

    Laden...

    Beiträge werden geladen ...

    Laden...

    Videos werden geladen ...

    Laden...

    Beiträge werden geladen ...

    Laden...

    Videos werden geladen ...