@rockwallet/stripe-sdk
v1.0.0
Published
MNEE Pay SDK — Stablecoin custom payment method for Stripe Elements
Readme
Stripe QR Payment SDK
A lightweight SDK that allows merchants to integrate custom payments via stablecoins directly into their Stripe checkout flow.
Currently supports USDC on the Base chain.
Features
- 💳 Custom payment method inside Stripe Payment Element
- 🔗 Stablecoin payments (USDC)
- 🌐 Works with existing Stripe checkout flows
Installation
Install the SDK:
npm install @rockwallet/stripe-sdkImport the SDK components:
import { MneePaymentModal, useMneePayment } from '@rockwallet/stripe-sdk'Integration Guide
1. Add Custom Payment Method to Stripe
Add a custom payment method inside the Stripe Payment Element options.
customPaymentMethods: [
{
id: 'your_cpmt_id',
options: {
type: 'static' as const,
subtitle: 'Pay with Stablecoins',
},
},
]2. Initialize the Mnee Payment Hook
Add the hook inside your payment form.
const mnee = useMneePayment({
integrationId: INTEGRATION_ID,
onSuccess: ({ transactionHash, amount }) => {
window.location.href = `${SUCCESS_URL}?tx=${transactionHash}&amount=${amount}`
},
})Parameters
| Property | Description |
| ----------------- | ------------------------------------------- |
| integrationId | Stripe Integration id provided by mnee pay |
| onSuccess | Callback triggered after successful payment |
3. Update the Submit Handler
Intercept the payment flow when the custom payment method is selected.
if (selectedPaymentMethod === CPMT_ID) {
mnee.openPayment({
amount: total, // product amount in cents
items: items, // product details
shippingInfo: shippingInfo // customer shipping info
})
return // modal handles payment flow
}4. Add the Payment Modal
Add the modal component at the end of your payment form.
<MneePaymentModal
isOpen={mnee.isOpen}
onClose={mnee.closePayment}
amount={mnee.amount}
items={mnee.items}
shippingInfo={mnee.shippingInfo}
integrationId={INTEGRATION_ID}
onSuccess={mnee.handleSuccess}
/>5. Webhook Integration
Merchants need to set up a webhook to record payments in Stripe after the user completes payment. The webhook also reports the Stripe payment record ID back to Mnee Pay.
Example Webhook (Next.js)
import { NextRequest, NextResponse } from 'next/server'
import Stripe from 'stripe'
import crypto from 'crypto'
const stripeKey = "your_stripe_secret_key"
const mneePayApiKey = "your_mnee_pay_api_key (provided by mnee pay)"
const cpm_id = "Your_cpmd_id"
const mneeBaseUrl = "mnee_pay backend url"
const stripe = new Stripe(stripeKey!, { apiVersion: '2026-01-28.clover' })
export async function POST(request: NextRequest) {
try {
const rawBody = await request.text()
const signature = request.headers.get('X-Webhook-Signature')
if (!signature) return NextResponse.json({ error: 'Missing signature' }, { status: 401 })
const expectedSignature = crypto.createHmac('sha256', mneePayApiKey!)
.update(rawBody)
.digest('hex')
if (signature !== expectedSignature) {
return NextResponse.json({ error: 'Invalid signature' }, { status: 401 })
}
const payload = JSON.parse(rawBody)
// Only handle successful payments
if (payload.event !== 'SUCCESS') return NextResponse.json({ received: true })
const { transactionId, stripeUserMetadata, payment, rwId, referenceId, order } = payload
// Find or create customer
const existingCustomers = await stripe.customers.search({ query: `email:'${stripeUserMetadata?.email}'` })
const customer = existingCustomers.data[0] ?? await stripe.customers.create({
name: `${stripeUserMetadata?.firstName ?? ''} ${stripeUserMetadata?.lastName ?? ''}`.trim(),
email: stripeUserMetadata?.email,
address: { country: stripeUserMetadata?.address?.country },
})
// Create or attach custom payment method
const existingPaymentMethods = await stripe.paymentMethods.list({ customer: customer.id, type: 'custom' })
const paymentMethod = existingPaymentMethods.data[0] ?? await stripe.paymentMethods.create({
type: 'custom',
custom: { type: cpm_id! },
}).then(pm => stripe.paymentMethods.attach(pm.id, { customer: customer.id }).then(() => pm))
// Record payment in Stripe
const paymentRecord = await stripe.paymentRecords.reportPayment({
amount_requested: { value: payment.amountUsdCents, currency: 'usd' },
payment_method_details: { payment_method: paymentMethod.id },
processor_details: { type: 'custom', custom: { payment_reference: payment.paymentTxHash } },
metadata: { rwId, referenceId, mneeTxId: payment.mneeTxId },
initiated_at: Math.floor(Date.now() / 1000),
outcome: 'guaranteed',
guaranteed: { guaranteed_at: Math.floor(Date.now() / 1000) },
customer_details: { customer: customer.id },
description: `MNEE Payment ${payment.paymentTxHash}`,
}, { idempotencyKey: `mnee_${transactionId}` })
// Report back to Mnee Pay
await fetch(`${mneeBaseUrl}/integrations/server/stripe/payment-record`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'x-api-key': mneePayApiKey! },
body: JSON.stringify({ transactionId, stripePaymentRecordId: paymentRecord.id }),
})
return NextResponse.json({ success: true })
} catch (error: any) {
return NextResponse.json({ error: error.message }, { status: 500 })
}
}Types
The SDK expects the following TypeScript types for items and shipping information.
Items
export interface Items {
product: {
id: string
name: string
price: number // in cents
}
quantity: number
}ShippingInfo
export interface ShippingInfo {
firstName?: string
lastName?: string
email?: string
address?: string
city?: string
state?: string
country?: string
zipCode?: string
}Payment Flow
- User selects Pay with Stablecoins
- SDK opens the QR payment modal
- User scans QR with wallet
- User pays using USDC on Base
- Transaction is verified
onSuccesscallback is triggered- Stripe payment record is created via webhook
- Stripe payment record ID is sent back to Mnee Pay
- User is redirected to success page
Environment Variables
CPMT_ID=your_custom_payment_method_id
INTEGRATION_ID=your_stripe_integration_idRequirements
- React
- Stripe Payment Element
- Node.js 18+
Supported Networks
| Network | Token | | ------- | ----- | | Base | USDC |
More networks coming soon.
License
MIT
