1
0
Fork 0
mirror of https://github.com/DanielnetoDotCom/YouPHPTube synced 2025-10-03 17:59:55 +02:00

Add Authorize.Net subscription management functionality

- Implemented cancelSubscription.json.php for handling subscription cancellations via JSON API.
- Created cancelSubscription.php for managing subscription views and cancellation in the UI.
- Developed getAcceptHostedToken.json.php to generate payment tokens for Authorize.Net.
- Added getProfileManager.json.php for managing user profiles with Authorize.Net.
- Implemented getSubscriptionStatus.json.php to check the status of subscriptions.
- Created getSubscriptions.json.php to retrieve all subscriptions for the logged-in user.
- Added SQL installation script for webhook logging.
- Implemented processPayment.json.php for processing payments through Authorize.Net.
- Developed webhook.php to handle incoming webhooks from Authorize.Net.
- Integrated YPTWallet with Authorize.Net for wallet funding and subscription management.
- Added confirmButton.php and confirmRecurrentButton.php for payment confirmation buttons in YPTWallet.
This commit is contained in:
Daniel Neto 2025-07-23 10:57:06 -03:00
parent 4ea653e8af
commit e63ea73beb
21 changed files with 3312 additions and 0 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,156 @@
<?php
require_once dirname(__FILE__) . '/../../../videos/configuration.php';
class Anet_webhook_log extends ObjectYPT
{
protected $id, $uniq_key, $event_type, $trans_id, $payload_json, $processed, $error_text, $status, $created_php_time, $modified_php_time, $users_id;
static function getSearchFieldsNames()
{
return array('uniq_key', 'event_type', 'trans_id', 'error_text', 'status');
}
static function getTableName()
{
return 'anet_webhook_log';
}
function setId($id)
{
$this->id = intval($id);
}
function setUniq_key($uniq_key)
{
$this->uniq_key = $uniq_key;
}
function setEvent_type($event_type)
{
$this->event_type = $event_type;
}
function setTrans_id($trans_id)
{
$this->trans_id = $trans_id;
}
function setPayload_json($payload_json)
{
$this->payload_json = $payload_json;
}
function setProcessed($processed)
{
$this->processed = intval($processed);
}
function setError_text($error_text)
{
$this->error_text = $error_text;
}
function setStatus($status)
{
$this->status = $status;
}
function setCreated_php_time($created_php_time)
{
$this->created_php_time = $created_php_time;
}
function setModified_php_time($modified_php_time)
{
$this->modified_php_time = $modified_php_time;
}
function setUsers_id($users_id)
{
$this->users_id = intval($users_id);
}
function getId()
{
return intval($this->id);
}
function getUniq_key()
{
return $this->uniq_key;
}
function getEvent_type()
{
return $this->event_type;
}
function getTrans_id()
{
return $this->trans_id;
}
function getPayload_json()
{
return $this->payload_json;
}
function getProcessed()
{
return intval($this->processed);
}
function getError_text()
{
return $this->error_text;
}
function getStatus()
{
return $this->status;
}
function getCreated_php_time()
{
return $this->created_php_time;
}
function getModified_php_time()
{
return $this->modified_php_time;
}
function getUsers_id()
{
return intval($this->users_id);
}
public static function alreadyProcessed($uniq_key)
{
if (empty($uniq_key)) {
return false;
}
$obj = self::getFromUniqKey($uniq_key);
if (!empty($obj) && !empty($obj['processed'])) {
return true;
}
return false;
}
public static function getFromUniqKey($uniq_key)
{
global $global;
$sql = "SELECT * FROM " . static::getTableName() . " WHERE uniq_key = ? LIMIT 1";
$res = sqlDAL::readSql($sql, "s", [$uniq_key]);
$data = sqlDAL::fetchAssoc($res);
sqlDAL::close($res);
if ($res) {
return $data;
}
return false;
}
public static function createIfNotExists($uniq_key, $event_type, $payload_json, $users_id = 0)
{
if (self::alreadyProcessed($uniq_key)) {
return false;
}
if(empty($users_id)){
$users_id = User::getId();
}
$obj = new self();
$obj->setUniq_key($uniq_key);
$obj->setEvent_type($event_type);
$obj->setPayload_json(_json_encode($payload_json));
$obj->setUsers_id($users_id);
$obj->setProcessed(0);
$obj->setCreated_php_time(time());
$obj->setModified_php_time(time());
return $obj->save();
}
}

View file

@ -0,0 +1,33 @@
<?php
header('Content-Type: application/json');
require_once '../../../../videos/configuration.php';
require_once $global['systemRootPath'] . 'plugin/AuthorizeNet/Objects/Anet_webhook_log.php';
$obj = new stdClass();
$obj->error = true;
$obj->msg = "";
$plugin = AVideoPlugin::loadPluginIfEnabled('AuthorizeNet');
if(!User::isAdmin()){
$obj->msg = "You cant do this";
die(json_encode($obj));
}
$o = new Anet_webhook_log(@$_POST['id']);
$o->setUniq_key($_POST['uniq_key']);
$o->setEvent_type($_POST['event_type']);
$o->setTrans_id($_POST['trans_id']);
$o->setPayload_json($_POST['payload_json']);
$o->setProcessed($_POST['processed']);
$o->setError_text($_POST['error_text']);
$o->setStatus($_POST['status']);
$o->setCreated_php_time($_POST['created_php_time']);
$o->setModified_php_time($_POST['modified_php_time']);
$o->setUsers_id($_POST['users_id']);
if($id = $o->save()){
$obj->error = false;
}
echo json_encode($obj);

View file

@ -0,0 +1,20 @@
<?php
require_once '../../../../videos/configuration.php';
require_once $global['systemRootPath'] . 'plugin/AuthorizeNet/Objects/Anet_webhook_log.php';
header('Content-Type: application/json');
$obj = new stdClass();
$obj->error = true;
$plugin = AVideoPlugin::loadPluginIfEnabled('AuthorizeNet');
if(!User::isAdmin()){
$obj->msg = "You cant do this";
die(json_encode($obj));
}
$id = intval($_POST['id']);
$row = new Anet_webhook_log($id);
$obj->error = !$row->delete();
die(json_encode($obj));
?>

View file

@ -0,0 +1,19 @@
<?php
global $global, $config;
if (!isset($global['systemRootPath'])) {
require_once __DIR__.'/../../../../videos/configuration.php';
}
if (!User::isAdmin()) {
forbiddenPage('You can not do this');
exit;
}
$plugin = AVideoPlugin::loadPluginIfEnabled('AuthorizeNet');
if(empty($plugin)){
forbiddenPage('Plugin AuthorizeNet is disabled');
}
$_page = new Page(array('AuthorizeNet'));
$_page->setExtraStyles(array('view/css/DataTables/datatables.min.css', 'view/js/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css'));
$_page->setExtraScripts(array('view/css/DataTables/datatables.min.js'));
include $global['systemRootPath'] . 'plugin/AuthorizeNet/View/Anet_webhook_log/index_body.php';
$_page->print();
?>

View file

@ -0,0 +1,169 @@
<?php
global $global, $config;
if (!isset($global['systemRootPath'])) {
require_once '../../videos/configuration.php';
}
if (!User::isAdmin()) {
forbiddenPage('Admins only');
}
?>
<div class="container-fluid">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fas fa-cog"></i> <?php echo __("Configurations"); ?>
</div>
<div class="panel-body">
<div class="row">
<div class="col-sm-4">
<div class="panel panel-default ">
<div class="panel-heading"><i class="far fa-plus-square"></i> <?php echo __("Create"); ?></div>
<div class="panel-body">
<form id="panelAnet_webhook_logForm">
<div class="row">
<div class="form-group col-sm-12">
<div class="btn-group pull-right">
<span class="btn btn-success" id="newAnet_webhook_logLink" onclick="clearAnet_webhook_logForm()"><i class="fas fa-plus"></i> <?php echo __("New"); ?></span>
<button class="btn btn-primary" type="submit"><i class="fas fa-save"></i> <?php echo __("Save"); ?></button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="col-sm-8">
<div class="panel panel-default ">
<div class="panel-heading"><i class="fas fa-edit"></i> <?php echo __("Edit"); ?></div>
<div class="panel-body">
<table id="Anet_webhook_logTable" class="display table table-bordered table-responsive table-striped table-hover table-condensed" width="100%" cellspacing="0">
<thead>
<tr>
<th></th>
</tr>
</thead>
<tfoot>
<tr>
<th></th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="Anet_webhook_logbtnModelLinks" style="display: none;">
<div class="btn-group pull-right">
<button href="" class="edit_Anet_webhook_log btn btn-default btn-xs">
<i class="fa fa-edit"></i>
</button>
<button href="" class="delete_Anet_webhook_log btn btn-danger btn-xs">
<i class="fa fa-trash"></i>
</button>
</div>
</div>
</div>
<script type="text/javascript">
function clearAnet_webhook_logForm() {
}
$(document).ready(function () {
$('#addAnet_webhook_logBtn').click(function () {
$.ajax({
url: webSiteRootURL+'plugin/AuthorizeNet/View/addAnet_webhook_logVideo.php',
data: $('#panelAnet_webhook_logForm').serialize(),
type: 'post',
success: function (response) {
if (response.error) {
avideoAlertError(response.msg);
} else {
avideoToast("<?php echo __("Your register has been saved!"); ?>");
$("#panelAnet_webhook_logForm").trigger("reset");
}
clearAnet_webhook_logForm();
tableVideos.ajax.reload();
modal.hidePleaseWait();
}
});
});
var Anet_webhook_logtableVar = $('#Anet_webhook_logTable').DataTable({
serverSide: true,
"ajax": webSiteRootURL+"plugin/AuthorizeNet/View/Anet_webhook_log/list.json.php",
"columns": [
,
{
sortable: false,
data: null,
defaultContent: $('#Anet_webhook_logbtnModelLinks').html()
}
],
select: true,
});
$('#newAnet_webhook_log').on('click', function (e) {
e.preventDefault();
$('#panelAnet_webhook_logForm').trigger("reset");
$('#Anet_webhook_logid').val('');
});
$('#panelAnet_webhook_logForm').on('submit', function (e) {
e.preventDefault();
modal.showPleaseWait();
$.ajax({
url: webSiteRootURL+'plugin/AuthorizeNet/View/Anet_webhook_log/add.json.php',
data: $('#panelAnet_webhook_logForm').serialize(),
type: 'post',
success: function (response) {
if (response.error) {
avideoAlertError(response.msg);
} else {
avideoToast(__("Your register has been saved!"));
$("#panelAnet_webhook_logForm").trigger("reset");
}
Anet_webhook_logtableVar.ajax.reload();
$('#Anet_webhook_logid').val('');
modal.hidePleaseWait();
}
});
});
$('#Anet_webhook_logTable').on('click', 'button.delete_Anet_webhook_log', function (e) {
e.preventDefault();
var tr = $(this).closest('tr')[0];
var data = Anet_webhook_logtableVar.row(tr).data();
swal({
title: __("Are you sure?"),
text: __("You will not be able to recover this action!"),
icon: "warning",
buttons: true,
dangerMode: true,
})
.then(function (willDelete) {
if (willDelete) {
modal.showPleaseWait();
$.ajax({
type: "POST",
url: webSiteRootURL+"plugin/AuthorizeNet/View/Anet_webhook_log/delete.json.php",
data: data
}).done(function (resposta) {
if (resposta.error) {
avideoAlertError(resposta.msg);
}
Anet_webhook_logtableVar.ajax.reload();
modal.hidePleaseWait();
});
} else {
}
});
});
$('#Anet_webhook_logTable').on('click', 'button.edit_Anet_webhook_log', function (e) {
e.preventDefault();
var tr = $(this).closest('tr')[0];
var data = Anet_webhook_logtableVar.row(tr).data();
});
});
</script>

View file

@ -0,0 +1,16 @@
<?php
require_once '../../../../videos/configuration.php';
require_once $global['systemRootPath'] . 'plugin/AuthorizeNet/Objects/Anet_webhook_log.php';
header('Content-Type: application/json');
$rows = Anet_webhook_log::getAll();
$total = Anet_webhook_log::getTotal();
$response = array(
'data' => $rows,
'draw' => intval(@$_REQUEST['draw']),
'recordsTotal' => $total,
'recordsFiltered' => $total,
);
echo _json_encode($response);
?>

View file

@ -0,0 +1,29 @@
<?php
require_once '../../../videos/configuration.php';
AVideoPlugin::loadPlugin("AuthorizeNet");
$_page = new Page(array('AuthorizeNet'));
$_page->setExtraStyles(array('view/css/DataTables/datatables.min.css', 'view/js/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css'));
$_page->setExtraScripts(array('view/css/DataTables/datatables.min.js', 'view/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js'));
?>
<div class="container-fluid">
<div class="panel panel-default">
<div class="panel-heading"><?php echo __('AuthorizeNet') ?>
<div class="pull-right">
<?php echo AVideoPlugin::getSwitchButton("AuthorizeNet"); ?>
</div>
</div>
<div class="panel-body">
<ul class="nav nav-tabs">
<li class="active"><a data-toggle="tab" href="#Anet_webhook_log"><?php echo __("anet_webhook_log"); ?></a></li>
</ul>
<div class="tab-content">
<div id="Anet_webhook_log" class="tab-pane fade in active" style="padding: 10px;">
<?php include $global['systemRootPath'] . 'plugin/AuthorizeNet/View/Anet_webhook_log/index_body.php'; ?>
</div>
</div>
</div>
</div>
</div>
<?php
$_page->print();
?>

View file

@ -0,0 +1,90 @@
<?php
require_once __DIR__ . '/../../videos/configuration.php';
$isCanceled = !empty($_GET['cancel']);
$type = $isCanceled ? 'cancel' : 'success';
$messages = [
'success' => [
'title' => 'Payment Successful',
'icon' => 'fa-check-circle',
'alert' => 'alert-success',
'button' => 'btn-success',
'progress' => 'progress-bar-success',
'text' => 'Your payment has been processed successfully. This window will close automatically.'
],
'cancel' => [
'title' => 'Payment Cancelled',
'icon' => 'fa-times-circle',
'alert' => 'alert-warning',
'button' => 'btn-warning',
'progress' => 'progress-bar-warning',
'text' => 'Your payment was not completed. You can try again or contact support if needed.'
]
];
$_page = new Page([$messages[$type]['title']]);
$_page->setIncludeNavbar(false);
$_page->setIncludeFooter(false);
?>
<style>
.countdown {
font-size: 16px;
margin-top: 10px;
color: #333;
}
.alert {
font-size: 18px;
padding: 30px;
}
.btn-close-now {
margin-top: 15px;
}
.progress {
margin-top: 15px;
height: 20px;
}
</style>
<div class="container" style="margin-top: 50px;">
<div class="alert text-center <?php echo $messages[$type]['alert']; ?>">
<h3>
<i class="fa <?php echo $messages[$type]['icon']; ?>"></i>
<?php echo $messages[$type]['title']; ?>
</h3>
<p><?php echo $messages[$type]['text']; ?></p>
<p class="countdown">
<i class="fa fa-clock-o"></i> Closing in <span id="countdown">10</span> seconds...
</p>
<div class="progress">
<div id="progressBar" class="progress-bar <?php echo $messages[$type]['progress']; ?>" role="progressbar" style="width: 100%;">
</div>
</div>
<button class="btn <?php echo $messages[$type]['button']; ?> btn-close-now" onclick="window.close();">
<i class="fa fa-sign-out"></i> Close Now
</button>
</div>
</div>
<script>
var seconds = 10;
var total = seconds;
function updateCountdown() {
document.getElementById('countdown').innerText = seconds;
var percent = (seconds / total) * 100;
document.getElementById('progressBar').style.width = percent + '%';
if (seconds <= 0) {
window.close();
}
seconds--;
}
setInterval(updateCountdown, 1000);
window.onload = updateCountdown;
</script>
<?php
$_page->print();

View file

@ -0,0 +1,86 @@
<?php
require_once __DIR__ . '/../../videos/configuration.php';
header('Content-Type: application/json');
$obj = new stdClass();
$obj->error = true;
$obj->msg = "";
try {
// Check if user is logged in
if (!User::isLogged()) {
$obj->msg = "You must be logged in to cancel subscriptions";
die(json_encode($obj));
}
// Check if AuthorizeNet plugin is enabled
$plugin = AVideoPlugin::loadPluginIfEnabled('AuthorizeNet');
if (empty($plugin)) {
$obj->msg = "AuthorizeNet plugin is disabled";
die(json_encode($obj));
}
// Get subscription ID from POST data
$subscriptionId = $_POST['subscriptionId'] ?? '';
if (empty($subscriptionId)) {
$obj->msg = "Missing subscription ID";
die(json_encode($obj));
}
// Verify that this subscription belongs to the current user
$users_id = User::getId();
$customerProfileId = AuthorizeNet::getOrCreateCustomerProfile($users_id);
if (empty($customerProfileId)) {
$obj->msg = "Customer profile not found";
die(json_encode($obj));
}
// Get subscription details to verify ownership
$subscriptionResult = AuthorizeNet::getSubscriptionWithCurrentStatus($subscriptionId);
if ($subscriptionResult['error']) {
$obj->msg = "Failed to verify subscription: " . $subscriptionResult['msg'];
die(json_encode($obj));
}
// Additional security check: verify the subscription belongs to this customer
$userSubscriptions = AuthorizeNet::getUserActiveSubscriptions($users_id);
$subscriptionFound = false;
if (!$userSubscriptions['error']) {
foreach ($userSubscriptions['subscriptions'] as $sub) {
if ($sub['subscriptionId'] === $subscriptionId) {
$subscriptionFound = true;
break;
}
}
}
if (!$subscriptionFound) {
$obj->msg = "Subscription not found or does not belong to current user";
die(json_encode($obj));
}
// Cancel the subscription
$cancelResult = AuthorizeNet::cancelSubscription($subscriptionId);
if ($cancelResult['error']) {
$obj->msg = $cancelResult['msg'];
die(json_encode($obj));
}
// Success response
$obj->error = false;
$obj->msg = "Subscription canceled successfully";
$obj->subscriptionId = $subscriptionId;
$obj->status = $cancelResult['status'];
} catch (Exception $e) {
$obj->msg = "An error occurred: " . $e->getMessage();
_error_log("[AuthorizeNet] Error in cancelSubscription.json.php: " . $e->getMessage());
}
echo json_encode($obj);
?>

View file

@ -0,0 +1,496 @@
<?php
require_once __DIR__ . '/../../videos/configuration.php';
// Check if user is logged in
if (!User::isLogged()) {
forbiddenPage('You must be logged in to access this page');
}
// Check if AuthorizeNet plugin is enabled
$plugin = AVideoPlugin::loadPluginIfEnabled('AuthorizeNet');
if (empty($plugin)) {
forbiddenPage('AuthorizeNet plugin is disabled');
}
$users_id = User::getId();
$subscriptionId = $_GET['subscription_id'] ?? '';
// If specific subscription ID is provided, get that subscription
$subscription = null;
if (!empty($subscriptionId)) {
$result = AuthorizeNet::getSubscriptionWithCurrentStatus($subscriptionId);
if (!$result['error'] && !empty($result['subscription'])) {
$subscription = $result['subscription'];
}
}
$_page = new Page(['Manage Subscription']);
?>
<div class="container-fluid">
<div class="panel panel-default">
<div class="panel-heading">
<h4>
<i class="fa fa-credit-card"></i>
<?php echo __('Manage Subscriptions'); ?>
</h4>
</div>
<div class="panel-body">
<?php if (!empty($subscription)): ?>
<!-- Single Subscription View -->
<div class="well">
<div class="row">
<div class="col-md-8">
<h4 class="media-heading">
<i class="fa fa-file-text-o"></i>
<?php echo htmlspecialchars($subscription['name'] ?? 'Subscription'); ?>
<?php
$status = strtolower($subscription['currentStatus'] ?? $subscription['status']);
$badgeClass = '';
switch($status) {
case 'active':
$badgeClass = 'label-success';
break;
case 'suspended':
$badgeClass = 'label-warning';
break;
case 'canceled':
case 'expired':
$badgeClass = 'label-danger';
break;
default:
$badgeClass = 'label-default';
}
?>
<span class="label <?php echo $badgeClass; ?>">
<?php echo htmlspecialchars($subscription['currentStatus'] ?? $subscription['status']); ?>
</span>
</h4>
<div class="row" style="margin-top: 15px;">
<div class="col-sm-6">
<p><strong><i class="fa fa-tag"></i> <?php echo __('Subscription ID'); ?>:</strong><br>
<?php echo htmlspecialchars($subscription['subscriptionId']); ?></p>
</div>
<div class="col-sm-6">
<p><strong><i class="fa fa-dollar"></i> <?php echo __('Amount'); ?>:</strong><br>
$<?php echo number_format($subscription['amount'], 2); ?></p>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<p><strong><i class="fa fa-clock-o"></i> <?php echo __('Billing Cycle'); ?>:</strong><br>
Every <?php echo $subscription['interval']['length']; ?>
<?php echo $subscription['interval']['unit']; ?></p>
</div>
<?php if (!empty($subscription['startDate'])): ?>
<div class="col-sm-6">
<p><strong><i class="fa fa-calendar"></i> <?php echo __('Start Date'); ?>:</strong><br>
<?php echo htmlspecialchars($subscription['startDate']); ?></p>
</div>
<?php endif; ?>
</div>
<?php if (!empty($subscription['totalOccurrences']) || !empty($subscription['plans_id'])): ?>
<div class="row">
<?php if (!empty($subscription['totalOccurrences'])): ?>
<div class="col-sm-6">
<p><strong><i class="fa fa-repeat"></i> <?php echo __('Total Occurrences'); ?>:</strong><br>
<?php echo htmlspecialchars($subscription['totalOccurrences']); ?></p>
</div>
<?php endif; ?>
<?php if (!empty($subscription['plans_id'])): ?>
<div class="col-sm-6">
<p><strong><i class="fa fa-list-alt"></i> <?php echo __('Plan ID'); ?>:</strong><br>
<?php echo htmlspecialchars($subscription['plans_id']); ?></p>
</div>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
<div class="col-md-4 text-right">
<?php if ($subscription['isActive'] ?? false): ?>
<button type="button"
class="btn btn-danger btn-lg btn-block"
onclick="cancelSubscription('<?php echo htmlspecialchars($subscription['subscriptionId']); ?>')">
<i class="fa fa-times"></i> <?php echo __('Cancel Subscription'); ?>
</button>
<?php else: ?>
<div class="alert alert-info">
<i class="fa fa-info-circle"></i>
<?php echo __('This subscription is no longer active'); ?>
</div>
<?php endif; ?>
<button type="button"
class="btn btn-default btn-block"
onclick="refreshSubscriptionStatus('<?php echo htmlspecialchars($subscription['subscriptionId']); ?>')">
<i class="fa fa-refresh"></i> <?php echo __('Refresh Status'); ?>
</button>
</div>
</div>
</div>
<div class="text-center">
<a href="<?php echo $global['webSiteRootURL']; ?>plugin/AuthorizeNet/cancelSubscription.php" class="btn btn-primary">
<i class="fa fa-arrow-left"></i> <?php echo __('Back to All Subscriptions'); ?>
</a>
</div>
<?php else: ?>
<!-- All Subscriptions View -->
<div id="subscriptionsContainer">
<div class="text-center">
<i class="fa fa-spinner fa-spin fa-2x"></i>
<p><?php echo __('Loading your subscriptions...'); ?></p>
</div>
</div>
<div class="text-center" style="margin-top: 20px;">
<button type="button" class="btn btn-primary" onclick="loadSubscriptions()">
<i class="fa fa-refresh"></i> <?php echo __('Refresh Subscriptions'); ?>
</button>
</div>
<?php endif; ?>
</div>
</div>
</div>
<script>
$(document).ready(function() {
<?php if (empty($subscription)): ?>
loadSubscriptions();
<?php endif; ?>
});
function loadSubscriptions() {
$('#subscriptionsContainer').html(`
<div class="text-center">
<i class="fa fa-spinner fa-spin fa-2x"></i>
<p><?php echo __('Loading your subscriptions...'); ?></p>
</div>
`);
$.ajax({
url: webSiteRootURL + 'plugin/AuthorizeNet/getSubscriptions.json.php',
type: 'GET',
dataType: 'json',
success: function(response) {
if (response.error) {
$('#subscriptionsContainer').html(`
<div class="alert alert-danger">
<i class="fa fa-exclamation-triangle"></i>
<strong><?php echo __('Error'); ?>:</strong> ${response.msg}
</div>
`);
return;
}
if (response.subscriptions.length === 0) {
$('#subscriptionsContainer').html(`
<div class="alert alert-info">
<i class="fa fa-info-circle"></i>
<strong><?php echo __('No subscriptions found'); ?></strong>
<p><?php echo __('You don\'t have any active subscriptions at the moment.'); ?></p>
</div>
`);
return;
}
let html = '';
response.subscriptions.forEach(function(subscription) {
html += renderSubscriptionCard(subscription);
});
$('#subscriptionsContainer').html(html);
},
error: function() {
$('#subscriptionsContainer').html(`
<div class="alert alert-danger">
<i class="fa fa-exclamation-triangle"></i>
<strong><?php echo __('Error'); ?>:</strong> <?php echo __('Failed to load subscriptions'); ?>
</div>
`);
}
});
}
function renderSubscriptionCard(subscription) {
const status = subscription.currentStatus ? subscription.currentStatus.toLowerCase() : subscription.status.toLowerCase();
const displayStatus = subscription.currentStatus || subscription.status;
const isActive = subscription.isActive || (subscription.status && subscription.status.toLowerCase() === 'active');
let badgeClass = '';
switch(status) {
case 'active':
badgeClass = 'label-success';
break;
case 'suspended':
badgeClass = 'label-warning';
break;
case 'canceled':
case 'expired':
badgeClass = 'label-danger';
break;
default:
badgeClass = 'label-default';
}
return `
<div class="well">
<div class="row">
<div class="col-md-8">
<h4 class="media-heading">
<i class="fa fa-file-text-o"></i>
${subscription.name || 'Subscription'}
<span class="label ${badgeClass}">
${displayStatus}
</span>
</h4>
<div class="row" style="margin-top: 15px;">
<div class="col-sm-6">
<p><strong><i class="fa fa-tag"></i> <?php echo __('Subscription ID'); ?>:</strong><br>
${subscription.subscriptionId}</p>
</div>
<div class="col-sm-6">
<p><strong><i class="fa fa-dollar"></i> <?php echo __('Amount'); ?>:</strong><br>
$${parseFloat(subscription.amount).toFixed(2)}</p>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<p><strong><i class="fa fa-clock-o"></i> <?php echo __('Billing Cycle'); ?>:</strong><br>
Every ${subscription.interval.length} ${subscription.interval.unit}</p>
</div>
${subscription.startDate ? `
<div class="col-sm-6">
<p><strong><i class="fa fa-calendar"></i> <?php echo __('Start Date'); ?>:</strong><br>
${subscription.startDate}</p>
</div>
` : ''}
</div>
${subscription.plans_id ? `
<div class="row">
<div class="col-sm-6">
<p><strong><i class="fa fa-list-alt"></i> <?php echo __('Plan ID'); ?>:</strong><br>
${subscription.plans_id}</p>
</div>
</div>
` : ''}
</div>
<div class="col-md-4 text-right">
${isActive ? `
<button type="button"
class="btn btn-danger btn-block"
onclick="cancelSubscription('${subscription.subscriptionId}')">
<i class="fa fa-times"></i> <?php echo __('Cancel'); ?>
</button>
` : ''}
</div>
</div>
</div>
`;
}
function cancelSubscription(subscriptionId) {
swal({
title: "<?php echo __('Are you sure?'); ?>",
text: "<?php echo __('This will cancel your subscription permanently. You will not be able to recover this action!'); ?>",
icon: "warning",
buttons: [
"<?php echo __('Cancel'); ?>",
"<?php echo __('Yes, cancel subscription'); ?>"
],
dangerMode: true,
}).then(function(willCancel) {
if (willCancel) {
modal.showPleaseWait();
$.ajax({
url: webSiteRootURL + 'plugin/AuthorizeNet/cancelSubscription.json.php',
type: 'POST',
data: {
subscriptionId: subscriptionId
},
dataType: 'json',
success: function(response) {
modal.hidePleaseWait();
if (response.error) {
swal("<?php echo __('Error'); ?>", response.msg, "error");
} else {
swal("<?php echo __('Success'); ?>", "<?php echo __('Subscription canceled successfully'); ?>", "success")
.then(function() {
<?php if (!empty($subscription)): ?>
location.reload();
<?php else: ?>
loadSubscriptions();
<?php endif; ?>
});
}
},
error: function() {
modal.hidePleaseWait();
swal("<?php echo __('Error'); ?>", "<?php echo __('Failed to cancel subscription'); ?>", "error");
}
});
}
});
}
function refreshSubscriptionStatus(subscriptionId) {
modal.showPleaseWait();
$.ajax({
url: webSiteRootURL + 'plugin/AuthorizeNet/getSubscriptionStatus.json.php',
type: 'GET',
data: {
subscriptionId: subscriptionId
},
dataType: 'json',
success: function(response) {
modal.hidePleaseWait();
if (response.error) {
avideoAlert("<?php echo __('Error'); ?>", response.msg, "error");
} else {
avideoToast("<?php echo __('Status refreshed successfully'); ?>");
location.reload();
}
},
error: function() {
modal.hidePleaseWait();
avideoAlert("<?php echo __('Error'); ?>", "<?php echo __('Failed to refresh status'); ?>", "error");
}
});
}
function viewSubscriptionDetails(subscriptionId) {
modal.showPleaseWait();
$.ajax({
url: webSiteRootURL + 'plugin/AuthorizeNet/getSubscriptionDetails.json.php',
type: 'GET',
data: { subscriptionId: subscriptionId },
dataType: 'json',
success: function(response) {
modal.hidePleaseWait();
if (response.error) {
avideoAlert("<?php echo __('Error'); ?>", response.msg, "error");
return;
}
const subscription = response.subscription;
const modalContent = `
<div class="modal fade" id="subscriptionDetailsModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">
<i class="fa fa-file-text-o"></i> <?php echo __('Subscription Details'); ?>
</h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-sm-6">
<h5><i class="fa fa-info-circle"></i> <?php echo __('Basic Information'); ?></h5>
<table class="table table-striped">
<tr><td><strong><?php echo __('Subscription ID'); ?>:</strong></td><td>${subscription.subscriptionId}</td></tr>
<tr><td><strong><?php echo __('Name'); ?>:</strong></td><td>${subscription.name || 'N/A'}</td></tr>
<tr><td><strong><?php echo __('Status'); ?>:</strong></td><td><span class="label label-${getStatusClass(subscription.currentStatus || subscription.status)}">${subscription.currentStatus || subscription.status}</span></td></tr>
<tr><td><strong><?php echo __('Amount'); ?>:</strong></td><td>$${parseFloat(subscription.amount).toFixed(2)}</td></tr>
</table>
</div>
<div class="col-sm-6">
<h5><i class="fa fa-calendar"></i> <?php echo __('Billing Information'); ?></h5>
<table class="table table-striped">
<tr><td><strong><?php echo __('Billing Cycle'); ?>:</strong></td><td>Every ${subscription.interval.length} ${subscription.interval.unit}</td></tr>
<tr><td><strong><?php echo __('Start Date'); ?>:</strong></td><td>${subscription.startDate || 'N/A'}</td></tr>
<tr><td><strong><?php echo __('Next Payment'); ?>:</strong></td><td>${subscription.nextPaymentDate || 'N/A'}</td></tr>
<tr><td><strong><?php echo __('Total Occurrences'); ?>:</strong></td><td>${subscription.totalOccurrences || 'Unlimited'}</td></tr>
</table>
</div>
</div>
${subscription.paymentHistory ? `
<div class="row">
<div class="col-sm-12">
<h5><i class="fa fa-history"></i> <?php echo __('Payment History'); ?></h5>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th><?php echo __('Date'); ?></th>
<th><?php echo __('Amount'); ?></th>
<th><?php echo __('Status'); ?></th>
<th><?php echo __('Transaction ID'); ?></th>
</tr>
</thead>
<tbody>
${subscription.paymentHistory.map(payment => `
<tr>
<td>${payment.date}</td>
<td>$${parseFloat(payment.amount).toFixed(2)}</td>
<td><span class="label label-${payment.status === 'completed' ? 'success' : 'warning'}">${payment.status}</span></td>
<td>${payment.transactionId}</td>
</tr>
`).join('')}
</tbody>
</table>
</div>
</div>
</div>
` : ''}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">
<i class="fa fa-times"></i> <?php echo __('Close'); ?>
</button>
${subscription.isActive ? `
<button type="button" class="btn btn-danger" onclick="cancelSubscription('${subscription.subscriptionId}')">
<i class="fa fa-times"></i> <?php echo __('Cancel Subscription'); ?>
</button>
` : ''}
</div>
</div>
</div>
</div>
`;
$('body').append(modalContent);
$('#subscriptionDetailsModal').modal('show');
$('#subscriptionDetailsModal').on('hidden.bs.modal', function() {
$(this).remove();
});
},
error: function() {
modal.hidePleaseWait();
avideoAlert("<?php echo __('Error'); ?>", "<?php echo __('Failed to load subscription details'); ?>", "error");
}
});
}
function getStatusClass(status) {
switch(status.toLowerCase()) {
case 'active': return 'success';
case 'suspended': return 'warning';
case 'canceled':
case 'expired': return 'danger';
default: return 'default';
}
}
</script>
<?php
$_page->print();
?>

View file

@ -0,0 +1,67 @@
<?php
use Google\Service\ServiceControl\Auth;
require_once __DIR__ . '/../../videos/configuration.php';
header('Content-Type: application/json');
if(!User::isLogged()){
forbiddenPage('You must be logged out to access this endpoint');
}
try {
$obj = AVideoPlugin::getDataObject('AuthorizeNet');
$users_id = User::getId();
// ========== Validate payment amount ==========
if (!empty($_REQUEST['plans_id']) && AVideoPlugin::isEnabledByName('Subscription')) {
$sp = new SubscriptionPlansTable($_REQUEST['plans_id']);
$amount = $sp->getPrice();
}
if(empty($amount)){
$amount = isset($_REQUEST['amount']) ? floatval($_REQUEST['amount']) : 0;
}
if ($amount <= 0) {
echo json_encode(['error' => true, 'msg' => 'Invalid amount', 'line' => __LINE__]);
exit;
}
// ========== Add optional metadata ==========
$metadata = [];
$metadata['users_id'] = User::getId();
$metadata['plans_id'] = $_REQUEST['plans_id'] ?? 0;
AuthorizeNet::createWebhookIfNotExists();
// ========== Process payment via SDK using Accept opaque token + metadata ==========
$result = AuthorizeNet::generateHostedPaymentPage($amount, $metadata);
if (!empty($result['success'])) {
echo json_encode([
'error' => false,
'msg' => 'Payment created successfully',
'transactionId' => $result['transactionId'],
'line' => __LINE__
]);
exit;
}
// ========== Return error response if payment fails ==========
echo json_encode([
'error' => !isset($result['error']) || !empty($result['error']),
'msg' => $result['msg'] ?? '',
'result' => $result,
'line' => __LINE__,
'url' => $result['url'] ?? '',
'token' => $result['token'] ?? '',
]);
exit;
} catch (Exception $e) {
// ========== Return exception error ==========
echo json_encode([
'error' => true,
'msg' => $e->getMessage(),
'line' => __LINE__
]);
exit;
}

View file

@ -0,0 +1,19 @@
<?php
require_once __DIR__ . '/../../videos/configuration.php';
require_once 'AuthorizeNet.php';
header('Content-Type: application/json');
try {
$users_id = User::getId();
$result = AuthorizeNet::generateManageProfileToken($users_id);
echo json_encode($result);
exit;
} catch (Exception $e) {
echo json_encode([
'error' => true,
'msg' => $e->getMessage(),
'line' => __LINE__
]);
exit;
}

View file

@ -0,0 +1,78 @@
<?php
require_once __DIR__ . '/../../videos/configuration.php';
header('Content-Type: application/json');
$obj = new stdClass();
$obj->error = true;
$obj->msg = "";
try {
// Check if user is logged in
if (!User::isLogged()) {
$obj->msg = "You must be logged in to check subscription status";
die(json_encode($obj));
}
// Check if AuthorizeNet plugin is enabled
$plugin = AVideoPlugin::loadPluginIfEnabled('AuthorizeNet');
if (empty($plugin)) {
$obj->msg = "AuthorizeNet plugin is disabled";
die(json_encode($obj));
}
// Get subscription ID from GET data
$subscriptionId = $_GET['subscriptionId'] ?? '';
if (empty($subscriptionId)) {
$obj->msg = "Missing subscription ID";
die(json_encode($obj));
}
// Verify ownership (similar to cancel endpoint)
$users_id = User::getId();
$customerProfileId = AuthorizeNet::getOrCreateCustomerProfile($users_id);
if (empty($customerProfileId)) {
$obj->msg = "Customer profile not found";
die(json_encode($obj));
}
// Get subscription with current status
$subscriptionResult = AuthorizeNet::getSubscriptionWithCurrentStatus($subscriptionId);
if ($subscriptionResult['error']) {
$obj->msg = $subscriptionResult['msg'];
die(json_encode($obj));
}
// Verify ownership
$userSubscriptions = AuthorizeNet::getUserActiveSubscriptions($users_id);
$subscriptionFound = false;
if (!$userSubscriptions['error']) {
foreach ($userSubscriptions['subscriptions'] as $sub) {
if ($sub['subscriptionId'] === $subscriptionId) {
$subscriptionFound = true;
break;
}
}
}
if (!$subscriptionFound) {
$obj->msg = "Subscription not found or does not belong to current user";
die(json_encode($obj));
}
// Success response
$obj->error = false;
$obj->subscription = $subscriptionResult['subscription'];
$obj->status = $subscriptionResult['subscription']['currentStatus'];
$obj->isActive = $subscriptionResult['subscription']['isActive'];
} catch (Exception $e) {
$obj->msg = "An error occurred: " . $e->getMessage();
_error_log("[AuthorizeNet] Error in getSubscriptionStatus.json.php: " . $e->getMessage());
}
echo json_encode($obj);
?>

View file

@ -0,0 +1,72 @@
<?php
require_once __DIR__ . '/../../videos/configuration.php';
header('Content-Type: application/json');
$obj = new stdClass();
$obj->error = true;
$obj->msg = "";
$obj->subscriptions = [];
try {
// Check if user is logged in
if (!User::isLogged()) {
$obj->msg = "You must be logged in to view subscriptions";
die(json_encode($obj));
}
// Check if AuthorizeNet plugin is enabled
$plugin = AVideoPlugin::loadPluginIfEnabled('AuthorizeNet');
if (empty($plugin)) {
$obj->msg = "AuthorizeNet plugin is disabled";
die(json_encode($obj));
}
$users_id = User::getId();
// Get customer profile
$customerProfileId = AuthorizeNet::getOrCreateCustomerProfile($users_id);
if (empty($customerProfileId)) {
$obj->msg = "Customer profile not found";
die(json_encode($obj));
}
// Get all subscriptions for this customer from Authorize.Net API
$subscriptionsResult = AuthorizeNet::getCustomerSubscriptions($customerProfileId);
if ($subscriptionsResult['error']) {
$obj->msg = $subscriptionsResult['msg'];
die(json_encode($obj));
}
$subscriptionsWithStatus = [];
// Get current status for each subscription
foreach ($subscriptionsResult['subscriptions'] as $subscription) {
$subscriptionId = $subscription['subscriptionId'];
// Get detailed subscription info with current status
$detailsResult = AuthorizeNet::getSubscriptionWithCurrentStatus($subscriptionId);
if (!$detailsResult['error'] && !empty($detailsResult['subscription'])) {
$subscriptionsWithStatus[] = $detailsResult['subscription'];
}
}
// Sort subscriptions by creation date (newest first)
usort($subscriptionsWithStatus, function($a, $b) {
return $b['subscriptionId'] - $a['subscriptionId'];
});
// Success response
$obj->error = false;
$obj->subscriptions = $subscriptionsWithStatus;
$obj->total = count($subscriptionsWithStatus);
} catch (Exception $e) {
$obj->msg = "An error occurred: " . $e->getMessage();
_error_log("[AuthorizeNet] Error in getSubscriptions.json.php: " . $e->getMessage());
}
echo json_encode($obj);
?>

View file

@ -0,0 +1,22 @@
CREATE TABLE IF NOT EXISTS `anet_webhook_log` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`uniq_key` VARCHAR(120) NOT NULL,
`event_type` VARCHAR(120) NOT NULL,
`trans_id` VARCHAR(45) NULL,
`payload_json` JSON NOT NULL,
`processed` TINYINT(1) NOT NULL DEFAULT 0,
`error_text` TEXT NULL,
`status` VARCHAR(45) NULL,
`created_php_time` BIGINT NULL,
`modified_php_time` BIGINT NULL,
`users_id` INT(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `uniq_key_UNIQUE` (`uniq_key` ASC),
INDEX `fk_anet_webhook_log_users1_idx` (`users_id` ASC),
INDEX `event_type_index` (`event_type` ASC),
CONSTRAINT `fk_anet_webhook_log_users1`
FOREIGN KEY (`users_id`)
REFERENCES `users` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;

View file

@ -0,0 +1,29 @@
<?php
require_once __DIR__ . '/../../videos/configuration.php';
header('Content-Type: application/json');
$plugin = new AuthorizeNet();
$amount = isset($_POST['amount']) ? floatval($_POST['amount']) : 0;
$userData = isset($_POST['userData']) ? $_POST['userData'] : [];
if ($amount <= 0) {
echo json_encode(['error' => 'Invalid amount']);
exit;
}
// TODO: Implement payment logic using Authorize.Net API
// Example: Call Authorize.Net API here
// $result = $plugin->chargePayment($amount, $userData);
// Simulate payment success for now
$paymentSuccess = true;
$users_id = @User::getId();
if ($paymentSuccess && !empty($users_id)) {
// Add funds to wallet
$walletPlugin = AVideoPlugin::loadPluginIfEnabled("YPTWallet");
if ($walletPlugin) {
$walletPlugin->addBalance($users_id, $amount, 'Authorize.Net one-time payment');
echo json_encode(['success' => true, 'result' => 'Payment processed and wallet updated']);
exit;
}
}
echo json_encode(['error' => 'Payment failed or user not logged in']);

View file

@ -0,0 +1,140 @@
<?php
require_once __DIR__ . '/../../videos/configuration.php';
require_once $global['systemRootPath'] . 'plugin/AuthorizeNet/AuthorizeNet.php';
$global['bypassSameDomainCheck'] = 1;
$rawBody = file_get_contents('php://input');
$headers = getallheaders();
// 1) Parse + signature
$parsed = AuthorizeNet::parseWebhookRequest($rawBody, $headers);
if (!empty($parsed['error'])) {
_error_log('[Authorize.Net webhook] ' . $parsed['msg']);
http_response_code(200);
echo $parsed['msg'] ?? 'ignored';
exit;
}
_error_log('[Authorize.Net webhook] Event: ' . $parsed['eventType']);
_error_log('[Authorize.Net webhook] uniq_key: ' . $parsed['uniq_key']);
// 2) Dedup
if (Anet_webhook_log::alreadyProcessed($parsed['uniq_key'])) {
_error_log('[Authorize.Net webhook] Duplicate ignored');
http_response_code(200);
echo 'duplicate';
exit;
}
// 3) Fetch txn (fallback/confirm)
$txnInfo = AuthorizeNet::getTransactionDetails($parsed['transactionId']);
// 4) Block only if both invalid signature AND no valid txn info
if (!$parsed['signatureValid'] && (empty($txnInfo) || !empty($txnInfo['error']))) {
_error_log('[Authorize.Net webhook] Bad signature and could not confirm transaction');
http_response_code(401);
echo 'invalid signature';
exit;
}
// 5) Analyze payload + raw txn
$analysis = AuthorizeNet::analyzeTransactionFromWebhook($parsed['payload'], $txnInfo['raw'] ?? null);
// Fill missing basics from txnInfo if needed
if (!$analysis['users_id'] && !empty($txnInfo['users_id'])) {
$analysis['users_id'] = (int)$txnInfo['users_id'];
}
if (!$analysis['amount'] && isset($txnInfo['amount'])) {
$analysis['amount'] = (float)$txnInfo['amount'];
}
if (!$analysis['currency'] && !empty($txnInfo['currency'])) {
$analysis['currency'] = $txnInfo['currency'];
}
if (!$analysis['isApproved'] && !empty($txnInfo['isApproved'])) {
$analysis['isApproved'] = (bool)$txnInfo['isApproved'];
}
if (!$analysis['plans_id'] && !empty($txnInfo['plans_id'])) {
$analysis['plans_id'] = (int)$txnInfo['plans_id'];
}
_error_log('[Authorize.Net webhook] Analysis: ' . json_encode($analysis));
$result = AuthorizeNet::processSinglePayment(
$analysis['users_id'],
(float)$analysis['amount'],
$parsed['uniq_key'],
$parsed['eventType'],
$parsed['payload'],
!empty($analysis['plans_id'])? "Authorize.Net subscription charge plan [{$analysis['plans_id']}]" : 'Authorize.Net one-time payment'
);
if (!empty($result['error'])) {
_error_log('[Authorize.Net webhook] Processing error: ' . $result['msg']);
http_response_code(500);
echo json_encode($result);
exit;
}
// 8) Create subscription if needed
$subscriptionResult = null;
if (!empty($analysis['plans_id'])) {
_error_log('[Authorize.Net webhook] Creating subscription for plans_id: ' . $analysis['plans_id']);
// Check if user already has an active subscription for this plan
$existingCheck = AuthorizeNet::checkUserActiveSubscriptions(
$analysis['users_id'],
$analysis['plans_id']
);
if (!$existingCheck['error'] && $existingCheck['hasActivePlanSubscription']) {
_error_log('[Authorize.Net webhook] User already has active subscription for plan: ' . $analysis['plans_id']);
$subscriptionResult = [
'error' => false,
'subscriptionId' => 'existing',
'msg' => 'User already has active subscription for this plan',
'existingSubscriptions' => $existingCheck['activeSubscriptions']
];
} else {
$sp = new SubscriptionPlansTable($analysis['plans_id']);
$subscription_name = $sp->getName() ?? 'Subscription';
// Proceed with creating new subscription
$subscriptionMetadata = [
'users_id' => (int)$analysis['users_id'],
'plans_id' => (int)$analysis['plans_id'],
'subscription_name' => $subscription_name,
'initial_payment_id' => $parsed['transactionId']
];
$interval = (int)($sp->getHow_many_days() ?? 30);
$intervalUnit = 'days';
$subscriptionResult = AuthorizeNet::createSubscription(
$analysis['users_id'],
$analysis['amount'],
$subscriptionMetadata,
$interval,
$intervalUnit
);
Subscription::renew($analysis['users_id'], $analysis['plans_id'], SubscriptionTable::$gatway_authorize, $subscriptionResult['subscriptionId'], $subscriptionResult);
if (!empty($subscriptionResult['error'])) {
_error_log('[Authorize.Net webhook] Subscription creation failed: ' . $subscriptionResult['msg']);
// Don't fail the entire webhook - the payment was processed successfully
} else {
_error_log('[Authorize.Net webhook] Subscription created: ' . $subscriptionResult['subscriptionId']);
}
}
}
// 9) Return success response
echo json_encode([
'success' => true,
'users_id' => $analysis['users_id'],
'subscription' => $analysis['isASubscription'],
'subscriptionId' => $analysis['subscriptionId'] ?? ($subscriptionResult['subscriptionId'] ?? null),
'newSubscription' => $shouldCreateSubscription,
'subscriptionCreated' => !empty($subscriptionResult) && empty($subscriptionResult['error']),
'sigValid' => $parsed['signatureValid'],
'logId' => $result['logId'] ?? null
]);

View file

@ -0,0 +1,38 @@
<?php
global $global;
require_once $global['systemRootPath'] . 'plugin/YPTWallet/YPTWalletPlugin.php';
require_once $global['systemRootPath'] . 'plugin/AuthorizeNet/AuthorizeNet.php';
class YPTWalletAuthorizeNet extends YPTWalletPlugin {
public function getAprovalLink() {
// Implement logic to generate Authorize.Net payment approval link if needed
return false;
}
public function getAprovalButton() {
global $global;
include $global['systemRootPath'].'plugin/YPTWallet/plugins/YPTWalletAuthorizeNet/confirmButton.php';
}
public function getRecurrentAprovalButton() {
global $global;
include $global['systemRootPath'].'plugin/YPTWallet/plugins/YPTWalletAuthorizeNet/confirmRecurrentButton.php';
}
public function getRecurrentAprovalButtonV2($total = '1.00', $currency = "USD", $frequency = "Month", $interval = 1, $name = '', $json = '', $addFunds_Success='', $trialDays = 0) {
$total = floatval($total);
if(empty($total)){
return '';
}
global $global;
include $global['systemRootPath'].'plugin/YPTWallet/plugins/YPTWalletAuthorizeNet/confirmRecurrentButtonV2.php';
}
public function getEmptyDataObject() {
$obj = new stdClass();
// Add custom config if needed
return $obj;
}
}

View file

@ -0,0 +1,62 @@
<?php
// Authorize.Net Accept Hosted payment & profile management buttons for YPTWallet integration
?>
<div class="btn-group" role="group" aria-label="Authorize.Net Actions">
<button class="btn btn-primary" onclick="startAuthorizeNetAcceptHosted()">
<i class="fas fa-credit-card"></i> Pay with Authorize.Net
</button>
<button class="btn btn-info" onclick="openAuthorizeNetProfileManager()">
<i class="fas fa-user-cog"></i>
</button>
</div>
<script>
function startAuthorizeNetAcceptHosted() {
modal.showPleaseWait();
var amount = $('#value<?php echo @$_GET['plans_id']; ?>').val();
if (!amount || isNaN(amount) || amount <= 0) {
avideoAlertError('Invalid amount');
return;
}
fetch(webSiteRootURL + 'plugin/AuthorizeNet/getAcceptHostedToken.json.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'amount=' + encodeURIComponent(amount)
})
.then(response => response.json())
.then(data => {
modal.hidePleaseWait();
if (!data.error && data.token && data.url) {
const strWindowFeatures = "directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,resizable=no,height=650,width=1000";
openWindowWithPost(data.url, 'Authorize.Net' ,{'token': data.token}, strWindowFeatures);
} else {
avideoAlertError('Payment error: ' + (data.msg || 'Could not get payment token'));
}
})
.catch(err => {
modal.hidePleaseWait();
avideoAlertError('Payment request failed: ' + err);
});
}
function openAuthorizeNetProfileManager() {
modal.showPleaseWait();
fetch(webSiteRootURL + 'plugin/AuthorizeNet/getProfileManager.json.php')
.then(response => response.json())
.then(data => {
modal.hidePleaseWait();
if (!data.error && data.token && data.url) {
avideoDialogWithPost(data.url, {'token': data.token});
} else {
avideoAlertError('Profile error: ' + (data.msg || 'Could not get profile token'));
}
})
.catch(err => {
modal.hidePleaseWait();
avideoAlertError('Profile request failed: ' + err);
});
}
</script>

View file

@ -0,0 +1,82 @@
<?php
$uniqid = uniqid('anetSub_');
?>
<div class="btn-group" role="group" aria-label="Authorize.Net Actions">
<button type="button"
class="btn btn-primary"
id="AuthorizeNetRecurringBtn<?php echo $uniqid; ?>">
<i class="fas fa-sync-alt"></i> <?php echo __('Subscribe with Authorize.Net'); ?>
</button>
<button class="btn btn-info" onclick="openAuthorizeNetProfileManager()">
<i class="fas fa-user-cog"></i>
</button>
</div>
<script>
$(function() {
$('#AuthorizeNetRecurringBtn<?php echo $uniqid; ?>').on('click', function(e) {
e.preventDefault();
modal.showPleaseWait();
$.ajax({
url: webSiteRootURL + 'plugin/AuthorizeNet/getAcceptHostedToken.json.php',
type: 'POST',
data: {
"plans_id": "<?php echo @$_GET['plans_id']; ?>"
},
success: function(resp) {
modal.hidePleaseWait();
if (resp.error) {
avideoAlertError(resp.msg || 'Unknown error');
return;
}
// Show payment details and redirect to Accept Hosted
if (resp.token && resp.url) {
const strWindowFeatures = "directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,resizable=no,height=650,width=1000";
openWindowWithPost(resp.url, 'Authorize.Net', {
'token': resp.token
}, strWindowFeatures);
return;
}
// Fallback
avideoAlertSuccess(resp.msg || "<?php echo __('Request processed successfully'); ?>");
},
error: function(xhr, status, error) {
modal.hidePleaseWait();
console.error('XHR Error:', xhr, status, error);
try {
var errorResp = JSON.parse(xhr.responseText);
avideoAlertError(errorResp.msg || 'Connection error');
} catch (e) {
avideoAlertError('Connection error: ' + (error || 'Unknown error'));
}
}
});
});
});
function openAuthorizeNetProfileManager() {
modal.showPleaseWait();
fetch(webSiteRootURL + 'plugin/AuthorizeNet/getProfileManager.json.php')
.then(response => response.json())
.then(data => {
modal.hidePleaseWait();
if (!data.error && data.token && data.url) {
avideoDialogWithPost(data.url, {
'token': data.token
});
} else {
avideoAlertError('Profile error: ' + (data.msg || 'Could not get profile token'));
}
})
.catch(err => {
modal.hidePleaseWait();
avideoAlertError('Profile request failed: ' + err);
});
}
</script>