ÖdemelerAbonelikler

Abonelik Planı

Abonelik planı, bir satıcının kullanıcıların kabul edebileceği faturalandırma koşullarını yayınlamasına olanak tanır. Bir kullanıcı abone olduktan sonra, satıcı veya onaylanmış bir tahsildar her faturalandırma döneminde plan tutarına kadar tahsilat yapabilir.

Bu kılavuz, tam akışı yapı taşları olarak göstermektedir. Satıcı bir plan oluşturur, abone bunu kabul eder ve satıcı veya tahsildar ortaya çıkan abonelik PDA'sından ödemeleri tahsil eder.

Kurulum

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

Plan Oluşturma

Satıcı, planın sahibidir. Plan PDA'sı, satıcı adresinden ve planId'den türetilir.

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,
});

Planı Güncelleme

Satıcı, oluşturulduktan sonra değiştirilebilir plan alanlarını güncelleyebilir. Mevcut aboneler kabul ettikleri koşulları korurken, yeni aboneler mevcut plan koşullarını kabul eder.

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();

Abone Ol

Abone, mevcut plan şartlarını kabul eder. Abonelik PDA'sı, plan PDA'sından ve abone adresinden türetilir.

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,
});

Ödeme Tahsil Et

Tüccar veya beyaz listeye alınmış bir çekici, tahsilatı imzalar. Plan bir hedef izin listesi kullandığında, alıcı token hesabının sahibi destinations içinde listelenmiş olmalıdır.

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();

İptal Et ve Geri Al

İptal etme, aboneliği sona eriyor olarak işaretler. Geri alma, iptal süresinin dolmasının ardından abonelik PDA'sını kapatır. Her iki işlemi de abone imzalar.

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();

Notlar

  • amount temel birimler cinsindendir. 6 ondalık basamaklı bir token için 5_000_000, 5 token anlamına gelir.
  • TypeScript SDK, bunları atladığınızda subscribe sırasında canlı plan koşullarını getirir.
  • Rust SubscribeBuilder, beklenen plan koşullarına ihtiyaç duyar. Önce plan hesabını getirin ve çözümleyin, ardından bu alanları SubscribeData üzerinden iletin.
  • Yalnızca satıcı veya pullers içinde listelenen bir cüzdan ödeme tahsil edebilir.
  • Abone kurulum, iptal ve geri alma işlemlerini imzalar. Satıcı veya onaylı çekici tahsilat işlemlerini imzalar.

Is this page helpful?

İçindekiler

Sayfayı Düzenle
© 2026 Solana Vakfı. Tüm hakları saklıdır.