Accept crypto payments on your website in 3 minutes.
- Getting Started
- Features
- Installation
- Basic Usage
- Configuration Options
- Framework Examples
- API Reference
- Payment Verification
- Webhooks
- Examples
- Support
Before you can start accepting crypto payments, you need to:
- Create a 100Pay account
- Obtain your API keys from the 100Pay Developers platform
- β Accept crypto payments on your website
- π° Withdraw to your crypto wallet or fiat balance
- π Create payment invoices
- π Create payment links
- πͺ Create your own coin on any supported network
- π Analytics to monitor your business
- π Swap crypto
- π± Buy/sell crypto
Add the 100Pay script to your HTML <head> or before the closing </body> tag:
<script src="https://js.100pay.co/"></script>Install the package using npm or yarn:
npm install @100pay-hq/checkoutyarn add @100pay-hq/checkoutThen import it in your JavaScript file:
// ES6 Import
import { shop100Pay } from "@100pay-hq/checkout";
// CommonJS Require
const { shop100Pay } = require("@100pay-hq/checkout");Create a payment form and a container for the 100Pay modal:
<form id="paymentForm">
<div class="form-group">
<label for="email">Email Address</label>
<input type="email" id="email-address" required />
</div>
<div class="form-group">
<label for="phone">Phone</label>
<input type="tel" id="phone" required />
</div>
<div class="form-group">
<label for="amount">Amount</label>
<input type="number" id="amount" required />
</div>
<div class="form-group">
<label for="first-name">First Name</label>
<input type="text" id="first-name" />
</div>
<div class="form-group">
<label for="last-name">Last Name</label>
<input type="text" id="last-name" />
</div>
<div class="form-submit">
<button type="submit">Pay with Crypto</button>
</div>
</form>
<!-- Container for the 100Pay checkout modal -->
<div id="show100Pay"></div>const paymentForm = document.getElementById('paymentForm');
paymentForm.addEventListener("submit", payWith100pay);
function payWith100pay(e) {
e.preventDefault();
const email = document.getElementById("email-address").value;
const phone = document.getElementById("phone").value;
const amount = document.getElementById("amount").value;
const firstName = document.getElementById("first-name").value;
const lastName = document.getElementById("last-name").value;
shop100Pay.setup({
ref_id: "" + Math.floor(Math.random() * 1000000000 + 1),
api_key: "TEST;PK;YOUR_API_KEY_HERE",
customer: {
user_id: "1", // optional
name: firstName + " " + lastName,
phone: phone,
email: email
},
billing: {
amount: amount,
currency: "USD",
description: "Test Payment",
country: "USA",
vat: 10, // optional
pricing_type: "fixed_price" // or "partial"
},
metadata: {
is_approved: "yes",
order_id: "OR2",
charge_ref: "REF"
// Add any custom fields you need
},
call_back_url: "https://yoursite.com/payment/callback",
onClose: () => {
console.log("Payment modal closed");
alert("You just closed the crypto payment modal.");
},
onPayment: (reference) => {
console.log("Payment reference:", reference);
alert(`New payment detected with reference ${reference}`);
/**
* β οΈ IMPORTANT: Never give value to users based on this callback alone!
* Always verify payments on your backend by calling the 100Pay API.
* See: https://100pay.co/blog/how-to-verify-crypto-payments-on-100-pay
*/
},
onError: (error) => {
console.error("Payment error:", error);
alert("Sorry, something went wrong. Please try again.");
}
});
}The shop100Pay.setup() method accepts two parameters: CHARGE_DATA and DISPLAY_OPTIONS (optional).
| Field | Type | Description |
|---|---|---|
api_key |
string |
Your 100Pay API key (get from dashboard) |
ref_id |
string |
Unique reference ID for this transaction |
customer |
object |
Customer information |
customer.name |
string |
Customer's full name |
customer.phone |
string |
Customer's phone number |
customer.email |
string |
Customer's email address |
billing |
object |
Billing information |
billing.amount |
number |
Payment amount |
billing.currency |
string |
Currency code (e.g., "USD", "EUR", "NGN") |
billing.country |
string |
Country code (e.g., "USA", "NG", "GB") |
billing.description |
string |
Description of the payment |
billing.pricing_type |
string |
Either "fixed_price" or "partial" |
metadata |
object |
Custom data to attach to the transaction |
call_back_url |
string |
URL to redirect users after payment |
onPayment |
function |
Callback when payment is detected |
onClose |
function |
Callback when modal is closed |
onError |
function |
Callback when an error occurs |
| Field | Type | Description |
|---|---|---|
customer.user_id |
string |
Your internal user ID |
billing.vat |
number |
VAT/tax percentage |
100Pay supports 90+ currencies including:
USD, EUR, GBP, NGN, CAD, AUD, JPY, CNY, INR, BRL, ZAR, KES, GHS, and many more.
See the Type Definitions section for the complete list.
100Pay supports payments from 240+ countries. Use ISO 3166-1 alpha-2 country codes (e.g., US, NG, GB) or USA for United States.
Customize the appearance of the payment modal:
shop100Pay.setup(
{
// ... charge data
},
{
maxWidth: "500px", // Maximum width of the modal (default: "400px")
maxHeight: "700px" // Maximum height of the modal (default: "unset")
}
);| Option | Type | Default | Description |
|---|---|---|---|
maxWidth |
string |
"400px" |
Maximum width of the payment modal |
maxHeight |
string |
"unset" |
Maximum height of the payment modal |
Example with custom display:
shop100Pay.setup({
api_key: "YOUR_API_KEY",
ref_id: "TXN_" + Date.now(),
// ... other charge data
}, {
maxWidth: "600px",
maxHeight: "800px"
});<template>
<div>
<form @submit.prevent="payWith100pay">
<div class="form-group">
<label for="email">Email Address</label>
<input type="email" v-model="form.email" required />
</div>
<div class="form-group">
<label for="phone">Phone</label>
<input type="tel" v-model="form.phone" required />
</div>
<div class="form-group">
<label for="amount">Amount</label>
<input type="number" v-model="form.amount" required />
</div>
<div class="form-group">
<label for="name">Full Name</label>
<input type="text" v-model="form.name" required />
</div>
<button type="submit">Pay with Crypto</button>
</form>
<!-- Container for 100Pay modal -->
<div id="show100Pay"></div>
</div>
</template>
<script>
import { shop100Pay } from "@100pay-hq/checkout";
export default {
name: "PaymentForm",
data() {
return {
form: {
name: "",
phone: "",
email: "",
amount: 100,
currency: "USD",
country: "USA"
}
};
},
methods: {
payWith100pay() {
shop100Pay.setup({
ref_id: "REF_" + Date.now(),
api_key: process.env.VUE_APP_100PAY_API_KEY,
customer: {
user_id: this.$auth?.user?.id, // optional
name: this.form.name,
phone: this.form.phone,
email: this.form.email
},
billing: {
amount: this.form.amount,
currency: this.form.currency,
description: "Product Purchase",
country: this.form.country,
pricing_type: "fixed_price"
},
metadata: {
order_id: "ORD_" + Date.now(),
source: "web"
},
call_back_url: `${window.location.origin}/payment/success`,
onClose: () => {
console.log("Payment modal closed");
},
onPayment: (reference) => {
console.log("Payment reference:", reference);
// Verify payment on your backend
this.verifyPayment(reference);
},
onError: (error) => {
console.error("Payment error:", error);
this.$toast.error("Payment failed. Please try again.");
}
}, {
maxWidth: "500px",
maxHeight: "750px"
});
},
async verifyPayment(reference) {
// Call your backend to verify the payment
try {
const response = await this.$axios.post("/api/verify-payment", {
reference
});
if (response.data.success) {
this.$router.push("/payment/success");
}
} catch (error) {
console.error("Verification error:", error);
}
}
}
};
</script>import React, { useState } from 'react';
import { shop100Pay } from '@100pay-hq/checkout';
function PaymentForm() {
const [formData, setFormData] = useState({
name: '',
email: '',
phone: '',
amount: 100
});
const handleChange = (e) => {
setFormData({
...formData,
[e.target.name]: e.target.value
});
};
const handleSubmit = (e) => {
e.preventDefault();
shop100Pay.setup({
ref_id: 'REF_' + Date.now(),
api_key: process.env.REACT_APP_100PAY_API_KEY,
customer: {
name: formData.name,
phone: formData.phone,
email: formData.email
},
billing: {
amount: formData.amount,
currency: 'USD',
description: 'Product Purchase',
country: 'USA',
pricing_type: 'fixed_price'
},
metadata: {
order_id: 'ORD_' + Date.now(),
source: 'web'
},
call_back_url: `${window.location.origin}/payment/success`,
onClose: () => {
console.log('Payment modal closed');
},
onPayment: (reference) => {
console.log('Payment reference:', reference);
verifyPayment(reference);
},
onError: (error) => {
console.error('Payment error:', error);
alert('Payment failed. Please try again.');
}
}, {
maxWidth: '500px',
maxHeight: '750px'
});
};
const verifyPayment = async (reference) => {
try {
const response = await fetch('/api/verify-payment', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ reference })
});
const data = await response.json();
if (data.success) {
window.location.href = '/payment/success';
}
} catch (error) {
console.error('Verification error:', error);
}
};
return (
<div>
<form onSubmit={handleSubmit}>
<div>
<label>Full Name</label>
<input
type="text"
name="name"
value={formData.name}
onChange={handleChange}
required
/>
</div>
<div>
<label>Email</label>
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
required
/>
</div>
<div>
<label>Phone</label>
<input
type="tel"
name="phone"
value={formData.phone}
onChange={handleChange}
required
/>
</div>
<div>
<label>Amount (USD)</label>
<input
type="number"
name="amount"
value={formData.amount}
onChange={handleChange}
required
/>
</div>
<button type="submit">Pay with Crypto</button>
</form>
{/* Container for 100Pay modal */}
<div id="show100Pay"></div>
</div>
);
}
export default PaymentForm;Initializes and displays the payment modal.
Parameters:
chargeData(CHARGE_DATA): Payment configuration objectdisplayOptions(DISPLAY_OPTIONS, optional): Modal display customization
Returns: void
Called when a payment is detected. Important: This is a client-side callback only. Always verify payments on your backend.
Parameters:
reference(string): The payment reference ID
Called when the payment modal is closed by the user.
Called when an error occurs during payment processing.
Parameters:
error(string | Error): Error message or Error object
interface CHARGE_DATA {
api_key: string;
ref_id: string;
customer: {
user_id?: string;
name: string;
phone: string;
email: string;
};
billing: {
amount: number;
currency: CURRENCIES;
country: COUNTRIES;
vat?: number;
pricing_type: "fixed_price" | "partial";
description: string;
};
metadata: Record<string, any>;
call_back_url: string;
onPayment: (reference: string) => void;
onClose: () => void;
onError: (error: string | Error) => void;
}
interface DISPLAY_OPTIONS {
maxWidth?: string;
maxHeight?: string;
}AED, ARS, AUD, BDT, BGN, BHD, BND, BOB, BRL, BWP, BYN, CAD, CHF, CLP, CNY, COP, CRC, CZK, DKK, DOP, DZD, EGP, EUR, FJD, GBP, GEL, GHS, HKD, HRK, HUF, IDR, ILS, INR, IQD, JOD, JPY, KES, KRW, KWD, KZT, LBP, LKR, LTL, MAD, MMK, MOP, MUR, MXN, MYR, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PEN, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, SAR, SEK, SGD, SVC, THB, TND, TRY, TWD, TZS, UAH, UGX, USD, UYU, UZS, VEF, VES, VND, XOF, ZAR
All ISO 3166-1 alpha-2 country codes are supported (240+ countries). Common examples: US, NG, GB, CA, AU, IN, CN, BR, ZA, KE, GH, etc. You can also use USA for United States.
Never trust the onPayment callback alone to confirm successful payments. This is a client-side callback that can be manipulated. Always verify payments on your backend.
After receiving the payment reference in the onPayment callback, make a GET request to the 100Pay verification endpoint from your backend:
// Backend (Node.js example)
const axios = require('axios');
async function verifyPayment(reference) {
try {
const response = await axios.get(
`https://api.100pay.co/api/v1/pay/charge/${reference}`,
{
headers: {
'api-key': process.env.PAY_100_API_KEY
}
}
);
const payment = response.data;
// Check payment status
if (payment.status === 'success' && payment.paid === true) {
// Payment confirmed - fulfill order
return { success: true, payment };
} else {
// Payment not confirmed
return { success: false, message: 'Payment not confirmed' };
}
} catch (error) {
console.error('Verification error:', error);
return { success: false, error };
}
}- User completes payment
onPaymentcallback fires with reference- Frontend sends reference to your backend
- Backend verifies with 100Pay API
- Backend fulfills order only if verified
- Backend sends confirmation to frontend
Learn More: How to Verify Crypto Payments on 100Pay
For real-time payment notifications, enable webhooks in your 100Pay dashboard. Webhooks notify your backend immediately when a payment is completed, failed, or refunded.
- Log in to your 100Pay Dashboard
- Navigate to Settings > Webhooks
- Add your webhook URL
- Select events to subscribe to
- Save and copy your webhook secret
// Backend webhook endpoint (Express.js example)
const crypto = require('crypto');
app.post('/webhooks/100pay', (req, res) => {
const signature = req.headers['x-100pay-signature'];
const payload = JSON.stringify(req.body);
// Verify webhook signature
const expectedSignature = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(payload)
.digest('hex');
if (signature !== expectedSignature) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Process webhook event
const event = req.body;
switch (event.type) {
case 'charge.success':
// Handle successful payment
handleSuccessfulPayment(event.data);
break;
case 'charge.failed':
// Handle failed payment
handleFailedPayment(event.data);
break;
// Handle other events
}
res.json({ received: true });
});Learn More: Subscribing to Webhooks on 100Pay
π View Live Demo
π View Source Code
- E-commerce Checkout - Accept crypto for product purchases
- Subscription Payments - Recurring crypto payments
- Donation Pages - Accept crypto donations
- Service Payments - Accept crypto for services
- Event Tickets - Sell tickets with crypto payments
- π 100Pay API Documentation
- π 100Pay Developer Docs
- π 100Pay Blog
- π Website
- π¬ Community Support
- π§ Email Support
MIT License - see LICENSE file for details
Contributions are welcome! Please feel free to submit a Pull Request.
Made with β€οΈ by 100Pay
