پارو صندوقدار لاراول
- معرفی
- ارتقاء صندوقدار
- نصب و راه اندازی
- پیکربندی
- مفاهیم اصلی
- قیمت
- مشتریان
- اشتراک ها
- آزمایشات اشتراک
- رسیدگی به قلاب های وب پارویی
- شارژ تک
- رسیدها
- رسیدگی به پرداخت های ناموفق
- آزمایش کردن
معرفی
Laravel Cashier Paddle یک رابط رسا و روان برای خدمات صورتحساب اشتراک Paddle فراهم می کند. تقریباً تمام کدهای صورتحساب اشتراک دیگ بخار را که از آن میترسید مدیریت میکند. علاوه بر مدیریت اشتراک اولیه، صندوقدار میتواند این موارد را نیز انجام دهد: کوپنها، اشتراک تعویض، «مقدار» اشتراک، دورههای مهلت لغو، و موارد دیگر.
هنگام کار با Cashier، توصیه می کنیم به راهنمای کاربر Paddle و اسناد API نیز مراجعه کنید .
ارتقاء صندوقدار
هنگام ارتقاء به نسخه جدید Cashier، مهم است که راهنمای ارتقا را به دقت مرور کنید .
نصب و راه اندازی
ابتدا به بسته Cashier برای Paddle with Composer نیاز دارید:
composer require laravel/cashier-paddle
برای اطمینان از اینکه Cashier به درستی همه رویدادهای Paddle را مدیریت می کند، به یاد داشته باشید که کنترل وب هوک Cashier را تنظیم کنید .
مهاجرت های پایگاه داده
ارائه دهنده خدمات Cashier دایرکتوری مهاجرت پایگاه داده خود را ثبت می کند،
بنابراین به یاد داشته باشید که پس از نصب بسته، پایگاه داده خود را انتقال دهید.
مهاجرت صندوقدار یک
customers
جدول جدید ایجاد می کند.
علاوه بر این، یک
subscriptions
جدول جدید برای ذخیره تمام اشتراک های مشتری شما ایجاد می شود.
در نهایت، یک جدول جدید
receipts
برای ذخیره تمام اطلاعات رسید شما ایجاد می شود:
php artisan migrate
اگر نیاز به بازنویسی انتقالهایی دارید که با بسته Cashier ارسال میشوند،
میتوانید آنها را با استفاده از
vendor:publish
دستور Artisan منتشر کنید:
php artisan vendor:publish --tag="cashier-migrations"
اگر می خواهید از اجرای کامل مهاجرت صندوقدار جلوگیری کنید، می توانید از
برنامه
ignoreMigrations
ارائه شده توسط صندوقدار استفاده کنید.
register
به طور معمول، این روش باید در متد شما
فراخوانی شود
AppServiceProvider
:
use Laravel\Paddle\Cashier; Cashier::ignoreMigrations();
پیکربندی
مدل قابل پرداخت
قبل از استفاده از Cashier، باید این
Billable
ویژگی را به تعریف مدل کاربری خود اضافه کنید.
این ویژگی روشهای مختلفی را ارائه میکند تا به شما امکان میدهد کارهای
رایج صورتحساب را انجام دهید، مانند ایجاد اشتراک، اعمال کوپن و بهروزرسانی اطلاعات روش پرداخت:
use Laravel\Paddle\Billable; class User extends Authenticatable{ use Billable;}
اگر نهادهای قابل پرداختی دارید که کاربر نیستند، میتوانید این ویژگی را نیز به آن کلاسها اضافه کنید:
use Laravel\Paddle\Billable; class Team extends Model{ use Billable;}
کلیدهای API
در مرحله بعد، باید کلیدهای Paddle خود را در
.env
فایل خود پیکربندی کنید.
می توانید کلیدهای Paddle API خود را از کنترل پنل Paddle بازیابی کنید:
PADDLE_VENDOR_ID=your-paddle-vendor-idPADDLE_VENDOR_AUTH_CODE=your-paddle-vendor-auth-codePADDLE_PUBLIC_KEY="your-paddle-public-key"
Paddle JS
Paddle برای راهاندازی ویجت پرداخت Paddle به کتابخانه جاوا اسکریپت خود
متکی است.
می توانید کتابخانه جاوا اسکریپت را با قرار دادن
@paddleJS
دستورالعمل درست قبل از تگ بسته شدن طرح بندی برنامه خود بارگیری کنید
</head>
:
<head> ... @paddleJS</head>
پیکربندی ارز
واحد پول نقد پیش فرض دلار آمریکا (USD) است.
با تنظیم متغیر محیطی می توانید ارز پیش فرض را تغییر دهید
CASHIER_CURRENCY
:
CASHIER_CURRENCY=EUR
علاوه بر پیکربندی واحد پول Cashier، میتوانید محلی را نیز تعیین کنید که
هنگام قالببندی مقادیر پول برای نمایش در فاکتورها استفاده شود.
در داخل، Cashier از
کلاس
PHP
NumberFormatter
برای تنظیم محلی ارز استفاده می کند:
CASHIER_CURRENCY_LOCALE=nl_BE
به منظور استفاده از زبانهای محلی به غیر از
en
، مطمئن شوید کهext-intl
پسوند PHP روی سرور شما نصب و پیکربندی شده است.
مفاهیم اصلی
لینک های پرداخت
Paddle فاقد یک CRUD API گسترده برای انجام تغییرات حالت است. بنابراین، بیشتر تعاملات با Paddle از طریق ویجت پرداخت آن انجام می شود . قبل از اینکه بتوانیم ویجت پرداخت را نمایش دهیم، با استفاده از Cashier یک "پیوند پرداخت" ایجاد می کنیم:
$user = User::find(1); $payLink = $user->newSubscription('default', $premium = 34567) ->returnTo(route('home')) ->create(); return view('billing', ['payLink' => $payLink]);
صندوقدار شامل یک
paddle-button
جزء تیغه است.
ما ممکن است URL پیوند پرداخت را به عنوان یک "سرپا" به این مؤلفه ارسال
کنیم.
هنگامی که این دکمه کلیک می شود، ویجت پرداخت Paddle نمایش داده می شود:
<x-paddle-button :url="$payLink" class="px-8 py-4"> Subscribe</x-paddle-button>
بهطور پیشفرض، این دکمهای را با استایل استاندارد Paddle نمایش میدهد.
می توانید با افزودن
data-theme="none"
ویژگی به کامپوننت، تمام استایل های Paddle را حذف کنید:
<x-paddle-button :url="$payLink" class="px-8 py-4" data-theme="none"> Subscribe</x-paddle-button>
ویجت پرداخت Paddle ناهمزمان است. هنگامی که کاربر اشتراکی را در ویجت ایجاد یا بهروزرسانی کرد، Paddle وبقلابهای برنامه ما را ارسال میکند تا بتوانیم وضعیت اشتراک را در پایگاه داده خود بهدرستی بهروزرسانی کنیم. بنابراین، مهم است که به درستی وب هوک ها را برای تطبیق تغییرات وضعیت از Paddle تنظیم کنید .
پس از تغییر وضعیت اشتراک، تاخیر برای دریافت وب هوک مربوطه معمولاً حداقل است، اما باید با در نظر گرفتن اینکه اشتراک کاربر شما ممکن است بلافاصله پس از تکمیل پرداخت در دسترس نباشد، این را در برنامه خود در نظر بگیرید.
برای اطلاعات بیشتر، میتوانید مستندات Paddle API را در مورد ایجاد پیوند پرداخت مرور کنید .
پرداخت درون خطی
اگر نمیخواهید از ویجت پرداخت به سبک «همپوشانی» استفاده کنید، Paddle همچنین گزینهای برای نمایش درون خطی ویجت دارد. در حالی که این رویکرد به شما اجازه نمی دهد که هیچ یک از فیلدهای HTML پرداخت را تنظیم کنید، به شما امکان می دهد ویجت را در برنامه خود جاسازی کنید.
برای سهولت در شروع پرداخت درون خطی، Cashier شامل یک
paddle-checkout
جزء Blade است.
برای شروع، باید
یک پیوند پرداخت ایجاد کنید
و پیوند پرداخت را به ویژگی مؤلفه ارسال کنید
override
:
<x-paddle-checkout :override="$payLink" class="w-full" />
برای تنظیم ارتفاع مؤلفه پرداخت درون خطی، می توانید
height
ویژگی را به مؤلفه Blade منتقل کنید:
<x-paddle-checkout :override="$payLink" class="w-full" height="500" />
پرداخت درون خطی بدون پیوندهای پرداخت
همچنین، میتوانید به جای استفاده از پیوند پرداخت، ویجت را با گزینههای سفارشی سفارشی کنید:
$options = [ 'product' => $productId, 'title' => 'Product Title',]; <x-paddle-checkout :options="$options" class="w-full" />
لطفاً برای جزئیات بیشتر در مورد گزینه های موجود، به راهنمای Paddle در Inline Checkout و همچنین مرجع پارامتر آنها مراجعه کنید.
اگر میخواهید
passthrough
هنگام تعیین گزینههای سفارشی نیز از این گزینه استفاده کنید، باید یک آرایه کلید/مقدار ارائه کنید زیرا Cashier به طور خودکار تبدیل آرایه به رشته JSON را انجام میدهد. علاوه بر این،customer_id
گزینه عبور برای استفاده داخلی صندوقدار رزرو شده است.
شناسایی کاربر
بر خلاف Stripe، کاربران Paddle در کل Paddle منحصر به فرد هستند، نه منحصر
به فرد در هر حساب Paddle.
به همین دلیل، API های Paddle در حال حاضر روشی برای به روز رسانی جزئیات
کاربر مانند آدرس ایمیل آنها ارائه نمی دهند.
هنگام ایجاد پیوندهای پرداخت، Paddle کاربران را با استفاده از
customer_email
پارامتر شناسایی می کند.
هنگام ایجاد اشتراک، Paddle سعی می کند ایمیل ارائه شده توسط کاربر را با یک
کاربر موجود Paddle مطابقت دهد.
با توجه به این رفتار، نکات مهمی وجود دارد که باید هنگام استفاده از صندوقدار و پارو در نظر داشته باشید. ابتدا، باید توجه داشته باشید که حتی اگر اشتراکها در Cashier به یک کاربر برنامه مرتبط هستند، میتوانند به کاربران مختلفی در سیستمهای داخلی Paddle مرتبط باشند . ثانیاً، هر اشتراک اطلاعات روش پرداخت متصل خود را دارد و همچنین میتواند آدرسهای ایمیل متفاوتی در سیستمهای داخلی Paddle داشته باشد (بسته به اینکه در هنگام ایجاد اشتراک کدام ایمیل به کاربر اختصاص داده شده است).
بنابراین، هنگام نمایش اشتراکها، همیشه باید به کاربر اطلاع دهید که کدام
آدرس ایمیل یا اطلاعات روش پرداخت به ازای هر اشتراک به اشتراک متصل است.
بازیابی این اطلاعات را می توان با روش های زیر در
Subscription
مدل انجام داد:
$subscription = $user->subscription('default'); $customerEmailAddress = $subscription->paddleEmail();$paymentMethod = $subscription->paymentMethod();$cardBrand = $subscription->cardBrand();$cardLastFour = $subscription->cardLastFour();$cardExpirationDate = $subscription->cardExpirationDate();
در حال حاضر هیچ راهی برای تغییر آدرس ایمیل کاربر از طریق Paddle API وجود
ندارد.
هنگامی که کاربر می خواهد آدرس ایمیل خود را در Paddle به روز کند، تنها راه
برای انجام این کار تماس با پشتیبانی مشتری Paddle است.
هنگام برقراری ارتباط با Paddle، آنها باید
paddleEmail
مقدار اشتراک را ارائه دهند تا به Paddle در به روز رسانی کاربر صحیح کمک
کند.
قیمت
Paddle به شما امکان میدهد قیمتها را برای هر ارز سفارشی کنید و اساساً به
شما امکان میدهد قیمتهای مختلف را برای کشورهای مختلف پیکربندی کنید.
Cashier Paddle به شما امکان می دهد تمام قیمت های یک محصول معین را با
استفاده از
productPrices
روش زیر بازیابی کنید:
use Laravel\Paddle\Cashier; // Retrieve prices for two products...$prices = Cashier::productPrices([123, 456]);
ارز بر اساس آدرس IP درخواست تعیین می شود. با این حال، میتوانید به صورت اختیاری کشور خاصی را برای بازیابی قیمتها ارائه دهید:
use Laravel\Paddle\Cashier; // Retrieve prices for two products...$prices = Cashier::productPrices([123, 456], ['customer_country' => 'BE']);
پس از بازیابی قیمت ها، می توانید آنها را هر طور که می خواهید نمایش دهید:
<ul> @foreach ($prices as $price) <li>{{ $price->product_title }} - {{ $price->price()->gross() }}</li> @endforeach</ul>
همچنین میتوانید قیمت خالص (بدون مالیات) را نمایش دهید و مبلغ مالیات را جداگانه نمایش دهید:
<ul> @foreach ($prices as $price) <li>{{ $price->product_title }} - {{ $price->price()->net() }} (+ {{ $price->price()->tax() }} tax)</li> @endforeach</ul>
اگر قیمتهای طرحهای اشتراک را بازیابی کردهاید، میتوانید قیمت اولیه و تکرارشونده آنها را جداگانه نمایش دهید:
<ul> @foreach ($prices as $price) <li>{{ $price->product_title }} - Initial: {{ $price->initialPrice()->gross() }} - Recurring: {{ $price->recurringPrice()->gross() }}</li> @endforeach</ul>
برای اطلاعات بیشتر، اسناد API Paddle را در مورد قیمت ها بررسی کنید .
مشتریان
اگر کاربری قبلاً مشتری است و میخواهید قیمتهایی را که برای آن مشتری اعمال میشود نمایش دهید، میتوانید این کار را با بازیابی قیمتها مستقیماً از نمونه مشتری انجام دهید:
use App\User; // Retrieve prices for two products...$prices = User::find(1)->productPrices([123, 456]);
paddleCountry
در داخل، Cashier از روش
کاربر
برای بازیابی قیمت ها به واحد پول خود استفاده می کند.
بنابراین، برای مثال، کاربری که در ایالات متحده زندگی می کند قیمت ها را به
دلار آمریکا می بیند در حالی که کاربر در بلژیک قیمت ها را به یورو می بیند.
اگر ارز منطبقی پیدا نشد، واحد پول پیشفرض محصول استفاده میشود.
میتوانید تمام قیمتهای یک محصول یا طرح اشتراک را در کنترل پنل Paddle
سفارشی کنید.
کوپن
همچنین میتوانید پس از کاهش کوپن، قیمتها را نمایش دهید.
هنگام فراخوانی
productPrices
متد، کوپن ها ممکن است به صورت رشته ای با کاما ارسال شوند:
use Laravel\Paddle\Cashier; $prices = Cashier::productPrices([123, 456], ['coupons' => 'SUMMERSALE,20PERCENTOFF']);
سپس قیمت های محاسبه شده را با استفاده از
price
روش زیر نمایش دهید:
<ul> @foreach ($prices as $price) <li>{{ $price->product_title }} - {{ $price->price()->gross() }}</li> @endforeach</ul>
می توانید قیمت های اصلی فهرست شده (بدون تخفیف کوپن) را با استفاده از
listPrice
روش زیر نمایش دهید:
<ul> @foreach ($prices as $price) <li>{{ $price->product_title }} - {{ $price->listPrice()->gross() }}</li> @endforeach</ul>
هنگام استفاده از API قیمتها، Paddle فقط اجازه میدهد کوپنها را برای محصولات یکبار خرید و نه برای طرحهای اشتراک اعمال کنید.
مشتریان
پیش فرض های مشتری
Cashier به شما امکان می دهد هنگام ایجاد پیوندهای پرداخت، چند پیش فرض مفید برای مشتری خود تنظیم کنید. تنظیم این پیشفرضها به شما این امکان را میدهد که آدرس ایمیل، کشور و کدپستی مشتری را از قبل پر کنید تا بتوانند فوراً به بخش پرداخت ویجت پرداخت وارد شوند. میتوانید این پیشفرضها را با لغو روشهای زیر در کاربر قابل پرداخت خود تنظیم کنید:
/** * Get the customer's email address to associate with Paddle. * * @return string|null */public function paddleEmail(){ return $this->email;} /** * Get the customer's country to associate with Paddle. * * This needs to be a 2 letter code. See the link below for supported countries. * * @return string|null * @link https://developer.paddle.com/reference/platform-parameters/supported-countries */public function paddleCountry(){ //} /** * Get the customer's postcode to associate with Paddle. * * See the link below for countries which require this. * * @return string|null * @link https://developer.paddle.com/reference/platform-parameters/supported-countries#countries-requiring-postcode */public function paddlePostcode(){ //}
این پیشفرضها برای هر اقدامی در Cashier که پیوند پرداخت ایجاد میکند استفاده میشود .
اشتراک ها
ایجاد اشتراک
برای ایجاد اشتراک، ابتدا نمونه ای از مدل قابل پرداخت خود را بازیابی کنید
که معمولاً نمونه ای از
App\User
.
هنگامی که نمونه مدل را بازیابی کردید، می توانید از این
newSubscription
روش برای ایجاد پیوند پرداخت اشتراک مدل استفاده کنید:
$user = User::find(1); $payLink = $user->newSubscription('default', $premium = 12345) ->returnTo(route('home')) ->create(); return view('billing', ['payLink' => $payLink]);
اولین آرگومان ارسال شده به
newSubscription
متد باید نام اشتراک باشد.
اگر برنامه شما فقط یک اشتراک ارائه می دهد، می توانید با این
default
یا تماس بگیرید
primary
.
آرگومان دوم، طرح خاصی است که کاربر در حال اشتراک در آن است.
این مقدار باید با شناسه طرح در Paddle مطابقت داشته باشد.
این
returnTo
روش یک URL را میپذیرد که کاربر شما پس از تکمیل موفقیتآمیز پرداخت، به آن
هدایت میشود.
این
create
روش یک پیوند پرداخت ایجاد می کند که می توانید از آن برای ایجاد دکمه
پرداخت استفاده کنید.
دکمه پرداخت را می توان با استفاده از
paddle-button
جزء Blade که با Cashier Paddle ارسال می شود ایجاد کرد:
<x-paddle-button :url="$payLink" class="px-8 py-4"> Subscribe</x-paddle-button>
پس از اینکه کاربر پرداخت خود را به پایان رساند، یک
subscription_created
وب هوک از Paddle ارسال می شود.
صندوقدار این وب هوک را دریافت می کند و اشتراک را برای مشتری شما تنظیم می
کند.
برای اطمینان از اینکه همه وبکهکها به درستی دریافت شده و توسط برنامه شما
مدیریت میشوند، مطمئن شوید که
مدیریت وبهوک را بهدرستی تنظیم کردهاید
.
توضیحات بیشتر
اگر میخواهید جزئیات اضافی مشتری یا اشتراک را مشخص کنید، میتوانید این
کار را با ارسال آنها به عنوان یک آرایه کلید/مقدار به
create
روش انجام دهید:
$payLink = $user->newSubscription('default', $monthly = 12345) ->returnTo(route('home')) ->create([ 'vat_number' => $vatNumber, ]);
برای کسب اطلاعات بیشتر در مورد فیلدهای اضافی پشتیبانی شده توسط Paddle، مستندات Paddle را در مورد ایجاد پیوندهای پرداخت بررسی کنید .
کوپن
اگر می خواهید هنگام ایجاد اشتراک کوپن اعمال کنید، می توانید از
withCoupon
روش زیر استفاده کنید:
$payLink = $user->newSubscription('default', $monthly = 12345) ->returnTo(route('home')) ->withCoupon('code') ->create();
فراداده
همچنین میتوانید آرایهای از متادیتا را با استفاده از
withMetadata
روش زیر ارسال کنید:
$payLink = $user->newSubscription('default', $monthly = 12345) ->returnTo(route('home')) ->withMetadata(['key' => 'value']) ->create();
هنگام ارائه ابرداده، لطفاً از استفاده
subscription_name
به عنوان کلید فراداده خودداری کنید. این کلید برای استفاده داخلی توسط صندوقدار رزرو شده است.
بررسی وضعیت اشتراک
هنگامی که کاربر در برنامه شما مشترک شد، می توانید وضعیت اشتراک او را با
استفاده از روش های مختلف مناسب بررسی کنید.
ابتدا،
اگر کاربر اشتراک فعال داشته باشد،
subscribed
روش برمی گردد ، حتی اگر اشتراک در حال حاضر در دوره آزمایشی خود باشد:
true
if ($user->subscribed('default')) { //}
این
subscribed
روش همچنین یک کاندیدای عالی برای
میانافزار مسیر
است که به شما امکان میدهد دسترسی به مسیرها و کنترلکنندهها را بر اساس
وضعیت اشتراک کاربر فیلتر کنید:
public function handle($request, Closure $next){ if ($request->user() && ! $request->user()->subscribed('default')) { // This user is not a paying customer... return redirect('billing'); } return $next($request);}
اگر می خواهید تعیین کنید که آیا کاربر هنوز در دوره آزمایشی خود است، می
توانید از این
onTrial
روش استفاده کنید.
این روش می تواند برای نمایش یک هشدار به کاربر مبنی بر اینکه هنوز در دوره
آزمایشی خود است مفید باشد:
if ($user->subscription('default')->onTrial()) { //}
این
subscribedToPlan
روش ممکن است برای تعیین اینکه آیا کاربر در یک طرح معین بر اساس شناسه طرح
Paddle معین مشترک شده است یا خیر استفاده شود.
در این مثال، تعیین می کنیم که آیا اشتراک کاربر
default
به طور فعال در طرح ماهانه مشترک است یا خیر:
if ($user->subscribedToPlan($monthly = 12345, 'default')) { //}
با ارسال یک آرایه به
subscribedToPlan
روش، می توانید تعیین کنید که آیا اشتراک کاربر
default
به طور فعال در برنامه ماهانه یا سالانه مشترک است:
if ($user->subscribedToPlan([$monthly = 12345, $yearly = 54321], 'default')) { //}
این
recurring
روش ممکن است برای تعیین اینکه آیا کاربر در حال حاضر مشترک است و دیگر در
دوره آزمایشی خود نیست استفاده می شود:
if ($user->subscription('default')->recurring()) { //}
وضعیت اشتراک لغو شده
برای تعیین اینکه آیا کاربر زمانی مشترک فعال بوده است، اما اشتراک خود را
لغو کرده است، می توانید از
cancelled
روش زیر استفاده کنید:
if ($user->subscription('default')->cancelled()) { //}
همچنین میتوانید تعیین کنید که آیا یک کاربر اشتراک خود را لغو کرده است یا
خیر، اما هنوز در «دوره مهلت» خود است تا زمانی که اشتراک به طور کامل منقضی شود.
به عنوان مثال، اگر کاربری اشتراکی را در تاریخ 5 مارس لغو کند که در ابتدا
قرار بود در 10 مارس منقضی شود، کاربر تا 10 مارس در "مهلت مهلت" خود است.
توجه داشته باشید که
subscribed
روش همچنان
true
در این مدت باز می گردد:
if ($user->subscription('default')->onGracePeriod()) { //}
برای تعیین اینکه آیا کاربر اشتراک خود را لغو کرده است و دیگر در "دوره
مهلت" خود نیست، می توانید از
ended
روش زیر استفاده کنید:
if ($user->subscription('default')->ended()) { //}
محدوده های اشتراک
اکثر حالت های اشتراک نیز به عنوان محدوده پرس و جو در دسترس هستند، به طوری که می توانید به راحتی پایگاه داده خود را برای اشتراک هایی که در یک وضعیت خاص هستند پرس و جو کنید:
// Get all active subscriptions...$subscriptions = Subscription::query()->active()->get(); // Get all of the cancelled subscriptions for a user...$subscriptions = $user->subscriptions()->cancelled()->get();
لیست کاملی از دامنه های موجود در زیر موجود است:
Subscription::query()->active();Subscription::query()->onTrial();Subscription::query()->notOnTrial();Subscription::query()->pastDue();Subscription::query()->recurring();Subscription::query()->ended();Subscription::query()->paused();Subscription::query()->notPaused();Subscription::query()->onPausedGracePeriod();Subscription::query()->notOnPausedGracePeriod();Subscription::query()->cancelled();Subscription::query()->notCancelled();Subscription::query()->onGracePeriod();Subscription::query()->notOnGracePeriod();
وضعیت سررسید گذشته
اگر پرداخت برای اشتراک ناموفق باشد، به عنوان علامت گذاری می شود
past_due
.
هنگامی که اشتراک شما در این وضعیت باشد، تا زمانی که مشتری اطلاعات پرداخت
خود را به روز نکند، فعال نخواهد بود.
می توانید با استفاده از
pastDue
روش موجود در نمونه اشتراک تعیین کنید که آیا یک اشتراک سررسید شده است:
if ($user->subscription('default')->pastDue()) { //}
هنگامی که سررسید اشتراک به پایان می رسد، باید به کاربر دستور دهید که اطلاعات پرداخت خود را به روز کند . میتوانید نحوه رسیدگی به اشتراکهای سررسید شده را در تنظیمات اشتراک Paddle پیکربندی کنید .
اگر میخواهید اشتراکها همچنان فعال در نظر گرفته شوند
past_due
، میتوانید از
keepPastDueSubscriptionsActive
روش ارائه شده توسط Cashier استفاده کنید.
register
به طور معمول، این روش باید در متد شما
فراخوانی شود
AppServiceProvider
:
use Laravel\Paddle\Cashier; /** * Register any application services. * * @return void */public function register(){ Cashier::keepPastDueSubscriptionsActive();}
هنگامی که اشتراکی در
past_due
وضعیتی است، تا زمانی که اطلاعات پرداخت به روز نشده باشد، نمی توان آن را تغییر داد. بنابراین، متدهایswap
وupdateQuantity
زمانی که اشتراک در یک وضعیت باشد، استثنا ایجاد میکندpast_due
.
هزینه های تک اشتراک
هزینه های تک اشتراک به شما این امکان را می دهد که مشترکین را با یک بار هزینه در کنار اشتراک خود شارژ کنید:
$response = $user->subscription('default')->charge(12.99, 'Support Add-on');
برخلاف هزینه های تکی ، این روش بلافاصله از روش پرداخت ذخیره شده مشتری برای اشتراک هزینه دریافت می کند. مبلغ شارژ همیشه به واحد پولی است که اشتراک در حال حاضر روی آن تنظیم شده است.
به روز رسانی اطلاعات پرداخت
Paddle همیشه یک روش پرداخت را برای هر اشتراک ذخیره می کند.
اگر میخواهید روش پرداخت پیشفرض برای اشتراک را بهروزرسانی کنید، ابتدا
باید با استفاده از روش موجود
updateUrl
در مدل اشتراک، یک «URL بهروزرسانی» اشتراک ایجاد کنید:
$user = App\User::find(1); $updateUrl = $user->subscription('default')->updateUrl();
سپس، میتوانید از URL تولید شده در ترکیب با
paddle-button
مؤلفه Blade ارائه شده توسط Cashier استفاده کنید تا به کاربر اجازه دهید
ویجت Paddle را راهاندازی کند و اطلاعات پرداخت خود را بهروزرسانی کند:
<x-paddle-button :url="$updateUrl" class="px-8 py-4"> Update Card</x-paddle-button>
هنگامی که کاربر بهروزرسانی اطلاعات خود را به پایان رساند، یک
subscription_updated
وب هوک توسط Paddle ارسال میشود و جزئیات اشتراک در پایگاه داده برنامه شما
بهروزرسانی میشود.
تغییر برنامه ها
پس از اینکه کاربر در برنامه شما مشترک شد، ممکن است گهگاه بخواهد به یک طرح
اشتراک جدید تغییر کند.
برای تعویض کاربر با یک اشتراک جدید، باید شناسه Paddle plan را به
swap
روش اشتراک ارسال کنید:
$user = App\User::find(1); $user->subscription('default')->swap($premium = 34567);
اگر کاربر در حالت آزمایشی باشد، دوره آزمایشی حفظ خواهد شد. همچنین، اگر "کمیتی" برای اشتراک وجود داشته باشد، آن مقدار نیز حفظ خواهد شد.
اگر میخواهید برنامهها را عوض کنید و هر دوره آزمایشی را که کاربر در حال
حاضر در آن است لغو کنید، میتوانید از
skipTrial
روش زیر استفاده کنید:
$user->subscription('default') ->skipTrial() ->swap($premium = 34567);
اگر میخواهید به جای اینکه برای چرخه صورتحساب بعدی کاربر منتظر بمانید،
برنامهها را مبادله کنید و فوراً فاکتور بگیرید، میتوانید از
swapAndInvoice
روش زیر استفاده کنید:
$user = App\User::find(1); $user->subscription('default')->swapAndInvoice($premium = 34567);
تناسب
بهطور پیشفرض، Paddle هنگام جابجایی بین طرحها، هزینهها را نسبت میدهد.
این
noProrate
روش ممکن است برای بهروزرسانی اشتراکها بدون نسبت هزینهها استفاده شود:
$user->subscription('default')->noProrate()->swap($premium = 34567);
مقدار اشتراک
گاهی اوقات اشتراک ها تحت تأثیر "کمیت" قرار می گیرند.
به عنوان مثال، برنامه شما ممکن است 10 دلار در ماه
برای هر کاربر
در یک حساب دریافت کند.
برای افزایش یا کاهش آسان تعداد اشتراک خود، از روش های
incrementQuantity
و استفاده کنید
decrementQuantity
:
$user = User::find(1); $user->subscription('default')->incrementQuantity(); // Add five to the subscription's current quantity...$user->subscription('default')->incrementQuantity(5); $user->subscription('default')->decrementQuantity(); // Subtract five to the subscription's current quantity...$user->subscription('default')->decrementQuantity(5);
از طرف دیگر، میتوانید مقدار خاصی را با استفاده از
updateQuantity
روش زیر تنظیم کنید:
$user->subscription('default')->updateQuantity(10);
این
noProrate
روش ممکن است برای به روز رسانی مقدار اشتراک بدون نسبت هزینه ها استفاده
شود:
$user->subscription('default')->noProrate()->updateQuantity(10);
توقف اشتراک ها
برای توقف موقت اشتراک،
pause
روش موجود در اشتراک کاربر را فراخوانی کنید:
$user->subscription('default')->pause();
هنگامی که یک اشتراک متوقف می شود، صندوقدار به طور خودکار
paused_from
ستون را در پایگاه داده شما تنظیم می کند.
از این ستون برای دانستن زمان
paused
شروع بازگشت متد استفاده می شود
true
.
به عنوان مثال، اگر مشتری اشتراک خود را در اول مارس متوقف کند، اما قرار
نبود اشتراک تا 5 مارس تکرار شود، این روش
تا 5 مارس
paused
ادامه خواهد داشت .
false
onPausedGracePeriod
با استفاده از این روش
میتوانید تعیین کنید که آیا کاربر اشتراک خود را موقتاً متوقف کرده است اما
هنوز در "دوره مهلت" خود است :
if ($user->subscription('default')->onPausedGracePeriod()) { //}
برای از سرگیری یک اشتراک متوقف شده، می توانید
unpause
روش موجود در اشتراک کاربر را فراخوانی کنید:
$user->subscription('default')->unpause();
اشتراک در زمانی که موقتاً متوقف شده است قابل تغییر نیست. اگر میخواهید به طرح دیگری مبادله کنید یا مقادیر بهروزرسانی کنید، ابتدا باید اشتراک را از سر بگیرید.
لغو اشتراک ها
برای لغو اشتراک، با
cancel
روش موجود در اشتراک کاربر تماس بگیرید:
$user->subscription('default')->cancel();
هنگامی که یک اشتراک لغو می شود، صندوقدار به طور خودکار
ends_at
ستون را در پایگاه داده شما تنظیم می کند.
از این ستون برای دانستن زمان
subscribed
شروع بازگشت متد استفاده می شود
false
.
به عنوان مثال، اگر مشتری در تاریخ 1 مارس اشتراک خود را لغو کند، اما قرار
نبود اشتراک تا 5 مارس پایان یابد، این روش
تا 5 مارس
subscribed
ادامه خواهد داشت .
true
onGracePeriod
با استفاده از این روش
میتوانید تعیین کنید که آیا کاربر اشتراک خود را لغو کرده است اما هنوز در
«دوره مهلت» خود است :
if ($user->subscription('default')->onGracePeriod()) { //}
اگر میخواهید اشتراک را فوراً لغو کنید، میتوانید از
cancelNow
روش موجود در اشتراک کاربر تماس بگیرید:
$user->subscription('default')->cancelNow();
اشتراک های Paddle پس از لغو قابل از سرگیری نمی باشد. اگر مشتری شما بخواهد اشتراک خود را از سر بگیرد، باید مشترک اشتراک جدیدی شود.
آزمایشات اشتراک
با روش پرداخت از قبل
هنگام آزمایش و جمعآوری جزئیات روش پرداخت، Paddle از هرگونه تغییر اشتراک مانند تعویض طرحها یا بهروزرسانی مقادیر جلوگیری میکند. اگر میخواهید به مشتری اجازه دهید برنامههای خود را در طول دوره آزمایشی مبادله کند، اشتراک باید لغو و دوباره ایجاد شود.
اگر میخواهید در حین جمعآوری اطلاعات روش پرداخت از قبل، دورههای آزمایشی
را به مشتریان خود ارائه دهید،
trialDays
هنگام ایجاد پیوندهای پرداخت اشتراک خود باید از این روش استفاده کنید:
$user = User::find(1); $payLink = $user->newSubscription('default', $monthly = 12345) ->returnTo(route('home')) ->trialDays(10) ->create(); return view('billing', ['payLink' => $payLink]);
این روش تاریخ پایان دوره آزمایشی را در سابقه اشتراک در پایگاه داده تنظیم میکند، و همچنین به Paddle دستور میدهد تا پس از این تاریخ، صورتحساب مشتری را شروع نکند.
اگر اشتراک مشتری قبل از تاریخ پایان دوره آزمایشی لغو نشود، به محض انقضای دوره آزمایشی هزینه از آنها کسر می شود، بنابراین باید حتماً کاربران خود را از تاریخ پایان دوره آزمایشی مطلع کنید.
onTrial
شما می توانید با استفاده از روش نمونه کاربر یا
onTrial
روش نمونه اشتراک
تعیین کنید که آیا کاربر در دوره آزمایشی خود است .
دو مثال زیر رفتار یکسانی دارند:
if ($user->onTrial('default')) { //} if ($user->subscription('default')->onTrial()) { //}
تعریف روزهای آزمایشی در دست و پا زدن / صندوقدار
میتوانید تعیین کنید که برنامهتان چند روز آزمایشی در داشبورد Paddle
دریافت میکند یا همیشه آنها را بهصراحت با استفاده از Cashier پاس کنید.
اگر تصمیم میگیرید روزهای آزمایشی طرح خود را در Paddle تعریف کنید، باید
توجه داشته باشید که اشتراکهای جدید، از جمله اشتراکهای جدید برای مشتری که در گذشته اشتراک داشتهاند، همیشه
یک دوره آزمایشی دریافت میکنند، مگر اینکه صریحاً با روش تماس بگیرید
trialDays(0)
.
بدون روش پرداخت از قبل
اگر میخواهید دورههای آزمایشی را بدون جمعآوری اطلاعات روش پرداخت کاربر
از قبل ارائه دهید، میتوانید ستون
trial_ends_at
روی سابقه مشتری پیوست شده به کاربر خود را به تاریخ پایان آزمایشی مورد نظر
خود تنظیم کنید.
این معمولاً در هنگام ثبت نام کاربر انجام می شود:
$user = User::create([ // Other user properties...]); $user->createAsCustomer([ 'trial_ends_at' => now()->addDays(10)]);
صندوقدار به این نوع آزمایش به عنوان یک "آزمایش عمومی" اشاره می کند، زیرا
به هیچ اشتراک موجود متصل نیست.
اگر تاریخ فعلی از مقدار زیر گذشته نباشد،
متد
onTrial
موجود در
User
نمونه برمیگردد
.
true
trial_ends_at
if ($user->onTrial()) { // User is within their trial period...}
onGenericTrial
همچنین اگر میخواهید به طور خاص بدانید که کاربر در دوره آزمایشی «عمومی»
خود است و هنوز اشتراک واقعی ایجاد نکرده است،
میتوانید از این روش استفاده کنید :
if ($user->onGenericTrial()) { // User is within their "generic" trial period...}
هنگامی که آماده ایجاد یک اشتراک واقعی برای کاربر هستید، می توانید
newSubscription
طبق معمول از روش زیر استفاده کنید:
$user = User::find(1); $payLink = $user->newSubscription('default', $monthly = 12345) ->returnTo(route('home')) ->create();
هیچ راهی برای تمدید یا تغییر دوره آزمایشی در اشتراک Paddle پس از ایجاد آن وجود ندارد.
رسیدگی به قلاب های وب پارویی
میتوانید از دستور Valet
share
برای کمک به آزمایش وبکهکها در طول توسعه محلی استفاده کنید.
Paddle می تواند برنامه شما را از رویدادهای مختلف از طریق وب هوک ها مطلع کند. به طور پیش فرض، مسیری که به کنترلر وب هوک Cashier اشاره می کند، از طریق ارائه دهنده خدمات Cashier پیکربندی می شود. این کنترلر تمام درخواست های وب هوک دریافتی را رسیدگی می کند.
بهطور پیشفرض، این کنترلکننده بهطور خودکار لغو اشتراکهایی را که هزینههای ناموفق زیادی دارند ( که توسط تنظیمات اشتراک Paddle شما تعریف شده است )، بهروزرسانیهای اشتراک و تغییرات روش پرداخت را کنترل میکند. با این حال، همانطور که به زودی متوجه خواهیم شد، می توانید این کنترلر را برای مدیریت هر رویداد وب هوکی که دوست دارید گسترش دهید.
برای اطمینان از اینکه برنامه شما میتواند به وبکهوکهای Paddle رسیدگی
کند، حتماً
URL وب هوک را در پانل کنترل Paddle پیکربندی کنید
.
به طور پیش فرض، کنترلر وب هوک Cashier به
/paddle/webhook
مسیر URL گوش می دهد.
لیست کامل تمام وبکهک هایی که باید در کنترل پنل Paddle پیکربندی کنید
عبارتند از:
- اشتراک ایجاد شد
- اشتراک به روز شد
- اشتراک حذف شد
- پرداخت با موفقیت انجام شد
- پرداخت اشتراک با موفقیت انجام شد
مطمئن شوید که از درخواستهای دریافتی با میانافزار تأیید امضای وبهوک شامل Cashier محافظت میکنید .
Webhooks & CSRF Protection
از آنجایی که وب هوک های Paddle باید
حفاظت CSRF
لاراول را دور بزنند ، حتماً URI را به عنوان یک استثنا در
VerifyCsrfToken
میان افزار خود فهرست کنید یا مسیر خارج از
web
گروه میان افزار را فهرست کنید:
protected $except = [ 'paddle/*',];
تعریف مدیریت رویداد Webhook
Cashier به طور خودکار لغو اشتراک را در صورت هزینههای ناموفق رسیدگی
میکند، اما اگر رویدادهای webhook دیگری دارید که میخواهید مدیریت کنید، باید این زمان را تمدید کنید
WebhookController
.
نام روشهای شما باید مطابق با قرارداد مورد انتظار Cashier باشد، بهویژه،
باید پیشوند روشها
handle
و نام «مورد شتر» وبقلابی باشد که میخواهید مدیریت کنید.
به عنوان مثال، اگر می خواهید
payment_succeeded
وب هوک را مدیریت کنید، باید یک
handlePaymentSucceeded
روش به کنترلر اضافه کنید:
<?php namespace App\Http\Controllers; use Laravel\Paddle\Http\Controllers\WebhookController as CashierController; class WebhookController extends CashierController{ /** * Handle payment succeeded. * * @param array $payload * @return void */ public function handlePaymentSucceeded($payload) { // Handle The Event }}
در مرحله بعد، مسیری را برای کنترل صندوقدار خود در
routes/web.php
فایل خود تعریف کنید.
با این کار مسیر ارائه شده با Cashier بازنویسی می شود:
Route::post( 'paddle/webhook', '\App\Http\Controllers\WebhookController');
صندوقدار یک
Laravel\Paddle\Events\WebhookReceived
رویداد را هنگام دریافت وب هوک و
Laravel\Paddle\Events\WebhookHandled
رویدادی را هنگام رسیدگی به یک وب هوک منتشر می کند.
هر دو رویداد حاوی بار کامل وب هوک Paddle هستند.
صندوقدار همچنین رویدادهای اختصاص داده شده به نوع وب هوک دریافتی را منتشر می کند. علاوه بر بار کامل از Paddle، آنها همچنین حاوی مدلهای مربوطه هستند که برای پردازش وبقلاب استفاده شدهاند، مانند مدل قابل صورتحساب، اشتراک یا رسید:
-
PaymentSucceeded
-
SubscriptionPaymentSucceeded
-
SubscriptionCreated
-
SubscriptionUpdated
-
SubscriptionCancelled
CASHIER_WEBHOOK
همچنین میتوانید با تنظیم متغیر env در فایل خود،
مسیر پیشفرض وب هوک داخلی را به صورت اختیاری لغو کنید
.env
.
این مقدار باید URL کامل مسیر وب هوک شما باشد و باید با URL تنظیم شده در
پانل کنترل Paddle شما مطابقت داشته باشد:
CASHIER_WEBHOOK=https://example.com/my-paddle-webhook-url
اشتراک های ناموفق
اگر اعتبار کارت اعتباری مشتری منقضی شود چه می شود؟ نگران نباشید - کنترلر Cashier's Webhook اشتراک مشتری را برای شما لغو می کند. پرداختهای ناموفق بهطور خودکار توسط کنترلکننده ضبط و رسیدگی میشود. هنگامی که Paddle تشخیص دهد که اشتراک ناموفق بوده است، کنترل کننده اشتراک مشتری را لغو می کند (معمولاً پس از سه بار تلاش برای پرداخت ناموفق).
تأیید امضاهای Webhook
برای ایمن سازی وب هوک های خود، می توانید از امضاهای وب هوک Paddle استفاده کنید . برای راحتی کار، Cashier به طور خودکار شامل یک میان افزار می شود که اعتبار درخواست دریافتی Paddle webhook را تأیید می کند.
برای فعال کردن تأیید وب هوک، مطمئن شوید که
PADDLE_PUBLIC_KEY
متغیر محیط در
.env
فایل شما تنظیم شده است.
ممکن است کلید عمومی از داشبورد حساب Paddle شما بازیابی شود.
شارژ تک
شارژ ساده
اگر میخواهید یک هزینه «یکباره» از مشتری دریافت کنید، میتوانید
charge
از روش یک نمونه مدل قابل پرداخت برای ایجاد پیوند پرداخت برای هزینه
استفاده کنید.
این
charge
روش مقدار شارژ (float) را به عنوان اولین آرگومان خود و توضیح شارژ را به
عنوان آرگومان دوم خود می پذیرد:
$payLink = $user->charge(12.99, 'Product Title'); return view('pay', ['payLink' => $payLink]);
پس از ایجاد پیوند پرداخت، میتوانید از
paddle-button
مؤلفه Blade ارائه شده توسط Cashier استفاده کنید تا به کاربر اجازه دهید
ویجت Paddle را راهاندازی کند و هزینه را تکمیل کند:
<x-paddle-button :url="$payLink" class="px-8 py-4"> Buy</x-paddle-button>
این
charge
روش یک آرایه را به عنوان آرگومان سوم خود می پذیرد و به شما امکان می دهد
هر گزینه ای را که می خواهید به ایجاد پیوند پرداخت Paddle زیربنایی منتقل کنید.
لطفاً
برای کسب اطلاعات بیشتر درباره گزینههای موجود هنگام ایجاد هزینه، به
مستندات Paddle مراجعه کنید:
$payLink = $user->charge(12.99, 'Product Title', [ 'custom_option' => $value,]);
هزینه ها به ارز مشخص شده در
cashier.currency
گزینه پیکربندی انجام می شود.
به طور پیش فرض، این روی USD تنظیم شده است.
CASHIER_CURRENCY
شما می توانید با تنظیم در فایل خود
، ارز پیش فرض را لغو کنید
.env
:
CASHIER_CURRENCY=EUR
همچنین میتوانید با استفاده از سیستم تطبیق قیمت پویا Paddle، قیمتهای هر ارز را لغو کنید . برای انجام این کار، به جای مقدار ثابت، آرایه ای از قیمت ها را ارسال کنید:
$payLink = $user->charge([ 'USD:19.99', 'EUR:15.99',], 'Product Title');
شارژ محصولات
اگر میخواهید برای یک محصول خاص که در Paddle پیکربندی شده است، هزینه
«یکباره» بپردازید، میتوانید
chargeProduct
از روش یک نمونه مدل قابل پرداخت برای ایجاد پیوند پرداخت استفاده کنید:
$payLink = $user->chargeProduct($productId); return view('pay', ['payLink' => $payLink]);
سپس، میتوانید پیوند پرداخت را به
paddle-button
مؤلفه ارائه دهید تا به کاربر اجازه دهید ویجت Paddle را مقداردهی اولیه
کند:
<x-paddle-button :url="$payLink" class="px-8 py-4"> Buy</x-paddle-button>
این
chargeProduct
روش آرایهای را بهعنوان آرگومان دوم خود میپذیرد و به شما امکان میدهد
هر گزینهای را که میخواهید به ایجاد پیوند پرداخت Paddle زیربنایی منتقل کنید.
لطفاً
در مورد گزینههایی که هنگام ایجاد هزینه در دسترس شما هستند، به
اسناد Paddle مراجعه کنید:
$payLink = $user->chargeProduct($productId, [ 'custom_option' => $value,]);
سفارشات بازپرداخت
اگر نیاز به بازپرداخت سفارش Paddle دارید، می توانید از این
refund
روش استفاده کنید.
این متد شناسه Paddle Order ID را به عنوان اولین آرگومان خود می پذیرد.
میتوانید رسیدهای یک نهاد قابل پرداخت را با استفاده از
receipts
روش زیر بازیابی کنید:
$receipt = $user->receipts()->first(); $refundRequestId = $user->refund($receipt->order_id);
همچنین می توانید به صورت اختیاری مبلغ خاصی را برای بازپرداخت و همچنین دلیلی برای بازپرداخت مشخص کنید:
$receipt = $user->receipts()->first(); $refundRequestId = $user->refund( $receipt->order_id, 5.00, 'Unused product time');
هنگام تماس با پشتیبانی Paddle می توانید از آن
$refundRequestId
به عنوان مرجع بازپرداخت استفاده کنید.
رسیدها
می توانید به راحتی آرایه ای از رسیدهای یک مدل قابل پرداخت را با استفاده
از
receipts
روش زیر بازیابی کنید:
$receipts = $user->receipts();
هنگام فهرست کردن رسیدها برای مشتری، می توانید از روش های کمکی رسید برای نمایش اطلاعات رسید مربوطه استفاده کنید. برای مثال، ممکن است بخواهید همه رسیدها را در یک جدول فهرست کنید تا کاربر بتواند به راحتی هر یک از رسیدها را دانلود کند:
<table> @foreach ($receipts as $receipt) <tr> <td>{{ $receipt->paid_at->toFormattedDateString() }}</td> <td>{{ $receipt->amount() }}</td> <td><a href="{{ $receipt->receipt_url }}" target="_blank">Download</a></td> </tr> @endforeach</table>
پرداخت های گذشته و آینده
میتوانید از روشها
lastPayment
و
nextPayment
برای نمایش پرداختهای گذشته یا آتی مشتری برای اشتراکهای تکراری استفاده
کنید:
$subscription = $user->subscription('default'); $lastPayment = $subscription->lastPayment();$nextPayment = $subscription->nextPayment();
هر دوی این روش ها نمونه ای از
Laravel\Paddle\Payment
;
با این حال،
پس از پایان چرخه صورتحساب (مانند زمانی که اشتراک لغو شده است)
nextPayment
باز خواهد گشت :
null
Next payment: {{ $nextPayment->amount() }} due on {{ $nextPayment->date()->format('d/m/Y') }}
رسیدگی به پرداخت های ناموفق
پرداخت های اشتراک به دلایل مختلف مانند کارت های منقضی شده یا کارتی که وجوه کافی ندارد، با شکست مواجه می شوند. وقتی این اتفاق میافتد، توصیه میکنیم که به Paddle اجازه دهید مشکلات پرداخت را برای شما مدیریت کند. به طور خاص، میتوانید ایمیلهای صورتحساب خودکار Paddle را در داشبورد Paddle خود تنظیم کنید.
subscription_payment_failed
همچنین، میتوانید با گرفتن وبهوک و فعال کردن گزینه «پرداخت اشتراک
ناموفق» در تنظیمات Webhook داشبورد Paddle خود،
سفارشیسازی دقیقتری انجام دهید :
<?php namespace App\Http\Controllers; use Laravel\Paddle\Http\Controllers\WebhookController as CashierController; class WebhookController extends CashierController{ /** * Handle subscription payment failed. * * @param array $payload * @return void */ public function handleSubscriptionPaymentFailed($payload) { // Handle the failed subscription payment... }}
آزمایش کردن
Paddle در حال حاضر فاقد یک CRUD API مناسب است، بنابراین باید به صورت دستی جریان صورتحساب خود را آزمایش کنید. Paddle همچنین فاقد محیط توسعهدهنده sandboxed است، بنابراین هر هزینهای که از کارت میکنید، هزینه واقعی است. برای حل این مشکل، توصیه می کنیم از کوپن هایی با 100٪ تخفیف یا محصولات رایگان در طول آزمایش استفاده کنید.