المدفوعاتالاشتراكات

خطة الاشتراك

تتيح خطة الاشتراك للتاجر نشر شروط الفوترة التي يمكن للمستخدمين قبولها. بعد اشتراك المستخدم، يمكن للتاجر أو السّاحب المُعتمد تحصيل ما يصل إلى مبلغ الخطة في كل فترة فوترة.

يعرض هذا الدليل التدفق الكامل كوحدات بناء. ينشئ التاجر خطة، ويقبلها المشترك، ثم يقوم التاجر أو السّاحب بتحصيل المدفوعات من حساب PDA الناتج عن الاشتراك.

التثبيت

pnpm add @solana/subscriptions @solana/kit @solana/kit-plugin-rpc @solana/kit-plugin-signer @solana-program/token

إنشاء خطة

يمتلك التاجر الخطة. يُشتق حساب PDA الخاص بالخطة من عنوان التاجر و planId.

import { address, createClient } from '@solana/kit';
import { solanaLocalRpc } from '@solana/kit-plugin-rpc';
import { signer } from '@solana/kit-plugin-signer';
import { findPlanPda, subscriptionsProgram } from '@solana/subscriptions';
const merchantClient = createClient()
.use(signer(merchantSigner))
.use(solanaLocalRpc({ rpcUrl: 'http://127.0.0.1:8899' }))
.use(subscriptionsProgram());
const planId = 1n;
const tokenMint = address('TOKEN_MINT_ADDRESS_HERE');
const amount = 5_000_000n;
const periodHours = 720n;
const metadataUri = 'https://example.com/plan.json';
const destinations = [merchantSigner.address];
const pullers = [address('PULLER_WALLET_ADDRESS_HERE')];
await merchantClient.subscriptions.instructions
.createPlan({
planId,
mint: tokenMint,
amount,
periodHours,
endTs: 0n,
destinations,
pullers,
metadataUri,
})
.sendTransaction();
const [planPda] = await findPlanPda({
owner: merchantSigner.address,
planId,
});

تحديث الخطة

يمكن للتاجر تحديث حقول الخطة القابلة للتعديل بعد الإنشاء. يحتفظ المشتركون الحاليون بالشروط التي قبلوها، بينما يقبل المشتركون الجدد شروط الخطة الحالية.

import { PlanStatus } from '@solana/subscriptions';
const updatedMetadataUri = 'https://example.com/updated-plan.json';
const updatedPullers = [address('NEW_PULLER_WALLET_ADDRESS_HERE')];
await merchantClient.subscriptions.instructions
.updatePlan({
owner: merchantSigner,
planPda,
status: PlanStatus.Active,
endTs: 0n,
pullers: updatedPullers,
metadataUri: updatedMetadataUri,
})
.sendTransaction();

الاشتراك

يوافق المشترك على شروط الخطة الحالية. يتم اشتقاق PDA للاشتراك من PDA الخطة وعنوان المشترك.

import { createClient } from '@solana/kit';
import { solanaLocalRpc } from '@solana/kit-plugin-rpc';
import { signer } from '@solana/kit-plugin-signer';
import { findAssociatedTokenPda, TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';
import {
fetchMaybeSubscriptionAuthority,
findSubscriptionAuthorityPda,
findSubscriptionDelegationPda,
subscriptionsProgram,
} from '@solana/subscriptions';
const subscriberClient = createClient()
.use(signer(subscriberSigner))
.use(solanaLocalRpc({ rpcUrl: 'http://127.0.0.1:8899' }))
.use(subscriptionsProgram());
const [subscriberAta] = await findAssociatedTokenPda({
mint: tokenMint,
owner: subscriberSigner.address,
tokenProgram: TOKEN_PROGRAM_ADDRESS,
});
const [subscriptionAuthorityPda] = await findSubscriptionAuthorityPda({
user: subscriberSigner.address,
tokenMint,
});
const subscriptionAuthority = await fetchMaybeSubscriptionAuthority(
subscriberClient.rpc,
subscriptionAuthorityPda,
);
if (!subscriptionAuthority.exists) {
await subscriberClient.subscriptions.instructions
.initSubscriptionAuthority({
tokenMint,
tokenProgram: TOKEN_PROGRAM_ADDRESS,
userAta: subscriberAta,
})
.sendTransaction();
}
await subscriberClient.subscriptions.instructions
.subscribe({
merchant: merchantSigner.address,
planId,
tokenMint,
})
.sendTransaction();
const [subscriptionPda] = await findSubscriptionDelegationPda({
planPda,
subscriber: subscriberSigner.address,
});

تحصيل الدفعة

يوقّع التاجر أو السّاحب المدرج في القائمة البيضاء على عملية التحصيل. عندما تستخدم الخطة قائمة وجهات مسموح بها، يجب أن يكون مالك حساب الرمز المستقبِل مدرجًا في destinations.

const receiverAta = address('MERCHANT_TOKEN_ACCOUNT_ADDRESS_HERE');
await merchantClient.subscriptions.instructions
.transferSubscription({
caller: merchantOrPullerSigner,
delegator: subscriberSigner.address,
tokenMint,
subscriptionPda,
planPda,
amount: 200_000n,
receiverAta,
tokenProgram: TOKEN_PROGRAM_ADDRESS,
})
.sendTransaction();

الإلغاء والإبطال

يضع الإلغاء علامة على الاشتراك بأنه منتهٍ. يؤدي الإبطال إلى إغلاق PDA للاشتراك بعد انقضاء فترة الإلغاء. يوقّع المشترك على كلتا المعاملتين.

await subscriberClient.subscriptions.instructions
.cancelSubscription({
subscriber: subscriberSigner,
planPda,
subscriptionPda,
})
.sendTransaction();
// Run this after the cancelled subscription's expiresAtTs has elapsed.
await subscriberClient.subscriptions.instructions
.revokeSubscription({
authority: subscriberSigner,
planPda,
subscriptionPda,
})
.sendTransaction();

ملاحظات

  • amount بالوحدات الأساسية. بالنسبة لرمز مميز بـ 6 خانات عشرية، يعني 5_000_000 أن هناك 5 رمزاً مميزاً.
  • يقوم SDK الخاص بـ TypeScript بجلب شروط الخطة المباشرة أثناء subscribe عندما تحذفها.
  • يحتاج SubscribeBuilder الخاص بـ Rust إلى شروط الخطة المتوقعة. قم بجلب حساب الخطة وفك تشفيره أولاً، ثم مرر تلك الحقول عبر SubscribeData.
  • يمكن للتاجر أو المحفظة المدرجة في pullers فقط تحصيل المدفوعات.
  • يوقع المشترك على معاملات الإعداد والإلغاء والإبطال. يوقع التاجر أو السَاحِب المعتمد على معاملات التحصيل.

Is this page helpful?

جدول المحتويات

تعديل الصفحة