feat(pay): guest cash purchase with signed cookie unlock (zibll-style)
Allow pay_no_logged_in cash content orders (user_id=0), set aksrt_pay_* cookies on paid, accept cookie in access state, and expose guest CTA on paywall/box.
This commit is contained in:
1 parent
8f15d16d35
commit
8e9e05c859
6 files changed
+301
-35
No files matched your search
@@ -237,6 +237,177 @@ if (!function_exists('aksrt_bump_content_sales_volume')) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether guest cash purchase is allowed (Zibll pay_no_logged_in + pay_limit=0).
|
||||
*/
|
||||
if (!function_exists('aksrt_allow_guest_content_pay')) {
|
||||
function aksrt_allow_guest_content_pay($post = null): bool {
|
||||
$p = get_post($post);
|
||||
if (!($p instanceof WP_Post)) {
|
||||
return false;
|
||||
}
|
||||
$meta = function_exists('aksrt_get_pay_meta') ? aksrt_get_pay_meta($p) : [];
|
||||
$pay_limit = (int) ($meta['pay_limit'] ?? 0);
|
||||
if ($pay_limit > 0) {
|
||||
return false;
|
||||
}
|
||||
$pay_modo = (($meta['pay_modo'] ?? '0') === 'points') ? 'points' : '0';
|
||||
if ($pay_modo === 'points') {
|
||||
return false; // points require login
|
||||
}
|
||||
$order = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_order_settings() : [];
|
||||
$paid = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_paid_content_settings() : [];
|
||||
$allow = !empty($order['no_logged_in']) || !empty($paid['no_logged_in']);
|
||||
/**
|
||||
* Filter guest content pay allow.
|
||||
*
|
||||
* @param bool $allow
|
||||
* @param WP_Post $p
|
||||
*/
|
||||
return (bool) apply_filters('aksrt_allow_guest_content_pay', $allow, $p);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cookie lifetime days for guest paid content (Zibll pay_cookie_day).
|
||||
*/
|
||||
if (!function_exists('aksrt_guest_pay_cookie_days')) {
|
||||
function aksrt_guest_pay_cookie_days(int $post_id = 0): int {
|
||||
$days = 15;
|
||||
if (class_exists('AKSRT_Settings')) {
|
||||
$order = AKSRT_Settings::get_order_settings();
|
||||
$days = max(1, min(31, (int) ($order['cookie_day'] ?? 15)));
|
||||
}
|
||||
/**
|
||||
* @param int $days
|
||||
* @param int $post_id
|
||||
*/
|
||||
return max(1, (int) apply_filters('aksrt_guest_pay_cookie_days', $days, $post_id));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Client IP helper for cookie token binding.
|
||||
*/
|
||||
if (!function_exists('aksrt_pay_client_ip')) {
|
||||
function aksrt_pay_client_ip(): string {
|
||||
if (function_exists('aksrt_get_client_ip')) {
|
||||
return (string) aksrt_get_client_ip();
|
||||
}
|
||||
return (string) ($_SERVER['REMOTE_ADDR'] ?? '');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build token material for guest order cookie (zibll-style).
|
||||
*
|
||||
* @param array<string,mixed> $order
|
||||
*/
|
||||
if (!function_exists('aksrt_content_order_cookie_token_key')) {
|
||||
function aksrt_content_order_cookie_token_key(array $order): string {
|
||||
$meta = is_array($order['meta_payload'] ?? null) ? $order['meta_payload'] : [];
|
||||
$ip = (string) ($meta['ip_address'] ?? $order['ip_address'] ?? '');
|
||||
$id = (string) ($order['id'] ?? $order['order_number'] ?? '');
|
||||
$post_id = (int) ($order['product_id'] ?? $meta['post_id'] ?? 0);
|
||||
$num = (string) ($order['order_number'] ?? '');
|
||||
$amount = function_exists('aksrt_format_price')
|
||||
? aksrt_format_price((float) ($order['amount'] ?? 0))
|
||||
: (string) round((float) ($order['amount'] ?? 0), 2);
|
||||
return $id . '_' . $post_id . '_' . trim($num) . '_' . $amount . '_' . trim($ip);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set guest paid cookies after content order paid (Zibll zibpay_posts_order_created_set_cookie).
|
||||
*
|
||||
* @param array<string,mixed> $order
|
||||
*/
|
||||
if (!function_exists('aksrt_set_guest_content_pay_cookies')) {
|
||||
function aksrt_set_guest_content_pay_cookies(array $order): void {
|
||||
$post_id = (int) ($order['product_id'] ?? 0);
|
||||
$order_number = (string) ($order['order_number'] ?? '');
|
||||
if ($post_id <= 0 || $order_number === '') {
|
||||
return;
|
||||
}
|
||||
$days = aksrt_guest_pay_cookie_days($post_id);
|
||||
$expire = time() + (DAY_IN_SECONDS * $days);
|
||||
$path = defined('COOKIEPATH') && COOKIEPATH ? COOKIEPATH : '/';
|
||||
$domain = defined('COOKIE_DOMAIN') ? COOKIE_DOMAIN : '';
|
||||
$secure = is_ssl();
|
||||
$httponly = true;
|
||||
|
||||
setcookie('aksrt_pay_' . $post_id, $order_number, $expire, $path, $domain, $secure, $httponly);
|
||||
$_COOKIE['aksrt_pay_' . $post_id] = $order_number;
|
||||
|
||||
$token = md5(aksrt_content_order_cookie_token_key($order));
|
||||
$token_name = 'aksrt_pay_token_' . md5($order_number);
|
||||
setcookie($token_name, $token, $expire, $path, $domain, $secure, $httponly);
|
||||
$_COOKIE[$token_name] = $token;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve guest paid order from browser cookie for a post.
|
||||
*
|
||||
* @return array<string,mixed>|null
|
||||
*/
|
||||
if (!function_exists('aksrt_get_guest_content_paid_order')) {
|
||||
function aksrt_get_guest_content_paid_order(int $post_id): ?array {
|
||||
if ($post_id <= 0 || empty($_COOKIE['aksrt_pay_' . $post_id])) {
|
||||
return null;
|
||||
}
|
||||
if (!class_exists('AKSRT_Order_Repository')) {
|
||||
return null;
|
||||
}
|
||||
$order_number = sanitize_text_field((string) $_COOKIE['aksrt_pay_' . $post_id]);
|
||||
if ($order_number === '') {
|
||||
return null;
|
||||
}
|
||||
$order = AKSRT_Order_Repository::get_instance()->get($order_number);
|
||||
if (!$order) {
|
||||
return null;
|
||||
}
|
||||
if ((string) ($order['product_type'] ?? '') !== AKSRT_Domain_Model::ORDER_PRODUCT_RESOURCE) {
|
||||
return null;
|
||||
}
|
||||
if ((int) ($order['product_id'] ?? 0) !== $post_id) {
|
||||
return null;
|
||||
}
|
||||
$status = (string) ($order['status'] ?? '');
|
||||
if (!AKSRT_Domain_Model::is_paid_order_status($status)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Cookie day window from paid_at.
|
||||
$paid_at = (string) ($order['paid_at'] ?? $order['created_at'] ?? '');
|
||||
if ($paid_at !== '') {
|
||||
$ts = strtotime($paid_at);
|
||||
$days = aksrt_guest_pay_cookie_days($post_id);
|
||||
if ($ts !== false && ($ts + DAY_IN_SECONDS * $days) < time()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
$token_name = 'aksrt_pay_token_' . md5($order_number);
|
||||
$cookie_token = isset($_COOKIE[$token_name]) ? (string) $_COOKIE[$token_name] : '';
|
||||
$expect = md5(aksrt_content_order_cookie_token_key($order));
|
||||
if ($cookie_token === '' || !hash_equals($expect, $cookie_token)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $order;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether current request has paid access via guest cookie.
|
||||
*/
|
||||
if (!function_exists('aksrt_guest_has_paid_access')) {
|
||||
function aksrt_guest_has_paid_access(int $post_id): bool {
|
||||
return null !== aksrt_get_guest_content_paid_order($post_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the amount a given user should pay for a post (Zibll VIP tier min).
|
||||
*
|
||||
@@ -813,9 +984,18 @@ if (!function_exists('aksrt_get_paywall_html')) {
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php if (!$is_logged_in) : ?>
|
||||
<?php if ($pay_limit <= 0 && $price > 0 && $pay_modo !== 'points' && function_exists('aksrt_allow_guest_content_pay') && aksrt_allow_guest_content_pay($post)) : ?>
|
||||
<button type="button" class="but <?php echo $pay_modo === 'points' ? 'jb-yellow' : 'jb-red'; ?> padding-lg cashier-link aksrt-paywall__btn" data-aksrt-pay-content="<?php echo esc_attr((string) $post->ID); ?>">
|
||||
<i class="fa fa-shopping-cart" aria-hidden="true"></i> <?php printf(esc_html__('游客购买(%s)', 'aksrt'), $price_text); ?>
|
||||
</button>
|
||||
<p class="aksrt-paywall__hint" style="margin-top:10px;">
|
||||
<a href="<?php echo esc_url($login_url); ?>"><?php esc_html_e('已有账号?登录后购买', 'aksrt'); ?></a>
|
||||
</p>
|
||||
<?php else : ?>
|
||||
<a href="<?php echo esc_url($login_url); ?>" class="but jb-red padding-lg aksrt-paywall__btn">
|
||||
<i class="fa fa-sign-in" aria-hidden="true"></i> <?php esc_html_e('登录后购买', 'aksrt'); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<?php elseif ($member_blocked) : ?>
|
||||
<a href="<?php echo esc_url($vip_url); ?>" class="but jb-vip padding-lg aksrt-paywall__btn">
|
||||
<i class="fas fa-crown" aria-hidden="true"></i> <?php esc_html_e('开通会员后可查看', 'aksrt'); ?>
|
||||
|
||||
Reference in new issue
Block a user