Skip to content

candypay/elements

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

53 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CandyPay payment component

Integrate payment component natively in your platform and start accepting SOL and SPL token payments, seamlessly!

Installation

npm install @candypay/elements @candypay/checkout-sdk

Usage

  1. First, wrap your app in the CheckoutProvider component as shown below:
import { CheckoutProvider } from "@candypay/elements";
import { AppProps } from "next/app";

const App = ({ Component, pageProps }: AppProps) => {
  return (
    <CheckoutProvider
      network="mainnet" // or "devnet"
    >
      <Component {...pageProps} />
    </CheckoutProvider>
  );
};

export default App;
  1. Using the PayElement component:
import { CreateIntentResponse } from "@candypay/checkout-sdk";
import axios from "axios";
import { PayElement } from "@candypay/elements";
import { toast } from "react-hot-toast";

export default function Web() {
  const intentHandler = async (): Promise<CreateIntentResponse> => {
    const res = await axios.post("/api/intent/create");
    return res.data;
  };

  return (
    <>
      <PayElement
        intentHandler={intentHandler}
        onSuccess={() => {
          console.log("success");
          toast.success("Payment successful");
        }}
        onError={() => {
          console.log("error");
          toast.error("Payment failed");
        }}
      />
    </>
  );
}
  1. API Handler to create the intent (using the checkout-sdk):
  • lib/init/candypay.ts
import { CandyPay } from "@candypay/checkout-sdk";

const candypay = new CandyPay({
  api_keys: {
    public_api_key: process.env[`NEXT_PUBLIC_CP_API`] as string,
    private_api_key: process.env[`CANDYPAY_PRIVATE_KEY`] as string,
  },
  network: "mainnet",
  config: {
    collect_shipping_address: false,
  },
});

export { candypay };
  • pages/api/intent/create.ts
import { NextApiHandler } from "next";
import { candypay } from "../../../lib/init/candypay";

const handler: NextApiHandler = async (req, res) => {
  if (req.method !== "POST") {
    res.status(405).end();
    return;
  }

  const response = await candypay.paymentIntent.create({
    tokens: ["shdw", "bonk"],
    items: [
      {
        name: "Nike Air Force",
        image:
          "https://static.nike.com/a/images/t_PDP_864_v1/f_auto,b_rgb:f5f5f5/b7d9211c-26e7-431a-ac24-b0540fb3c00f/air-force-1-07-shoes-WrLlWX.png",
        price: 0.1,
        quantity: 1,
      },
    ],
  });

  return res.status(200).json(response);
};

export default handler;

In the above example, candypay is an instance of the CandyPay class from the checkout-sdk package. The paymentIntent.create method returns a CreateIntentResponse object, which is used by the PayElement component to render the payment form.

Props

PayElement

Prop Type Description
intentHandler () => Promise<CreateIntentResponse> A function that returns a CreateIntentResponse object. This is used to create the payment intent.
onSuccess () => void A function that is called when the payment is successful.
onError () => void A function that is called when the payment fails.
theme Theme Primary and secondary colors to be used for the component.

Theme

Example theme object:

const theme = {
  primaryColor: "#ff0000",
  secondaryColor: "#0000ff",
};

onSuccess

The onSuccess prop is called when the payment is successful. It is passed an object with the following params:

{
  customer: string; // the public key of the customer in string format
  signature: string; // signature of the transaction
}

Example

<PayElement
  intentHandler={intentHandler}
  onSuccess={(d: SuccessResponse) => {
    console.log(d.signature);
    toast.success("Payment successful");
  }}
  onError={() => {
    console.log("error");
    toast.error("Payment failed");
  }}
/>

In the above example, SuccessResponse is a type imported from the sdk like so:

import { SuccessResponse } from "@candypay/elements";

If you're using js, you can ignore assigning the type to the onSuccess prop.

NOTE: If you're using Vercel serverless functions then the initial API request might take a while because of the cold start.