まいにちDapps#2 クレカ決済できるNFTのmintサイトの作り方

ponta

ponta

· 5 min read
クレカ決済できるNFTのmintサイトの作り方

まいにちDappsの2日目は、前日に続いてNFTのmintサイトを作成しますが、クレジットカード💳での支払いに対応していきます。私たちが受託開発を行う際、クライアントからは非クリプトユーザーに対応した機能の1つとしてクレカ決済が要望されることがあります(個人的には必ずしも良い策だとは思わないですが😅)。

今回は以下のいくつかの方法を試してみます。

  • Paper.xyzのCheckout機能
  • Crossmint
  • Stripeで実装する方法

Paper.xyzのCheckout機能

Paper.xyzはサービス内ウォレットの導入(Embedding Wallet)や今回使用するCheckout機能などNFT・Dapps開発者のためのツールを提供してくれているサービスです。先日Thirdwebに買収されたことを発表しました。

記事はかなり古いものなので、UIは現在とは異なっていますが、こちらの記事を参考に進めていきます。

https://withpaper.com/dashboard/contracts にアクセスします。Paper.xyzを使ってNFTのコントラクトを新規に作成することも可能ですが、今回はThirdwebで既に作成してあるコントラクトを使いたいので、"Register Contract"ボタンを押します。

Image

Import Contract URLを選択し、ThirdwebのURLを入力します。

Image

まいにちDapps 1日目で作成したNFT Dropのコントラクトをそのまま使用します。

Image

クレカ決済ができる販売リンクが生成されます。

まずNFTを受け取るWalletをConnectする必要がありますが、先述したEmbedding Walletの機能を使ったサービス内ウォレットをemailベースで作成することもできます。

Image

ImageImage

EmailにPINコードが送られてくるのでそれを使用するとウォレットが作成されてクレジットカード画面に遷移できます。

Image

支払われた売り上げの情報はDashboardで確認して、本人確認等が済んだのち引き出すことができます。

Image

また自分のサイトに独自UIで埋め込むこともできるみたいです。

https://docs.withpaper.com/reference/checkoutwithcard

Paperが購入者側から手数料を徴収するのでその点ご注意下さい。

Crossmintの導入

Paper.xyzと似たようなサービスでCrossmintがあります。

こちらの記事公式ドキュメントのQuickStartを元に進めていきます。

staging.crossmint.com/console にアクセスしてDeveloperアカウントを作成します。

https://staging.crossmint.com/console/collections に行き、NFTコントラクトを登録します。

ImageImageImage

ダッシュボードに反映されます。

Image

Next.jsのプロジェクトを立ち上げて導入してみます。

"use client";

import { CrossmintPayButton } from "@crossmint/client-sdk-react-ui";

export default function Home() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <CrossmintPayButton
        collectionId="a1f6cca0-1c24-4226-92c5-f50a85bbd965"
        projectId="28990d6d-1252-4c45-a89f-1a7e0eb4e5bc"
        mintConfig={{
          type: "thirdweb-drop",
          totalPrice: "0.01",
          quantity: "1",
        }}
        environment="staging"
      />
    </main>
  );
}


mintボタンが生成されます。

ImageImageImage

決済部分にはStripeが使われているようです。

ちなみにStripeのステージングモードではクレカ番号は424242424242で行けます。

ImageImage

一度crossmint内に生成されたウォレットに対してmintされているようです。

Image

好きなウォレットにガスレスで送ってくれるようです。

Image

こちらも十分使いやすいと思いました。

Stripeで実装

最後に比較的自力で実装するケースを紹介します。

アーキテクチャとしてはシンプルで、Stripeでクレカ決済を行い、成功したらwebhookをキャッチしてそこでNFTをウォレットに対してmintするというものです。

Thirdwebでコントラクトをデプロイしておきます。

次に、Stripeのテストモードで商品を準備します。Productページから "+Add Product" をクリックして商品を追加します。subscriptionではなく単品にします。

Image

作成した商品のprice_idと開発者アカウントのSecret_Keyを取得しておきます。

次にNFT mintサイトを作ります。Next.jsのプロジェクトを立ち上げます。

トップページにボタンを設置、API層にstripe-checkoutというapiを生やします。

import { NextResponse } from "next/server";
import Stripe from "stripe";

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY || "", {
  apiVersion: "2022-11-15",
});

export async function POST(request: Request) {
  const data = await request.json();
  const { address } = data;
  const session = await stripe.checkout.sessions.create({
    line_items: [
      {
        price: process.env.STRIPE_PRICE_ID,
        quantity: 1,
      },
    ],
    payment_method_types: ["card"],
    mode: "payment",
    success_url: `${process.env.NEXT_PUBLIC_BASE_URL}/success`,
    cancel_url: `${process.env.NEXT_PUBLIC_BASE_URL}/?canceled=true`,
    allow_promotion_codes: true,
    metadata: { address: address },
  });

  return NextResponse.json({
    session_id: session.id,
    checkout_url: session.url,
  });
}
"use client";
import { ConnectWallet, useAddress } from "@thirdweb-dev/react";
import { useRouter } from "next/navigation";

export default function Home() {
  const address = useAddress();
  const router = useRouter();

  const payment = async () => {
    const response: any = await fetch(`/api/stripe-checkout`, {
      method: "POST",
      body: JSON.stringify({
        address: address,
      }),
    });
    console.log(response);
    const result = await response.json();
    router.push(result.checkout_url);
  };

  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      {address ? (
        <button
          type="button"
          onClick={payment}
          className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 mr-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800"
        >
          Payment
        </button>
      ) : (
        <ConnectWallet></ConnectWallet>
      )}
    </main>
  );
}

ボタンを押すとStripeの決済画面に飛ぶ仕組みができました。

Image

webhookを作ります。

https://dashboard.stripe.com/test/webhooks

テストするにはwebhookのエンドポイントをリモートからアクセス可能にする必要があるのでvercelにデプロイするか、開発中であればngrokなどで一時的なurlを取得する方法があります。

Image

上記画像の右側にあるコードをNextに適切なコードに変更します。

import { headers } from "next/headers";
import { NextResponse } from "next/server";
import { ThirdwebSDK } from "@thirdweb-dev/sdk";

import Stripe from "stripe";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY || "", {
  apiVersion: "2022-11-15",
});

export async function POST(request: Request) {
  const bodyString = await request.text();
  const body = JSON.parse(bodyString);
  const signature = headers().get("Stripe-Signature") as string;
  let event: Stripe.Event;

  try {
    event = stripe.webhooks.constructEvent(
      bodyString,
      signature,
      process.env.STRIPE_ENDPOINT_SECRET || ""
    );
  } catch (err: any) {
    return NextResponse.error();
  }

  switch (event.type) {
    case "checkout.session.completed":
      const checkoutSessionCompleted = event.data.object;
      // Then define and call a function to handle the event checkout.session.completed

      const sdk = ThirdwebSDK.fromPrivateKey(
        process.env.PRIVATE_KEY || "",
        "mumbai",
        {
          secretKey: process.env.SECRET_KEY, // Use secret key if using on the server, get it from dashboard settings
        }
      );

      const contract = await sdk.getContract(
        "0xE71eE93Ad57c8b355e1bCDFe435B05673d8B4930"
      );
      const tx = await contract.erc721.claimTo(
        body.data.object.metadata.address,
        1
      );
      console.log(tx);
      break;
    // ... handle other event types
    default:
      console.log(`Unhandled event type ${event.type}`);
  }

  return NextResponse.json({});
}

デプロイして試してみました。Polygonscanでも確認できているのでOKそうです。

Image

まとめ

以上今回はクレジットカード決済をNFT mintサイトに導入する3つの実装方法をご紹介しました。いずれの方法も本番環境で行うには発行者の事業体の審査が必要になるのでご留意ください。

日本の事業者さんでPiementというサービスが提供されているようです!こちらは試せていないのですが、LPを見る限り、NFTプロジェクト側の手数料は無料で導入でき、ユーザーに支払ってもらうビジネスモデルで運営されているようです。

弊社Pontechはweb3に関わる開発を得意とするテック企業です。サービス開発に関するご相談はこちらのフォームからお願いいたします。

また、受託開発案件に共に取り組むメンバーを募集しています!ご興味のある方はぜひお話させてください!

ponta

About ponta

2019年からEthereumを中心にDapp開発に従事。スキーとNBAとTWICEが好き。

Copyright © 2023 Pontech.Inc