Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
A
aisbf
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexlab
aisbf
Commits
68fd5fd4
Commit
68fd5fd4
authored
Apr 16, 2026
by
Your Name
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Initial payment method implementation
parent
0fd682cb
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
109 additions
and
100 deletions
+109
-100
setup.py
setup.py
+1
-1
aisbf-oauth2-extension.zip
static/aisbf-oauth2-extension.zip
+0
-0
base.html
templates/base.html
+1
-0
billing.html
templates/dashboard/billing.html
+96
-20
subscription.html
templates/dashboard/subscription.html
+11
-79
No files found.
setup.py
View file @
68fd5fd4
...
...
@@ -49,7 +49,7 @@ class InstallCommand(_install):
setup
(
name
=
"aisbf"
,
version
=
"0.99.2
6
"
,
version
=
"0.99.2
7
"
,
author
=
"AISBF Contributors"
,
author_email
=
"stefy@nexlab.net"
,
description
=
"AISBF - AI Service Broker Framework || AI Should Be Free - A modular proxy server for managing multiple AI provider integrations"
,
...
...
static/aisbf-oauth2-extension.zip
View file @
68fd5fd4
No preview for this file type
templates/base.html
View file @
68fd5fd4
...
...
@@ -21,6 +21,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0"
>
<title>
{% block title %}AISBF Dashboard{% endblock %}
</title>
<link
rel=
"icon"
type=
"image/png"
href=
"/favicon.ico"
>
<link
rel=
"stylesheet"
href=
"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
>
<style>
*
{
margin
:
0
;
padding
:
0
;
box-sizing
:
border-box
;
}
body
{
font-family
:
-apple-system
,
BlinkMacSystemFont
,
'Segoe UI'
,
Roboto
,
Oxygen
,
Ubuntu
,
Cantarell
,
sans-serif
;
background
:
#1a1a2e
;
color
:
#e0e0e0
;
}
...
...
templates/dashboard/billing.html
View file @
68fd5fd4
...
...
@@ -20,7 +20,7 @@
{% if payment_methods and payment_methods|length > 0 %}
<div
style=
"display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px;"
>
{% for method in payment_methods %}
<div
class=
"payment-method-card {% if method.is_default %}default{% endif %}"
>
<div
class=
"payment-method-card {% if method.is_default %}default{% endif %}"
style=
"background: #1a1a2e; border: 1px solid #0f3460; border-radius: 8px; padding: 15px; margin-bottom: 10px;"
>
<div
style=
"display: flex; align-items: center; margin-bottom: 10px;"
>
<div
style=
"margin-right: 15px;"
>
{% if method.type == 'paypal' %}
...
...
@@ -54,9 +54,9 @@
</div>
<div
style=
"display: flex; flex-direction: column; gap: 5px;"
>
{% if not method.is_default %}
<button
class=
"btn btn-secondary set-default-btn"
data-method-id=
"{{ method.id }}"
style=
"
padding: 5px 10px; font-size: 12px
;"
>
Set Default
</button>
<button
class=
"btn btn-secondary set-default-btn"
data-method-id=
"{{ method.id }}"
style=
"
background: #17a2b8; border: none; color: white; padding: 8px 12px; border-radius: 4px; cursor: pointer; font-size: 12px; display: inline-block !important; visibility: visible !important
;"
>
Set Default
</button>
{% endif %}
<button
class=
"btn btn-secondary delete-method-btn"
data-method-id=
"{{ method.id }}"
data-method-type=
"{{ method.type }}"
style=
"background: #dc3545;
padding: 5px 10px; font-size: 12px;
"
>
<button
class=
"btn btn-secondary delete-method-btn"
data-method-id=
"{{ method.id }}"
data-method-type=
"{{ method.type }}"
style=
"background: #dc3545;
border: none; color: white; padding: 8px 12px; border-radius: 4px; cursor: pointer; font-size: 14px; display: inline-block !important; visibility: visible !important; width: auto; min-width: 40px;"
title=
"Delete payment method
"
>
<i
class=
"fas fa-trash"
></i>
</button>
</div>
...
...
@@ -197,9 +197,7 @@
</div>
{% endblock %}
{% block extra_css %}
{% block extra_js %}
<style>
/* Payment Method Cards */
.payment-method-card
{
...
...
@@ -253,43 +251,107 @@
.form-group
input
[
type
=
"checkbox"
]
{
margin-right
:
5px
;
}
/* Payment method buttons styling */
.delete-method-btn
,
.set-default-btn
{
display
:
inline-flex
!important
;
align-items
:
center
!important
;
justify-content
:
center
!important
;
visibility
:
visible
!important
;
opacity
:
1
!important
;
min-height
:
32px
!important
;
min-width
:
32px
!important
;
}
.delete-method-btn
:hover
{
background
:
#c82333
!important
;
}
.set-default-btn
:hover
{
background
:
#0d8aa8
!important
;
}
/* Ensure Font Awesome icons are visible */
.fas
,
.fab
,
.far
{
font-family
:
"Font Awesome 6 Free"
,
"Font Awesome 6 Brands"
!important
;
font-weight
:
900
!important
;
display
:
inline-block
!important
;
}
</style>
<script>
document
.
addEventListener
(
'DOMContentLoaded'
,
function
()
{
console
.
log
(
'Billing page JavaScript loaded'
);
// Delete payment method
document
.
querySelectorAll
(
'.delete-method-btn'
).
forEach
(
button
=>
{
button
.
addEventListener
(
'click'
,
function
()
{
const
deleteButtons
=
document
.
querySelectorAll
(
'.delete-method-btn'
);
console
.
log
(
'Found delete buttons:'
,
deleteButtons
.
length
);
deleteButtons
.
forEach
(
button
=>
{
button
.
addEventListener
(
'click'
,
function
(
event
)
{
event
.
preventDefault
();
console
.
log
(
'Delete button clicked'
);
const
methodId
=
this
.
dataset
.
methodId
;
const
methodType
=
this
.
dataset
.
methodType
;
if
(
confirm
(
`Are you sure you want to delete this
${
methodType
}
payment method?`
))
{
console
.
log
(
'Method ID:'
,
methodId
,
'Method Type:'
,
methodType
);
if
(
!
methodId
)
{
console
.
error
(
'No method ID found'
);
alert
(
'Error: Payment method ID not found'
);
return
;
}
if
(
confirm
(
`Are you sure you want to delete this
${
methodType
||
'payment'
}
method?`
))
{
console
.
log
(
'Sending DELETE request to:'
,
`/dashboard/billing/payment-methods/
${
methodId
}
`
);
fetch
(
`/dashboard/billing/payment-methods/
${
methodId
}
`
,
{
method
:
'DELETE'
,
headers
:
{
'Content-Type'
:
'application/json'
,
}
})
.
then
(
response
=>
response
.
json
())
.
then
(
response
=>
{
console
.
log
(
'Response status:'
,
response
.
status
);
return
response
.
json
();
})
.
then
(
data
=>
{
console
.
log
(
'Response data:'
,
data
);
if
(
data
.
success
)
{
alert
(
'Payment method deleted successfully'
);
window
.
location
.
reload
();
}
else
{
alert
(
'Error: '
+
(
data
.
error
||
'Failed to delete payment method'
));
}
})
.
catch
(
error
=>
{
console
.
error
(
'
E
rror:'
,
error
);
alert
(
'An error occurred while deleting the payment method
'
);
console
.
error
(
'
Fetch e
rror:'
,
error
);
alert
(
'An error occurred while deleting the payment method
: '
+
error
.
message
);
});
}
});
});
// Set default payment method
document
.
querySelectorAll
(
'.set-default-btn'
).
forEach
(
button
=>
{
button
.
addEventListener
(
'click'
,
function
()
{
const
setDefaultButtons
=
document
.
querySelectorAll
(
'.set-default-btn'
);
console
.
log
(
'Found set default buttons:'
,
setDefaultButtons
.
length
);
setDefaultButtons
.
forEach
(
button
=>
{
button
.
addEventListener
(
'click'
,
function
(
event
)
{
event
.
preventDefault
();
console
.
log
(
'Set default button clicked'
);
const
methodId
=
this
.
dataset
.
methodId
;
console
.
log
(
'Method ID:'
,
methodId
);
if
(
!
methodId
)
{
console
.
error
(
'No method ID found'
);
alert
(
'Error: Payment method ID not found'
);
return
;
}
console
.
log
(
'Sending POST request to:'
,
`/dashboard/billing/payment-methods/
${
methodId
}
/set-default`
);
fetch
(
`/dashboard/billing/payment-methods/
${
methodId
}
/set-default`
,
{
method
:
'POST'
,
...
...
@@ -297,19 +359,33 @@ document.addEventListener('DOMContentLoaded', function() {
'Content-Type'
:
'application/json'
,
}
})
.
then
(
response
=>
response
.
json
())
.
then
(
response
=>
{
console
.
log
(
'Response status:'
,
response
.
status
);
return
response
.
json
();
})
.
then
(
data
=>
{
console
.
log
(
'Response data:'
,
data
);
if
(
data
.
success
)
{
alert
(
'Payment method set as default'
);
window
.
location
.
reload
();
}
else
{
alert
(
'Error: '
+
(
data
.
error
||
'Failed to set default payment method'
));
}
})
.
catch
(
error
=>
{
console
.
error
(
'Error:'
,
error
);
alert
(
'An error occurred while setting default payment method'
);
console
.
error
(
'Fetch error:'
,
error
);
alert
(
'An error occurred while setting default payment method: '
+
error
.
message
);
});
});
});
// Check if buttons have data attributes
deleteButtons
.
forEach
((
btn
,
index
)
=>
{
console
.
log
(
`Delete button
${
index
}
: methodId=
${
btn
.
dataset
.
methodId
}
, methodType=
${
btn
.
dataset
.
methodType
}
`
);
});
setDefaultButtons
.
forEach
((
btn
,
index
)
=>
{
console
.
log
(
`Set default button
${
index
}
: methodId=
${
btn
.
dataset
.
methodId
}
`
);
});
});
</script>
...
...
templates/dashboard/subscription.html
View file @
68fd5fd4
...
...
@@ -165,87 +165,19 @@
</div>
</div>
<!-- Add Payment Method Modal -->
<div
class=
"modal fade"
id=
"addPaymentMethodModal"
tabindex=
"-1"
>
<div
class=
"modal-dialog"
>
<div
class=
"modal-content"
>
<div
class=
"modal-header"
>
<h5
class=
"modal-title"
>
Add Payment Method
</h5>
<button
type=
"button"
class=
"btn-close"
data-bs-dismiss=
"modal"
></button>
</div>
<div
class=
"modal-body"
>
<ul
class=
"nav nav-pills mb-3 justify-content-center"
id=
"paymentTabs"
>
{% if 'stripe' in enabled_gateways %}
<li
class=
"nav-item"
>
<button
class=
"nav-link active"
data-bs-toggle=
"pill"
data-bs-target=
"#stripeTab"
>
<i
class=
"fab fa-cc-stripe me-2"
></i>
Credit Card
</button>
</li>
{% endif %}
{% if 'paypal' in enabled_gateways %}
<li
class=
"nav-item"
>
<button
class=
"nav-link {% if 'stripe' not in enabled_gateways %}active{% endif %}"
data-bs-toggle=
"pill"
data-bs-target=
"#paypalTab"
>
<i
class=
"fab fa-paypal me-2"
></i>
PayPal
</button>
</li>
{% endif %}
{% if 'bitcoin' in enabled_gateways or 'eth' in enabled_gateways or 'usdt' in enabled_gateways or 'usdc' in enabled_gateways %}
<li
class=
"nav-item"
>
<button
class=
"nav-link"
data-bs-toggle=
"pill"
data-bs-target=
"#cryptoTab"
>
<i
class=
"fab fa-bitcoin me-2"
></i>
Crypto
</button>
</li>
{% endif %}
</ul>
<div
class=
"tab-content"
>
<div
class=
"tab-pane fade show active"
id=
"stripeTab"
>
<div
class=
"text-center py-4"
>
<i
class=
"fab fa-cc-stripe fa-3x mb-3 text-primary"
></i>
<p>
Secure credit card payment via Stripe
</p>
<button
class=
"btn btn-primary"
>
Connect with Stripe
</button>
</div>
</div>
<div
class=
"tab-pane fade"
id=
"paypalTab"
>
<div
class=
"text-center py-4"
>
<i
class=
"fab fa-paypal fa-3x mb-3 text-primary"
></i>
<p>
Pay with your PayPal account
</p>
<button
class=
"btn btn-primary"
>
Connect with PayPal
</button>
</div>
</div>
<div
class=
"tab-pane fade"
id=
"cryptoTab"
>
<div
class=
"text-center py-3"
>
<div
class=
"d-flex justify-content-center gap-3 mb-3"
>
{% if 'bitcoin' in enabled_gateways %}
<button
class=
"btn btn-outline-warning"
>
<i
class=
"fab fa-bitcoin me-2"
></i>
Bitcoin
</button>
{% endif %}
{% if 'eth' in enabled_gateways or 'ethereum' in enabled_gateways %}
<button
class=
"btn btn-outline-purple"
>
<i
class=
"fab fa-ethereum me-2"
></i>
Ethereum
</button>
{% endif %}
{% if 'usdt' in enabled_gateways %}
<button
class=
"btn btn-outline-success"
>
<i
class=
"fas fa-coins me-2"
></i>
USDT
</button>
{% endif %}
{% if 'usdc' in enabled_gateways %}
<button
class=
"btn btn-outline-info"
>
<i
class=
"fas fa-coins me-2"
></i>
USDC
</button>
{% endif %}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Add Payment Method Button (only shown when no payment methods exist) -->
{% if not payment_methods or payment_methods|length == 0 %}
<div
style=
"background: #16213e; border: 2px solid #f39c12; border-radius: 8px; padding: 20px; margin-bottom: 20px;"
>
<div
style=
"text-align: center;"
>
<i
class=
"fas fa-credit-card fa-3x mb-3"
style=
"color: #f39c12;"
></i>
<h3
style=
"margin: 0 0 15px 0; color: #f39c12;"
>
No Payment Methods
</h3>
<p
style=
"color: #a0a0a0; margin-bottom: 20px;"
>
Add a payment method to upgrade your plan and manage subscriptions
</p>
<a
href=
"{{ url_for(request, '/dashboard/billing') }}"
class=
"btn"
style=
"background: #f39c12; color: #1a1a2e;"
>
<i
class=
"fas fa-wallet me-2"
></i>
Go to Billing
&
Payment Methods
</a>
</div>
</div>
{% endif %}
{% endblock %}
{% block extra_css %}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment