Merge pull request #397 from pcoder/task/3580/expand_input_field_on_credit_card

This PR rearranges the components in the payment form. 

- We introduced a new field "Cardholder's Name" as part of the billing address. 
- The stripe input fields are mounted individually.
- The overlapping of date field in the mobile view of the confirm order page is fixed.
- We now have customized place holder texts and customized styles for the stripe input fields.

Task/3580/expand input field on credit card
This commit is contained in:
Pcoder 2017-07-17 20:12:22 +02:00 committed by GitHub
commit 4fa6e7ae4c
10 changed files with 1030 additions and 631 deletions

View file

@ -25,7 +25,13 @@
</div>
<hr>
<div class="row">
<div class="col-xs-6">
<div class="col-xs-12 col-sm-6 pull-right text-left">
<address>
<strong>{% trans "Date"%}:</strong><br>
<span id="order-created_at">{% now "Y-m-d H:i" %}</span><br><br>
</address>
</div>
<div class="col-xs-12 col-sm-6">
<address>
<h3><b>{% trans "Billed To:"%}</b></h3>
{% with request.session.billing_address_data as billing_address %}
@ -34,13 +40,6 @@
{% endwith %}
</address>
</div>
<div class="col-xs-6 text-right">
<address>
<strong>{% trans "Date"%}:</strong><br>
<span id="order-created_at">{% now "Y-m-d H:i" %}</span><br><br>
</address>
</div>
</div>
<div class="row">
<div class="col-xs-6">

File diff suppressed because it is too large Load diff

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-07-11 00:02+0530\n"
"POT-Creation-Date: 2017-07-17 00:53+0530\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -26,47 +26,47 @@ msgstr "Dein Account wurde noch nicht aktiviert."
msgid "Paste here your public key"
msgstr "Fügen Sie Ihren public key ein"
#: templates/hosting/base_short.html:68
#: templates/hosting/base_short.html:71
msgid "My Virtual Machines"
msgstr "Meine virtuellen Maschinen"
#: templates/hosting/base_short.html:73 templates/hosting/orders.html.py:12
#: templates/hosting/base_short.html:76 templates/hosting/orders.html.py:12
msgid "My Orders"
msgstr "Meine Bestellungen"
#: templates/hosting/base_short.html:82
#: templates/hosting/base_short.html:85
msgid "Keys"
msgstr "Schlüssel"
#: templates/hosting/base_short.html:87
#: templates/hosting/base_short.html:90
msgid "Notifications "
msgstr "Benachrichtigungen"
#: templates/hosting/base_short.html:90
#: templates/hosting/base_short.html:93
msgid "Logout"
msgstr "Abmelden"
#: templates/hosting/base_short.html:95
#: templates/hosting/base_short.html:98
msgid "How it works"
msgstr "So funktioniert es"
#: templates/hosting/base_short.html:98
#: templates/hosting/base_short.html:101
msgid "Your infrastructure"
msgstr "deine Infrastruktur"
#: templates/hosting/base_short.html:101
#: templates/hosting/base_short.html:104
msgid "Our inftrastructure"
msgstr "Unsere Infrastruktur"
#: templates/hosting/base_short.html:104
#: templates/hosting/base_short.html:107
msgid "Pricing"
msgstr "Preise"
#: templates/hosting/base_short.html:107
#: templates/hosting/base_short.html:110
msgid "Contact"
msgstr "Kontakt"
#: templates/hosting/base_short.html:110
#: templates/hosting/base_short.html:113
#: templates/hosting/confirm_reset_password.html:38
#: templates/hosting/login.html:17 templates/hosting/login.html.py:26
#: templates/hosting/reset_password.html:32 templates/hosting/signup.html:30
@ -289,23 +289,23 @@ msgstr "Bezahlmethode"
msgid "Order summary"
msgstr "Bestellungsübersicht"
#: templates/hosting/order_detail.html:65 templates/hosting/payment.html:17
#: templates/hosting/order_detail.html:65 templates/hosting/payment.html:13
#: templates/hosting/virtual_machine_detail.html:76
msgid "Cores"
msgstr "Prozessorkerne"
#: templates/hosting/order_detail.html:67 templates/hosting/payment.html:20
#: templates/hosting/order_detail.html:67 templates/hosting/payment.html:16
#: templates/hosting/virtual_machine_detail.html:82
msgid "Memory"
msgstr "Arbeitsspeicher"
#: templates/hosting/order_detail.html:69 templates/hosting/payment.html:23
#: templates/hosting/order_detail.html:69 templates/hosting/payment.html:19
msgid "Disk space"
msgstr "Festplattenkapazität"
#: templates/hosting/order_detail.html:71
#: templates/hosting/order_detail.html:71 templates/hosting/payment.html:41
msgid "Total"
msgstr ""
msgstr "Gesamt"
#: templates/hosting/order_detail.html:77
msgid "Finish Configuration"
@ -349,46 +349,98 @@ msgstr "Schliessen"
msgid "Delete"
msgstr "Löschen"
#: templates/hosting/payment.html:12
msgid "Billing Amount"
msgstr "Rechnungsbetrag"
#: templates/hosting/payment.html:10
msgid "Your Order"
msgstr "Deine Bestellung"
#: templates/hosting/payment.html:26
#: templates/hosting/payment.html:22
#: templates/hosting/virtual_machine_detail.html:98
msgid "Configuration"
msgstr "Konfiguration"
#: templates/hosting/payment.html:38
#: templates/hosting/payment.html:41
msgid "including VAT"
msgstr "inkl. Mehrwertsteuer"
#: templates/hosting/payment.html:55
msgid "Billing Address"
msgstr "Rechnungsadresse"
#: templates/hosting/payment.html:52
#: templates/hosting/payment.html:66
msgid "Credit Card"
msgstr "Kreditkarte"
#: templates/hosting/payment.html:56
#: templates/hosting/payment.html:71
msgid ""
"Please fill in your credit card information below. We are using <a href="
"\"https://stripe.com\" target=\"_blank\">Stripe</a> for payment and do not "
"store your information in our database."
"\n"
" Please fill in your credit card information "
"below. We are using <a\n"
" href=\"https://stripe.com\" target="
"\"_blank\">Stripe</a> for payment and do not store\n"
" your information in our database.\n"
" "
msgstr ""
"Bitte füll deine Kreditkarteninformationen unten aus. Wir nutzen <a href="
"\n"
"Bitte füll Deine Kreditkarteninformationen unten aus. Wir nutzen <a href="
"\"https://stripe.com\" target=\"_blank\">Stripe</a> für die Bezahlung und "
"speichern keine Informationen in unserer Datenbank."
#: templates/hosting/payment.html:71 templates/hosting/payment.html.py:96
#: templates/hosting/payment.html:90
msgid ""
"You are not making any payment yet. After submitting your card information, "
"you will be taken to the Confirm Order Page."
"\n"
" You are not making any payment yet. "
"After submitting your card\n"
" information, you will be taken to "
"the Confirm Order Page.\n"
" "
msgstr ""
"Es wird noch keine Bezahlung vorgenommen. Nach der Eingabe deiner "
"\n"
"Es wird noch keine Bezahlung vorgenommen. Nach der Eingabe Deiner "
"Kreditkateninformationen wirst du auf die Bestellbestätigungsseite "
"weitergeleitet."
#: templates/hosting/payment.html:76 templates/hosting/payment.html.py:100
#: templates/hosting/payment.html:101 templates/hosting/payment.html.py:143
msgid "Submit"
msgstr "Absenden"
#: templates/hosting/payment.html:113
msgid "Card Number"
msgstr "Kreditkartennummer"
#: templates/hosting/payment.html:117
msgid "Expiry Date"
msgstr "Ablaufdatum"
#: templates/hosting/payment.html:122
msgid "CVC"
msgstr ""
#: templates/hosting/payment.html:126
msgid "Card Type"
msgstr "Kartentyp"
#: templates/hosting/payment.html:135
msgid ""
"\n"
" You are not making any payment "
"yet. After submitting your card\n"
" information, you will be taken "
"to the Confirm Order Page.\n"
" "
msgstr ""
"\n"
"Es wird noch keine Bezahlung vorgenommen. Nach der Eingabe Deiner "
"Kreditkateninformationen wirst du auf die Bestellbestätigungsseite "
"weitergeleitet."
#: templates/hosting/payment.html:178
msgid "Processing"
msgstr "Weiter"
#: templates/hosting/payment.html:179
msgid "Enter your credit card number"
msgstr "Deine Kreditkartennummer"
#: templates/hosting/reset_password.html:15
msgid "Reset your password"
msgstr "Passwort zurücksetzen"
@ -529,12 +581,15 @@ msgstr "Du kannst dich nun"
msgid "Sorry. Your request is invalid."
msgstr "Entschuldigung, deine Anfrage ist ungültig."
#: views.py:756
#: views.py:757
msgid ""
"We could not find the requested VM. Please "
"contact Data Center Light Support."
msgstr ""
#~ msgid "Billing Amount"
#~ msgstr "Rechnungsbetrag"
#~ msgid "Payment Details"
#~ msgstr "Rechnungsdetails"
@ -552,15 +607,9 @@ msgstr ""
#~ msgid "CARD NUMBER"
#~ msgstr "Kreditkartennummer"
#~ msgid "Valid Card Number"
#~ msgstr "Gültige Kreditkartennummer"
#~ msgid "EXPIRATION DATE"
#~ msgstr "Ablaufdatum"
#~ msgid "CV CODE"
#~ msgstr "CV Code"
#~ msgid "Home"
#~ msgstr "Home"

View file

@ -4,14 +4,15 @@
* For details, see http://www.apache.org/licenses/LICENSE-2.0.
*/
@font-face {
font-family: 'Lato-Regular';
src: url('../fonts/Lato/Lato-Regular.ttf');
}
@font-face {
src: url('../fonts/Lato/Lato-Black.ttf');
}
@font-face {
font-family: 'Lato-Light';
src: url('../fonts/Lato/Lato-Light.ttf');
@ -33,6 +34,7 @@ h6 {
font-family: 'Lato-Regular', sans-serif;
font-weight: 300;
}
.topnav {
font-size: 14px;
}
@ -191,17 +193,19 @@ h6 {
float: right;
margin-top: 0;
}
/*------Auth section---------*/
.auth-container{
.auth-container {
height: 100vh;
position: relative;
}
.auth-bg{
.auth-bg {
background: url(../img/auth-bg.jpg);
position: fixed;
left: 0;
top: 0;
width: 100%;
width: 100%;
height: 100vh;
background-repeat: no-repeat;
background-position: center center;
@ -209,7 +213,8 @@ h6 {
background-attachment: fixed;
}
.auth-bg::before{
.auth-bg::before {
content: "";
position: absolute;
top: 0;
@ -219,26 +224,30 @@ h6 {
background: rgba(75, 75, 101, 0.55);
z-index: 1;
}
.auth-container .container{
.auth-container .container {
z-index: 1000;
}
.auth-container .auth-content{
.auth-container .auth-content {
width: 100%;
margin: 0 auto;
max-width: 390px;
}
.auth-container .auth-center{
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
.auth-container .auth-center {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 100%;
}
.auth-container .auth-title{
.auth-container .auth-title {
margin-bottom: 50px;
}
.auth-container .auth-title h2{
.auth-container .auth-title h2 {
color: #fff;
font-size: 44px;
text-align: center;
@ -247,7 +256,8 @@ h6 {
margin-bottom: 30px;
position: relative;
}
.auth-container .auth-title h2::after{
.auth-container .auth-title h2::after {
content: "";
position: absolute;
bottom: -20px;
@ -258,17 +268,17 @@ h6 {
transform: translate(-50%, 0);
}
.auth-box{
.auth-box {
background: #fff;
padding: 0;
padding-bottom: 30px;
box-sizing: border-box;
box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
border-radius: 4px;
z-index: 10;
}
.auth-box .section-heading{
.auth-box .section-heading {
color: #5a5a5a;
padding-top: 30px;
padding-bottom: 5px;
@ -279,42 +289,51 @@ h6 {
border-radius: 3px 3px 0px 0px;
margin: 0 auto;
}
.auth-box .form{
.auth-box .form {
padding: 20px;
width: 80%;
margin: 0 auto;
}
.auth-box .form .red{
.auth-box .form .red {
color: #ea3a3a;
}
.auth-box .form .btn{
box-shadow: 0 0px 9px rgba(0,0,0,0.19), 0 3px 5px rgba(0,0,0,0.23);
.auth-box .form .btn {
box-shadow: 0 0px 9px rgba(0, 0, 0, 0.19), 0 3px 5px rgba(0, 0, 0, 0.23);
letter-spacing: 3px;
font-size: 17px;
text-transform: uppercase;
}
.auth-box .form .form-control{
.auth-box .form .form-control {
height: 44px;
font-size: 16px;
}
.auth-box .auth-footer {
text-align: center;
padding: 10px;
}
.auth-box .auth-footer .text{
.auth-box .auth-footer .text {
color: #777;
}
.auth-box .auth-footer .links a{
color: #1e94cc;
}
.auth-box .auth-footer .links a:hover{
.auth-box .auth-footer .links a {
color: #1e94cc;
}
.auth-box.sign-up{
.auth-box .auth-footer .links a:hover {
color: #1e94cc;
}
.auth-box.sign-up {
padding-bottom: 5px;
}
.auth-box.sign-up .form{
.auth-box.sign-up .form {
padding: 15px 20px 0 20px;
}
@ -325,6 +344,7 @@ h6 {
line-height: 30px;
font-family: 'Lato' !important;
}
.sign-up-message a {
font-size: 18px;
color: #1e94cc !important;
@ -353,38 +373,47 @@ h6 {
ul.banner-social-buttons > li:last-child {
margin-bottom: 0;
}
.auth-box .form {
padding: 15px 0px 0 0;
}
.auth-box.sign-up .form {
padding: 15px 0px 0 0;
}
.auth-box .form .form-control {
height: 44px;
font-size: 13px;
}
.auth-container .auth-title {
display: none;
}
}
@media (max-width: 540px) {
.auth-container .auth-title h2{
.auth-container .auth-title h2 {
font-size: 32px;
width: 90%;
margin-bottom: 50px;
}
.auth-container.auth-signup .auth-title h2{
.auth-container.auth-signup .auth-title h2 {
font-size: 20px;
width: 90%;
margin-bottom: 50px;
}
.auth-box .form {
width: 90%;
}
.auth-box .section-heading {
font-size: 15px;
}
}
footer {
padding: 2%;
background-color: #f8f8f8;
@ -418,3 +447,231 @@ a.unlink:hover {
color: inherit;
}
/***** DCL payment page **********/
.dcl-order-container {
font-family: Lato;
}
.dcl-order-table-header {
border-bottom: 1px solid #eee;
padding-top: 15px;
padding-bottom: 15px;
font-size: 16px;
color: #333;
text-align: center;
font-weight: 300;
}
.dcl-order-table-content {
border-bottom: 1px solid #eee;
padding-top: 15px;
padding-bottom: 15px;
font-size: 18px;
font-weight: 600;
text-align: center;
}
.tbl-content {
}
.dcl-order-table-total {
border-bottom: 4px solid #eee;
padding-top: 15px;
padding-bottom: 20px;
font-size: 20px;
font-weight: 600;
color: #999;
}
.dcl-order-table-total span {
font-size: 13px;
color: #999;
font-weight: 400;
padding-left: 5px;
}
.dcl-order-table-total .tbl-total {
text-align: center;
color: #000;
}
.tbl-no-padding {
padding: 0px;
}
.dcl-billing-sec {
margin-top: 50px;
}
.dcl-order-sec {
padding: 0 30px;
}
.card-warning-content {
font-family: Lato;
border: 1px solid #a1a1a1;
border-radius: 3px;
padding: 5px;
}
.stripe-payment-btn {
outline: none;
width: auto;
float: right;
font-style: normal;
font-weight: 300;
position: absolute;
padding-left: 30px;
padding-right: 30px;
right: 0;
}
.brand {
}
.brand #brand-icon {
}
.card-number-element {
}
.card-expiry-element {
}
.card-cvc-element label {
padding-left: 10px;
}
.card-element {
margin-bottom: 10px;
padding: 0;
}
.card-element label{
width:100%;
margin-bottom:0px;
}
.my-input {
border-bottom: 1px solid #ccc;
}
.card-cvc-element .my-input {
padding-left: 10px;
}
#card-errors {
clear: both;
padding: 0 0 10px;
color: #eb4d5c;
}
.credit-card-goup{
padding: 0;
}
@media (max-width: 767px) {
.dcl-order-table-total span {
padding-left: 3px;
}
.dcl-order-sec {
padding: 10px 20px 30px 20px;
border-bottom: 4px solid #eee;
}
.tbl-header {
border-bottom: 1px solid #eee;
padding: 10px 0;
}
.tbl-content {
border-bottom: 1px solid #eee;
padding: 10px 0;
}
.dcl-order-table-header {
border-bottom: 0px solid #eee;
padding: 10px 0;
text-align: left;
}
.dcl-order-table-content {
border-bottom: 0px solid #eee;
padding: 10px 0;
text-align: right;
font-size: 16px;
}
.dcl-order-table-total {
font-size: 18px;
color: #000;
padding: 10px 0;
border-bottom: 0px solid #eee;
}
.dcl-order-table-total .tbl-total {
padding: 0px;
text-align: right;
}
.dcl-billing-sec {
margin-top: 30px;
margin-bottom: 30px;
}
.brand {
}
.card-expiry-element {
padding-right: 10px;
}
.card-cvc-element {
padding-left: 10px;
}
.hide-mobile{
display:none;
}
#billing-form .form-control {
box-shadow: none !important;
font-weight: 400;
}
}
@media (min-width: 1200px) {
.dcl-order-container {
width: 990px;
padding-right: 15px;
padding-left: 15px;
margin-right: auto;
margin-left: auto;
}
}
@media (min-width: 768px) {
.dcl-billing {
padding-right: 50px;
border-right: 1px solid #eee;
}
.dcl-creditcard {
padding-left: 50px;
}
.tbl-tot {
padding-left: 17px;
}
.content-dashboard {
/*width: auto !important;*/
}
}
@media only screen and (max-width: 1040px) and (min-width: 768px) {
.content-dashboard {
width: 96% !important;
}
}
@media only screen and (max-width: 1330px) and (min-width: 1200px) {
.content-dashboard {
width: 100% !important;
}
}

View file

@ -1,39 +1,143 @@
$( document ).ready(function() {
var cardBrandToPfClass = {
'visa': 'pf-visa',
'mastercard': 'pf-mastercard',
'amex': 'pf-american-express',
'discover': 'pf-discover',
'diners': 'pf-diners',
'jcb': 'pf-jcb',
'unknown': 'pf-credit-card'
};
function setBrandIcon(brand) {
var brandIconElement = document.getElementById('brand-icon');
var pfClass = 'pf-credit-card';
if (brand in cardBrandToPfClass) {
pfClass = cardBrandToPfClass[brand];
}
for (var i = brandIconElement.classList.length - 1; i >= 0; i--) {
brandIconElement.classList.remove(brandIconElement.classList[i]);
}
brandIconElement.classList.add('pf');
brandIconElement.classList.add(pfClass);
}
$(document).ready(function () {
$.ajaxSetup({
beforeSend: function (xhr, settings) {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
// Only send the token to relative URLs i.e. locally.
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
// Only send the token to relative URLs i.e. locally.
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
});
var hasCreditcard = window.hasCreditcard || false;
if (!hasCreditcard){
if (!hasCreditcard) {
var stripe = Stripe(window.stripeKey);
var elements = stripe.elements({locale: window.current_lan});
var card = elements.create('card', options={hidePostalCode: true});
card.mount('#card-element');
var element_style = {
fonts: [{
family: 'lato-light',
src: 'url(https://cdn.jsdelivr.net/font-lato/2.0/Lato/Lato-Light.woff) format("woff2")'
}, {
family: 'lato-regular',
src: 'url(https://cdn.jsdelivr.net/font-lato/2.0/Lato/Lato-Regular.woff) format("woff2")'
}
],
locale: window.current_lan
};
var elements = stripe.elements(element_style);
var credit_card_text_style = {
base: {
iconColor: '#666EE8',
color: '#31325F',
lineHeight: '25px',
fontWeight: 300,
fontFamily: "'lato-light', sans-serif",
fontSize: '14px',
'::placeholder': {
color: '#777'
}
},
invalid: {
iconColor: '#eb4d5c',
color: '#eb4d5c',
lineHeight: '25px',
fontWeight: 300,
fontFamily: "'lato-regular', sans-serif",
fontSize: '14px',
'::placeholder': {
color: '#eb4d5c',
fontWeight: 400
}
}
};
var credit_card_cvv_style = {
base: {
iconColor: '#666EE8',
color: '#31325F',
lineHeight: '25px',
fontWeight: 300,
fontFamily: "'lato-regular', sans-serif",
fontSize: '14px',
'::placeholder': {
color: '#555'
}
},
invalid: {
iconColor: '#eb4d5c',
color: '#eb4d5c',
lineHeight: '25px',
fontWeight: 300,
fontFamily: "'lato-regular', sans-serif",
fontSize: '14px',
'::placeholder': {
color: '#eb4d5c',
fontWeight: 600
}
}
};
var enter_ccard_text = "Enter your credit card number";
if (typeof window.enter_your_card_text !== 'undefined') {
enter_ccard_text = window.enter_your_card_text;
}
var cardNumberElement = elements.create('cardNumber', {
style: credit_card_text_style,
placeholder: enter_ccard_text
});
cardNumberElement.mount('#card-number-element');
var cardExpiryElement = elements.create('cardExpiry', {
style: credit_card_text_style
});
cardExpiryElement.mount('#card-expiry-element');
var cardCvcElement = elements.create('cardCvc', {
style: credit_card_text_style
});
cardCvcElement.mount('#card-cvc-element');
cardNumberElement.on('change', function (event) {
if (event.brand) {
setBrandIcon(event.brand);
}
});
}
console.log("has creditcard", hasCreditcard);
// hasCreditcard= true;
@ -42,85 +146,58 @@ $( document ).ready(function() {
submit_form_btn.on('click', submit_payment);
function submit_payment(e){
e.preventDefault();
console.log("creditcard sdasd");
// if (hasCreditcard) {
$('#billing-form').submit();
// }
function submit_payment(e) {
e.preventDefault();
console.log("creditcard sdasd");
// if (hasCreditcard) {
$('#billing-form').submit();
// }
}
var $form_new = $('#payment-form-new');
$form_new.submit(payWithStripe_new);
var $form = $('#payment-form');
$form.submit(payWithStripe);
/* If you're using Stripe for payments */
function payWithStripe(e) {
function payWithStripe_new(e) {
e.preventDefault();
function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('payment-form');
var hiddenInput = document.createElement('input');
$('#id_token').val(token.id);
$('#billing-form').submit();
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('payment-form-new');
$('#id_token').val(token.id);
$('#billing-form').submit();
}
stripe.createToken(card).then(function(result) {
stripe.createToken(cardNumberElement).then(function (result) {
if (result.error) {
// Inform the user if there was an error
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
// Inform the user if there was an error
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
} else {
$form.find('[type=submit]').html('Processing <i class="fa fa-spinner fa-pulse"></i>');
var process_text = "Processing";
if (typeof window.processing_text !== 'undefined') {
process_text = window.processing_text
}
$form_new.find('[type=submit]').html(process_text + ' <i class="fa fa-spinner fa-pulse"></i>');
// Send the token to your server
stripeTokenHandler(result.token);
}
});
// /* Visual feedback */
// $form.find('[type=submit]').html('Validating <i class="fa fa-spinner fa-pulse"></i>');
// var PublishableKey = window.stripeKey;
// Stripe.setPublishableKey(PublishableKey);
// Stripe.card.createToken($form, function stripeResponseHandler(status, response) {
// if (response.error) {
// /* Visual feedback */
// $form.find('[type=submit]').html('Try again');
// /* Show Stripe errors on the form */
// $form.find('.payment-errors').text(response.error.message);
// $form.find('.payment-errors').closest('.row').show();
// } else {
// /* Visual feedback */
// $form.find('[type=submit]').html('Processing <i class="fa fa-spinner fa-pulse"></i>');
// /* Hide Stripe errors on the form */
// $form.find('.payment-errors').closest('.row').hide();
// $form.find('.payment-errors').text("");
// // response contains id and card, which contains additional card details
// var token = response.id;
// // AJAX
// //set token on a hidden input
// $('#id_token').val(token);
// $('#billing-form').submit();
// }
// });
}
/* Form validation */
$.validator.addMethod("month", function(value, element) {
return this.optional(element) || /^(01|02|03|04|05|06|07|08|09|10|11|12)$/.test(value);
$.validator.addMethod("month", function (value, element) {
return this.optional(element) || /^(01|02|03|04|05|06|07|08|09|10|11|12)$/.test(value);
}, "Please specify a valid 2-digit month.");
$.validator.addMethod("year", function(value, element) {
return this.optional(element) || /^[0-9]{2}$/.test(value);
$.validator.addMethod("year", function (value, element) {
return this.optional(element) || /^[0-9]{2}$/.test(value);
}, "Please specify a valid 2-digit year.");
validator = $form.validate({
validator = $form_new.validate({
rules: {
cardNumber: {
required: true,
@ -140,28 +217,16 @@ $( document ).ready(function() {
digits: true
}
},
highlight: function(element) {
highlight: function (element) {
$(element).closest('.form-control').removeClass('success').addClass('error');
},
unhighlight: function(element) {
unhighlight: function (element) {
$(element).closest('.form-control').removeClass('error').addClass('success');
},
errorPlacement: function(error, element) {
errorPlacement: function (error, element) {
$(element).closest('.form-group').append(error);
}
});
paymentFormReady = function() {
if ($form.find('[name=cardNumber]').hasClass("success") &&
$form.find('[name=expMonth]').hasClass("success") &&
$form.find('[name=expYear]').hasClass("success") &&
$form.find('[name=cvCode]').val().length > 1) {
return true;
} else {
return false;
}
};
// $form.find('[type=submit]').prop('disabled', true);
// var readyInterval = setInterval(function() {
// if (paymentFormReady()) {

View file

@ -24,15 +24,7 @@
</div>
<hr>
<div class="row">
<div class="col-xs-6">
<address>
<h3><b>{% trans "Billed To:"%}</b></h3>
{{user.name}}<br>
{{order.billing_address.street_address}},{{order.billing_address.postal_code}}<br>
{{order.billing_address.city}}, {{order.billing_address.country}}.
</address>
</div>
<div class="col-xs-6 text-right">
<div class="col-xs-12 col-md-6 pull-right text-left">
<address>
<strong>{% trans "Date"%}:</strong><br>
<span id="order-created_at">{{order.created_at|date:'Y-m-d H:i'}}</span><br><br>
@ -44,6 +36,15 @@
</address>
</div>
<div class="col-xs-12 col-md-6">
<address>
<h3><b>{% trans "Billed To:"%}</b></h3>
{{user.name}}<br>
{{order.billing_address.street_address}},{{order.billing_address.postal_code}}<br>
{{order.billing_address.city}}, {{order.billing_address.country}}.
</address>
</div>
</div>
<div class="row">
<div class="col-xs-6">

View file

@ -2,139 +2,182 @@
{% load staticfiles bootstrap3 i18n %}
{% block content %}
<!-- Credit card form -->
<div>
<div class="payment-container">
<div class="row">
<div class="col-xs-12 col-md-offset-2 col-md-4 summary-box">
<form role="form" novalidate>
<div class="row">
<div class="col-xs-12">
<h3><b>{%trans "Billing Amount" %}</b></h3>
<hr>
<div class="content">
<!-- <p><b>Type</b> <span class="pull-right">{{request.session.vm_specs.location_code}}</span></p> -->
<!-- <hr> -->
<p><b>{%trans "Cores"%}</b> <span
class="pull-right">{{request.session.specs.cpu|floatformat}}</span></p>
<hr>
<p><b>{%trans "Memory"%}</b> <span
class="pull-right">{{request.session.specs.memory|floatformat}} GB</span></p>
<hr>
<p><b>{%trans "Disk space"%}</b> <span
class="pull-right">{{request.session.specs.disk_size|floatformat}} GB</span></p>
<hr>
<p><b>{%trans "Configuration"%}</b> <span
class="pull-right">{{request.session.template.name}}</span></p>
<hr>
<h4>Total<p
class="pull-right"><b>{{request.session.specs.price }} CHF</b></p></h4>
</div>
</div>
</div>
</form>
</div>
<div class="col-xs-12 col-md-4 billing">
<h3><b>{%trans "Billing Address"%}</b></h3>
<hr>
<form role="form" id="billing-form" method="post" action="" novalidate>
{% for field in form %}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/paymentfont/1.1.2/css/paymentfont.min.css"/>
<div class="dcl-order-container">
<div class="payment-container">
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 dcl-order-sec">
<h3><strong>{%trans "Your Order" %}</strong></h3>
<div class="col-xs-6 col-sm-12 col-md-12 col-lg-12 dcl-order-table-header">
<div class="col-xs-12 col-sm-2 col-md-1 col-lg-1 tbl-header">
{%trans "Cores" %}
</div>
<div class="col-xs-12 col-sm-3 col-md-4 col-lg-4 tbl-header">
{%trans "Memory" %}
</div>
<div class="col-xs-12 col-sm-3 col-md-3 col-lg-3 tbl-header">
{%trans "Disk space" %}
</div>
<div class="col-xs-12 col-sm-4 col-md-4 col-lg-4 tbl-header">
{%trans "Configuration" %}
</div>
</div>
<div class="col-xs-6 col-sm-12 col-md-12 col-lg-12 dcl-order-table-content">
<div class="col-xs-12 col-sm-2 col-md-1 col-lg-1 tbl-content">
{{request.session.specs.cpu|floatformat}}
</div>
<div class="col-xs-12 col-sm-3 col-md-4 col-lg-4 tbl-content">
{{request.session.specs.memory|floatformat}} GB
</div>
<div class="col-xs-12 col-sm-3 col-md-3 col-lg-3 tbl-content">
{{request.session.specs.disk_size|floatformat}} GB
</div>
<div class="col-xs-12 col-sm-4 col-md-4 col-lg-4 tbl-content">
{{request.session.template.name}}
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 dcl-order-table-total">
<div class="col-xs-6 col-sm-6 col-md-6 col-lg-6 tbl-tot tbl-no-padding">
{%trans "Total" %} <span>{%trans "including VAT" %}</span>
</div>
<div class="col-xs-6 col-sm-6 col-md-6 col-lg-6 tbl-no-padding">
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6"></div>
<div class="col-xs-12 col-sm-4 col-md-4 col-lg-4 tbl-total">{{request.session.specs.price}}
CHF
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 dcl-billing-sec">
<div class="col-xs-12 col-sm-5 col-md-6 billing dcl-billing">
<h3><b>{%trans "Billing Address"%}</b></h3>
<hr>
<form role="form" id="billing-form" method="post" action="" novalidate>
{% for field in form %}
{% csrf_token %}
{% bootstrap_field field show_label=False type='fields'%}
{% endfor %}
{% bootstrap_form_errors form type='non_fields'%}
</form>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-md-offset-2 col-md-4 "></div>
<div class="col-xs-12 col-md-4 creditcard-box">
<h3><b>{%trans "Credit Card"%}</b></h3>
<hr>
<div>
<div>
<p> {% trans 'Please fill in your credit card information below. We are using <a href="https://stripe.com" target="_blank">Stripe</a> for payment and do not store your information in our database.' %}</p>
</div>
<br>
<div>
{% if credit_card_data.last4 %}
<form role="form" id="payment-form-with-creditcard"novalidate>
<h5 class="billing-head">Credit Card</h5>
<h5 class="membership-lead">Last 4: *****{{credit_card_data.last4}}</h5>
<h5 class="membership-lead">Type: {{credit_card_data.cc_brand}}</h5>
<input type="hidden" name="credit_card_needed" value="false"/>
</form>
<div class="row">
<br>
<div class="col-xs-12>
<p style="font-family: Lato;border: 1px solid #a1a1a1;border-radius: 3px; padding: 5px; ">{% trans "You are not making any payment yet. After submitting your card information, you will be taken to the Confirm Order Page." %}</p>
</div>
<div class="col-xs-12">
<div class="col-xs-6 pull-right">
<button style="width: 100px; float: right; font-style: normal; font-weight: bold; position: absolute; right: 0;" id="payment_button_with_creditcard" class="btn btn-success" type="submit">
{% trans "Submit" %}
</button>
</div>
</div>
</div>
{% else %}
<form role="form" id="payment-form" novalidate>
{% bootstrap_field field show_label=False type='fields'%}
{% endfor %}
{% bootstrap_form_errors form type='non_fields'%}
</form>
</div>
<div class="col-xs-12 col-sm-7 col-md-6 creditcard-box dcl-creditcard">
<h3><b>{%trans "Credit Card"%}</b></h3>
<hr>
<div>
<div>
<p>
{% blocktrans %}
Please fill in your credit card information below. We are using <a
href="https://stripe.com" target="_blank">Stripe</a> for payment and do not store
your information in our database.
{% endblocktrans %}
</p>
</div>
<br>
<div>
{% if credit_card_data.last4 %}
<form role="form" id="payment-form-with-creditcard" novalidate>
<h5 class="billing-head">Credit Card</h5>
<h5 class="membership-lead">Last 4: *****{{credit_card_data.last4}}</h5>
<h5 class="membership-lead">Type: {{credit_card_data.cc_brand}}</h5>
<input type="hidden" name="credit_card_needed" value="false"/>
</form>
<div class="row">
<div class="form-group col-xs-12">
<div id="card-element">
<!-- a Stripe Element will be inserted here. -->
</div>
<div class="col-xs-12">
<p>
{% blocktrans %}
You are not making any payment yet. After submitting your card
information, you will be taken to the Confirm Order Page.
{% endblocktrans %}
</p>
</div>
<div class="col-xs-12">
<div class="col-xs-6 pull-right">
<button id="payment_button_with_creditcard" class="btn btn-success stripe-payment-btn"
type="submit">
{%trans "Submit" %}
</button>
</div>
</div>
</div>
</div>
<div id="card-errors" role="alert"></div>
<div class="row">
<br>
<div class="col-xs-12">
<p style="font-family: Lato;border: 1px solid #a1a1a1;border-radius: 3px; padding: 5px;"> {% trans "You are not making any payment yet. After submitting your card information, you will be taken to the Confirm Order Page." %}</p>
</div>
<div class="col-xs-12">
<div class="col-xs-6 pull-right">
<button style="width: 100px; float: right; font-style: normal; font-weight: bold; position: absolute; right: 0;" class="btn btn-success" type="submit">{% trans "Submit" %}</button>
</div>
</div>
</div>
<div class="row" style="display:none;">
<div class="col-xs-12">
<p class="payment-errors"></p>
</div>
</div>
{% if paymentError %}
<div class="row">
<div class="col-xs-12">
<p>
{% bootstrap_alert paymentError alert_type='danger' %}
</p>
</div>
</div>
{% endif %}
{% else %}
<form action="" id="payment-form-new" method="POST">
<input type="hidden" name="token"/>
<div class="group">
<div class="col-xs-12 col-sm-12 col-md-10 col-lg-9 credit-card-goup">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 card-element card-number-element">
<label>{%trans "Card Number" %}</label>
<div id="card-number-element" class="field my-input"></div>
</div>
<div class="col-xs-5 col-sm-3 col-md-3 col-lg-3 card-element card-expiry-element">
<label>{%trans "Expiry Date" %}</label>
<div id="card-expiry-element" class="field my-input"></div>
</div>
<div class="col-xs-12 col-sm-2 col-md-6 col-lg-7 hide-mobile"></div>
<div class="col-xs-3 col-sm-3 col-md-3 col-lg-2 card-element card-cvc-element">
<label>{%trans "CVC" %}</label>
<div id="card-cvc-element" class="field my-input"></div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 card-element brand">
<label>{%trans "Card Type" %}</label>
<i class="pf pf-credit-card" id="brand-icon"></i>
</div>
</div>
</div>
<div id="card-errors" role="alert"></div>
<div class="row">
<div class="col-xs-12">
<p class="card-warning-content">
{% blocktrans %}
You are not making any payment yet. After submitting your card
information, you will be taken to the Confirm Order Page.
{% endblocktrans %}
</p>
</div>
<div class="col-xs-12">
<div class="col-xs-6 pull-right">
<button class="btn btn-success stripe-payment-btn" type="submit">{%trans "Submit" %}
</button>
</div>
</div>
</div>
</form>
{% endif %}
</div>
</div>
</div>
</div>
</div>
<div class="row" style="display:none;">
<div class="col-xs-12">
<p class="payment-errors"></p>
</div>
</div>
{% if paymentError %}
<div class="row">
<div class="col-xs-12">
<p>
{% bootstrap_alert paymentError alert_type='danger' %}
</p>
</div>
</div>
{% endif %}
</form>
{% endif %}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- stripe key data -->
{% if stripe_key %}
{% get_current_language as LANGUAGE_CODE %}
<script type="text/javascript">
window.processing_text = '{%trans "Processing" %}';
window.enter_your_card_text = '{%trans "Enter your credit card number" %}';
(function () {
(function () {
window.stripeKey = "{{stripe_key}}";
window.current_lan = "{{LANGUAGE_CODE}}";
})();
@ -143,7 +186,9 @@
{% if credit_card_data.last4 and credit_card_data.cc_brand %}
<script type="text/javascript">
(function () {window.hasCreditcard = true;})();
(function () {
window.hasCreditcard = true;
})();
</script>
{%endif%}

View file

@ -440,6 +440,7 @@ class PaymentVMView(LoginRequiredMixin, FormView):
form_kwargs.update({
'initial': {
'cardholder_name': current_billing_address.cardholder_name,
'street_address': current_billing_address.street_address,
'city': current_billing_address.city,
'postal_code': current_billing_address.postal_code,

View file

@ -5,11 +5,12 @@ from django.core.mail import EmailMultiAlternatives
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth import authenticate
from membership.models import CustomUser
# from utils.fields import CountryField
class SignupFormMixin(forms.ModelForm):
confirm_password = forms.CharField(widget=forms.PasswordInput())
password = forms.CharField(widget=forms.PasswordInput())
@ -50,8 +51,6 @@ class LoginFormMixin(forms.Form):
return email
except CustomUser.DoesNotExist:
raise forms.ValidationError("User does not exist")
else:
return email
class PasswordResetRequestForm(forms.Form):
@ -67,8 +66,6 @@ class PasswordResetRequestForm(forms.Form):
return email
except CustomUser.DoesNotExist:
raise forms.ValidationError("User does not exist")
else:
return email
class SetPasswordForm(forms.Form):
@ -91,7 +88,7 @@ class SetPasswordForm(forms.Form):
if password1 != password2:
raise forms.ValidationError(
self.error_messages['password_mismatch'],
code='password_mismatch',)
code='password_mismatch', )
return password2
@ -104,8 +101,9 @@ class BillingAddressForm(forms.ModelForm):
class Meta:
model = BillingAddress
fields = ['street_address', 'city', 'postal_code', 'country']
fields = ['cardholder_name', 'street_address', 'city', 'postal_code', 'country']
labels = {
'cardholder_name': _('Cardholder Name'),
'street_address': _('Street Address'),
'city': _('City'),
'postal_code': _('Postal Code'),

View file

@ -8,6 +8,7 @@ from .fields import CountryField
# Create your models here.
class BaseBillingAddress(models.Model):
cardholder_name = models.CharField(max_length=100, default="")
street_address = models.CharField(max_length=100)
city = models.CharField(max_length=50)
postal_code = models.CharField(max_length=50)
@ -18,7 +19,6 @@ class BaseBillingAddress(models.Model):
class BillingAddress(BaseBillingAddress):
def __str__(self):
return self.street_address
@ -32,6 +32,7 @@ class UserBillingAddress(BaseBillingAddress):
def to_dict(self):
return {
'Cardholder Name': self.cardholder_name,
'Street Address': self.street_address,
'City': self.city,
'Postal Code': self.postal_code,