
Research
npm Malware Targets Telegram Bot Developers with Persistent SSH Backdoors
Malicious npm packages posing as Telegram bot libraries install SSH backdoors and exfiltrate data from Linux developer machines.
@blocklet/payment-react
Advanced tools
A React component library for building payment flows, subscriptions, and donation systems in Blocklet applications. Seamlessly integrated with Blocklet's payment infrastructure.
npm install @blocklet/payment-react
import { PaymentProvider, CheckoutForm } from '@blocklet/payment-react';
function App() {
return (
<PaymentProvider session={session} connect={connectApi}>
<CheckoutForm
id="plink_xxx" // Payment Link ID
mode="inline" // Embed directly in your UI
showCheckoutSummary={true}
onChange={(state) => console.log('Checkout State:', state)}
/>
</PaymentProvider>
);
}
CheckoutForm
- Payment form for checkout sessions and payment linksCheckoutTable
- Pricing table displayCheckoutDonate
- Donation widgetOverdueInvoicePayment
- Handle overdue invoice paymentsFormInput
- Base form input componentPhoneInput
- Phone number input with validationAddressForm
- Complete address formStripeForm
- Stripe payment formCurrencySelector
- Currency selection dropdownCountrySelect
- Country selection dropdownStatus
- Status indicatorLivemode
- Test mode indicatorSwitch
- Toggle switchConfirmDialog
- Confirmation dialogAmount
- Amount display with formattingTruncatedText
- Text truncationLink
- Safe navigation link// Loading Button with state management
import { LoadingButton } from '@blocklet/payment-react';
function PaymentButton() {
const [loading, setLoading] = useState(false);
const handlePayment = async () => {
setLoading(true);
try {
await processPayment();
} finally {
setLoading(false);
}
};
return (
<LoadingButton
loading={loading}
onClick={handlePayment}
variant="contained"
color="primary"
>
Pay Now
</LoadingButton>
);
}
TxLink
- Transaction linkTxGas
- Gas fee displayPaymentBeneficiaries
- Payment beneficiaries listCustomerInvoiceList
- Invoice history listCustomerPaymentList
- Payment history listPaymentProvider
- Payment context providerDonateProvider
- Donation context providerPaymentThemeProvider
- Theme provideruseSubscription
- event socket callbackuseMobile
- Mobile detectionimport { api } from '@blocklet/payment-react';
// Basic usage
const response = await api.get('/api/payments');
const data = await api.post('/api/checkout', { amount: 100 });
// With query parameters
const results = await api.get('/api/invoices', {
params: { status: 'paid' }
});
// With request config
const config = {
headers: { 'Custom-Header': 'value' }
};
const response = await api.put('/api/subscription', data, config);
import { CachedRequest } from '@blocklet/payment-react';
// Create a cached request
const priceRequest = new CachedRequest(
'product-prices',
() => api.get('/api/prices'),
{
strategy: 'session', // 'session' | 'local' | 'memory'
ttl: 5 * 60 * 1000 // Cache for 5 minutes
}
);
// Use the cached request
async function fetchPrices() {
// Will use cache if available and not expired
const prices = await priceRequest.fetch();
// Force refresh cache
const freshPrices = await priceRequest.fetch(true);
return prices;
}
import { dayjs } from '@blocklet/payment-react';
// Format dates
const formatted = dayjs().format('YYYY-MM-DD');
// Parse timestamps
const date = dayjs(timestamp);
const unix = date.unix();
// Relative time
const relative = dayjs().from(date);
// use your own translator
import { createTranslator } from '@blocklet/payment-react';
const translator = createTranslator({
en: {
checkout: { title: 'Complete Payment' }
},
zh: {
checkout: { title: '完成支付' }
}
});
// use payment-react locales
import { translations as extraTranslations } from '@blocklet/payment-react';
import merge from 'lodash/merge';
import en from './en';
import zh from './zh';
export const translations = merge(
{
zh,
en,
},
extraTranslations
);
import { createLazyComponent } from '@blocklet/payment-react';
const LazyComponent = createLazyComponent(async () => {
const [{ Component }, { useHook }] = await Promise.all([
import('./Component'),
import('./hooks')
]);
globalThis.__DEPENDENCIES__ = { useHook };
return Component;
});
import {
DonateProvider,
CheckoutDonate,
PaymentProvider
} from '@blocklet/payment-react';
import { useEffect, useState } from 'react';
function DonationPage() {
const [session, setSession] = useState(null);
useEffect(() => {
// Get session from your auth system
const getSession = async () => {
const userSession = await fetchSession();
setSession(userSession);
};
getSession();
}, []);
return (
<PaymentProvider session={session} connect={connectApi}>
<DonateProvider
mountLocation="your-unique-donate-instance"
description="Help locate this donation instance"
defaultSettings={{
btnText: 'Like',
}}
>
<CheckoutDonate
settings={{
target: "post-123", // required, unique identifier for the donation instance
title: "Support Author", // required, title of the donation modal
description: "If you find this article helpful, feel free to buy me a coffee", // required, description of the donation
reference: "https://your-site.com/posts/123", // required, reference link of the donation
beneficiaries: [
{
address: "tip user did", // required, address of the beneficiary
share: "100", // required, percentage share
},
],
}}
/>
{/* Custom donation history display */}
<CheckoutDonate
mode="custom"
settings={{
target: "post-123", // required, unique identifier for the donation instance
title: "Support Author", // required, title of the donation modal
description: "If you find this article helpful, feel free to buy me a coffee", // required, description of the donation
reference: "https://your-site.com/posts/123", // required, reference link of the donation
beneficiaries: [
{
address: "tip user did", // required, address of the beneficiary
share: "100", // required, percentage share
},
],
}}
>
{(openDonate, totalAmount, supporters, loading, settings) => (
<div>
<h2>Our Supporters</h2>
{loading ? (
<CircularProgress />
) : (
<div>
<div>
Total Donations: {totalAmount} {supporters.currency?.symbol}
</div>
<div>
{supporters.supporters.map(supporter => (
<div key={supporter.id}>
<span>{supporter.customer?.name}</span>
<span>{supporter.amount_total} {supporters.currency?.symbol}</span>
</div>
))}
</div>
</div>
)}
</div>
)}
</CheckoutDonate>
</DonateProvider>
</PaymentProvider>
);
}
OverdueInvoicePayment
component
Display overdue invoices for a subscription, and support batch payment
Props:
subscriptionId
: [Optional] The subscription IDcustomerId
: [Optional] The customer ID or DIDonPaid
: [Optional] Callback function called after successful payment, receives (id, currencyId, type)
mode
: [Optional] Component mode, default
or custom
(default is default
)dialogProps
: [Optional] Dialog properties, default is { open: true }
detailLinkOptions
: [Optional] Detail link options, format: { enabled, onClick, title }
successToast
: [Optional] Whether to show success toast, default is true
children
: [Optional] Custom rendering function, used only when mode="custom"
Custom Mode:
children
function receives two parameters:
handlePay
: Function to start the payment processdata
: Payment data (includes subscription
, summary
, invoices
, subscriptionCount
, detailUrl
)import {
PaymentProvider,
OverdueInvoicePayment,
CustomerInvoiceList,
Amount
} from '@blocklet/payment-react';
function SubscriptionPage({ subscriptionId }) {
return (
<PaymentProvider session={session}>
{/* Handle subscription overdue payments */}
<OverdueInvoicePayment
subscriptionId={subscriptionId}
onPaid={() => {
// Refresh subscription status
refetchSubscription();
}}
/>
{/* Handle customer overdue payment */}
<OverdueInvoicePayment
customerId={session.user.did}
onPaid={() => {
// Refresh customer status
refetch();
}}
/>
{/* Custom Overdue Invoice Payment */}
<OverdueInvoicePayment
subscriptionId={subscriptionId}
onPaid={() => {
refetchSubscription();
}}
mode="custom"
>
{(handlePay, { subscription, summary, invoices }) => (
<Card>
<CardHeader title="Overdue Payments" />
<CardContent>
<Stack spacing={2}>
{Object.entries(summary).map(([currencyId, info]) => (
<div key={currencyId}>
<Typography>
Due Amount:
<Amount
amount={info.amount}
/>
{info.currency?.symbol}
</Typography>
<Button
onClick={() => handlePay(info)}
variant="contained"
>
Pay Now
</Button>
</div>
))}
</Stack>
</CardContent>
</Card>
)}
</OverdueInvoicePayment>
{/* Display invoice history */}
<CustomerInvoiceList
subscription_id={subscriptionId}
type="table"
include_staking
status="open,paid,uncollectible,void"
/>
</PaymentProvider>
);
}
// 1. Choose appropriate cache strategy
const shortLivedCache = new CachedRequest('key', fetchData, {
strategy: 'memory',
ttl: 60 * 1000 // 1 minute
});
const persistentCache = new CachedRequest('key', fetchData, {
strategy: 'local',
ttl: 24 * 60 * 60 * 1000 // 1 day
});
// 2. Clear cache when data changes
async function updateData() {
await api.post('/api/data', newData);
await cache.fetch(true); // Force refresh
}
// 3. Handle cache errors
try {
const data = await cache.fetch();
} catch (err) {
console.error('Cache error:', err);
// Fallback to fresh data
const fresh = await cache.fetch(true);
}
Since version 1.14.22, the component includes a built-in theme provider. If you need to modify the styles of internal components, pass the theme
property to override or inherit the external theme.
Option | Description |
---|---|
default | Wrapped with built-in PaymentThemeProvider |
inherit | Use the parent component's themeProvider |
PaymentThemeOptions | Override some styles of PaymentThemeProvider |
// 1. Use themeOptions
<CheckoutForm
id="plink_xxx"
onChange={console.info}
theme={{
components: {
MuiButton: {
styleOverrides: {
containedPrimary: {
backgroundColor: '#1DC1C7',
color: '#fff',
'&:hover': {
backgroundColor: 'rgb(20, 135, 139)',
},
},
},
},
},
}}
/>
// 2. Use theme sx
<CheckoutForm
id="plink_xxx"
showCheckoutSummary={false}
onChange={console.info}
theme={{
sx: {
'.cko-submit-button': {
backgroundColor: '#1DC1C7',
color: '#fff',
'&:hover': {
backgroundColor: 'rgb(20, 135, 139)',
},
},
},
}}
/>
import {
Status,
Livemode,
Switch,
Link,
Amount
} from '@blocklet/payment-react';
// Status indicator for payment states
<Status
label="active"
color="success"
size="small"
sx={{ margin: 1 }}
/>
// Test mode indicator
<Livemode />
// Custom switch button
<Switch
checked={true}
onChange={(checked) => console.log('Switched:', checked)}
/>
// Safe navigation link
<Link to="/demo" />
## License
Apache-2.0
FAQs
Reusable react components for payment kit v2
The npm package @blocklet/payment-react receives a total of 562 weekly downloads. As such, @blocklet/payment-react popularity was classified as not popular.
We found that @blocklet/payment-react demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Malicious npm packages posing as Telegram bot libraries install SSH backdoors and exfiltrate data from Linux developer machines.
Security News
pip, PDM, pip-audit, and the packaging library are already adding support for Python’s new lock file format.
Product
Socket's Go support is now generally available, bringing automatic scanning and deep code analysis to all users with Go projects.