توسعه و سفارشیسازی
توسعه و سفارشیسازی
افزودن درگاه پرداخت سفارشی
۱. پیادهسازی PaymentGatewayInterface
رابط PaymentGatewayInterface پنج متد دارد که همه باید پیادهسازی شوند: request، verify، refund، get_name، و supports_refund. توجه کنید که مبلغها همگی به تومان (int) هستند.
namespace MyPlugin\Gateways;
use ProNobat\Gateways\PaymentGatewayInterface;
use ProNobat\Gateways\PaymentRequestResult;
use ProNobat\Gateways\PaymentVerifyResult;
use ProNobat\Gateways\PaymentRefundResult;
use ProNobat\Settings\Settings;
class MyGateway implements PaymentGatewayInterface {
public function get_name(): string {
return 'my_gateway'; // باید با کلید Settings و مقدار enum پایگاه داده مطابقت داشته باشد
}
public function supports_refund(): bool {
return false; // اگر درگاه استرداد خودکار ندارد، false برگردانید
}
private function api_key(): string {
// تنظیمات درگاه زیر payments.<slug> ذخیره میشود
return (string) Settings::instance()->get_secret( 'payments.my_gateway.api_key' );
}
public function request(
int $amount_toman,
string $description,
string $callback_url,
array $metadata = []
): PaymentRequestResult {
$response = wp_remote_post( 'https://mygateway.com/api/payment', [
'body' => [
'api_key' => $this->api_key(),
'amount' => $amount_toman,
'description' => $description,
'callback_url' => $callback_url,
],
] );
$body = json_decode( (string) wp_remote_retrieve_body( $response ), true );
return new PaymentRequestResult(
success: ! is_wp_error( $response ) && ( $body['status'] ?? '' ) === 'ok',
authority: (string) ( $body['authority'] ?? '' ),
redirect_url: (string) ( $body['payment_url'] ?? '' ),
error: (string) ( $body['message'] ?? '' ),
);
}
public function verify(
string $authority,
int $amount_toman,
array $callback_data = []
): PaymentVerifyResult {
$response = wp_remote_post( 'https://mygateway.com/api/verify', [
'body' => [
'api_key' => $this->api_key(),
'authority' => sanitize_text_field( $authority ),
'amount' => $amount_toman,
],
] );
$body = json_decode( (string) wp_remote_retrieve_body( $response ), true );
return new PaymentVerifyResult(
success: ! is_wp_error( $response ) && ( $body['status'] ?? '' ) === 'verified',
ref_id: (string) ( $body['ref_id'] ?? '' ),
error: (string) ( $body['message'] ?? '' ),
);
}
public function refund(
string $gateway_ref,
int $amount_toman,
string $reason = ''
): PaymentRefundResult {
return new PaymentRefundResult( success: false, error: 'manual_refund_required' );
}
}۲. ثبت درگاه با فیلتر
مقدار هر کلید باید یک نمونه (instance) از کلاس درگاه باشد؛ افزونه با instanceof بررسی میکند و نام کلاس (::class) پذیرفته نمیشود.
add_filter( 'pronobat_payment_gateways', function( array $gateways ) {
$gateways['my_gateway'] = new \MyPlugin\Gateways\MyGateway();
return $gateways;
} );تنظیمات درگاه سفارشی شما زیر کلید payments.my_gateway در آرایهی Settings ذخیره میشود و با Settings::instance()->get_secret( 'payments.my_gateway.api_key' ) قابل خواندن است. پنل تنظیمات پرونوبت مبتنی بر React است؛ بنابراین برای افزودن فیلد سفارشی به رابط کاربری باید آن SPA را گسترش دهید یا تنظیمات را از طریق فیلتر/کد خود مدیریت کنید.
گسترش AvailabilityCalculator
برای تغییر منطق بازههای خالی از فیلتر pronobat_available_slots استفاده کنید:
add_filter( 'pronobat_available_slots', function( array $slots, int $staff_id, string $date, int $service_id ) {
// مثال: حذف بازههای بعد از ساعت ۱۷ برای سرویس شماره ۵
if ( $service_id === 5 ) {
$slots = array_filter( $slots, fn($s) => substr( $s['start'], 0, 2 ) < 17 );
}
return array_values( $slots );
}, 10, 4 );الگوهای امن
- همیشه
$wpdb->prepare()برای کوئریهای پایگاه داده استفاده کنید - ورودیهای کاربر را با
sanitize_text_field(),absint(),esc_url_raw()پاکسازی کنید - هرگز مستقیم
$_POSTرا نخوانید — از args مسیر REST باsanitize_callbackاستفاده کنید
پرونوبت را همین الان امتحان کنید
یک نمونه کامل و زنده از افزونه با دادههای واقعی — بدون نیاز به نصب.