@@ -4,7 +4,7 @@ define(['backbone', 'jquery', 'js/verify_student/photocapture'],
|
||||
describe("Photo Verification", function () {
|
||||
|
||||
beforeEach(function () {
|
||||
setFixtures('<div id="order-error" style="display: none;"></div><input type="radio" name="contribution" value="35" id="contribution-35" checked="checked"><input type="radio" id="contribution-other" name="contribution" value=""><input type="text" size="9" name="contribution-other-amt" id="contribution-other-amt" value="30"><img id="face_image" src="src="data:image/png;base64,dummy"><img id="photo_id_image" src="src="data:image/png;base64,dummy"><button id="pay_button">pay button</button>');
|
||||
setFixtures('<div id="order-error" style="display: none;"></div><input type="radio" name="contribution" value="35" id="contribution-35" checked="checked"><input type="radio" id="contribution-other" name="contribution" value=""><input type="text" size="9" name="contribution-other-amt" id="contribution-other-amt" value="30"><img id="face_image" src="src="data:image/png;base64,dummy"><img id="photo_id_image" src="src="data:image/png;base64,dummy"><button class="payment-button">pay button</button>');
|
||||
});
|
||||
|
||||
it('retake photo', function () {
|
||||
@@ -27,7 +27,7 @@ define(['backbone', 'jquery', 'js/verify_student/photocapture'],
|
||||
});
|
||||
submitToPaymentProcessing();
|
||||
expect(window.submitForm).toHaveBeenCalled();
|
||||
expect($("#pay_button")).toHaveClass("is-disabled");
|
||||
expect($(".payment-button")).toHaveClass("is-disabled");
|
||||
});
|
||||
|
||||
it('Error during process', function () {
|
||||
@@ -44,7 +44,7 @@ define(['backbone', 'jquery', 'js/verify_student/photocapture'],
|
||||
expect(window.showSubmissionError).toHaveBeenCalled();
|
||||
|
||||
// make sure the button isn't disabled
|
||||
expect($("#pay_button")).not.toHaveClass("is-disabled");
|
||||
expect($(".payment-button")).not.toHaveClass("is-disabled");
|
||||
|
||||
// but also make sure that it was disabled during the ajax call
|
||||
expect($.fn.addClass).toHaveBeenCalledWith("is-disabled");
|
||||
|
||||
@@ -5,7 +5,7 @@ define(['js/common_helpers/ajax_helpers', 'js/student_account/enrollment'],
|
||||
describe( 'edx.student.account.EnrollmentInterface', function() {
|
||||
|
||||
var COURSE_KEY = 'edX/DemoX/Fall',
|
||||
ENROLL_URL = '/commerce/orders/',
|
||||
ENROLL_URL = '/commerce/baskets/',
|
||||
FORWARD_URL = '/course_modes/choose/edX/DemoX/Fall/',
|
||||
EMBARGO_MSG_URL = '/embargo/blocked-message/enrollment/default/';
|
||||
|
||||
|
||||
@@ -11,8 +11,6 @@ define([
|
||||
|
||||
describe( 'edx.verify_student.MakePaymentStepView', function() {
|
||||
|
||||
var PAYMENT_URL = "/pay";
|
||||
|
||||
var PAYMENT_PARAMS = {
|
||||
orderId: "test-order",
|
||||
signature: "abcd1234"
|
||||
@@ -21,7 +19,7 @@ define([
|
||||
var STEP_DATA = {
|
||||
minPrice: "12",
|
||||
currency: "usd",
|
||||
purchaseEndpoint: PAYMENT_URL,
|
||||
processors: ["test-payment-processor"],
|
||||
courseKey: "edx/test/test",
|
||||
courseModeSlug: 'verified'
|
||||
};
|
||||
@@ -50,15 +48,16 @@ define([
|
||||
};
|
||||
|
||||
var expectPaymentButtonEnabled = function( isEnabled ) {
|
||||
var appearsDisabled = $( '#pay_button' ).hasClass( 'is-disabled' ),
|
||||
isDisabled = $( '#pay_button' ).prop( 'disabled' );
|
||||
var el = $( '.payment-button'),
|
||||
appearsDisabled = el.hasClass( 'is-disabled' ),
|
||||
isDisabled = el.prop( 'disabled' );
|
||||
|
||||
expect( !appearsDisabled ).toEqual( isEnabled );
|
||||
expect( !isDisabled ).toEqual( isEnabled );
|
||||
};
|
||||
|
||||
var expectPaymentDisabledBecauseInactive = function() {
|
||||
var payButton = $( '#pay_button' );
|
||||
var payButton = $( '.payment_button' );
|
||||
|
||||
// Payment button should be hidden
|
||||
expect( payButton.length ).toEqual(0);
|
||||
@@ -67,21 +66,22 @@ define([
|
||||
var goToPayment = function( requests, kwargs ) {
|
||||
var params = {
|
||||
contribution: kwargs.amount || "",
|
||||
course_id: kwargs.courseId || ""
|
||||
course_id: kwargs.courseId || "",
|
||||
processor: kwargs.processor || ""
|
||||
};
|
||||
|
||||
// Click the "go to payment" button
|
||||
$( '#pay_button' ).click();
|
||||
$( '.payment-button' ).click();
|
||||
|
||||
// Verify that the request was made to the server
|
||||
AjaxHelpers.expectRequest(
|
||||
requests, "POST", "/verify_student/create_order/",
|
||||
$.param( params )
|
||||
AjaxHelpers.expectPostRequest(
|
||||
requests, "/verify_student/create_order/", $.param( params )
|
||||
);
|
||||
|
||||
// Simulate the server response
|
||||
if ( kwargs.succeeds ) {
|
||||
AjaxHelpers.respondWithJson( requests, PAYMENT_PARAMS );
|
||||
// TODO put fixture responses in the right place
|
||||
AjaxHelpers.respondWithJson( requests, {payment_page_url: 'http://payment-page-url/', payment_form_data: {foo: 'bar'}} );
|
||||
} else {
|
||||
AjaxHelpers.respondWithTextError( requests, 400, SERVER_ERROR_MSG );
|
||||
}
|
||||
@@ -95,7 +95,7 @@ define([
|
||||
|
||||
expect(form.serialize()).toEqual($.param(params));
|
||||
expect(form.attr('method')).toEqual("POST");
|
||||
expect(form.attr('action')).toEqual(PAYMENT_URL);
|
||||
expect(form.attr('action')).toEqual('http://payment-page-url/');
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
@@ -114,9 +114,10 @@ define([
|
||||
goToPayment( requests, {
|
||||
amount: STEP_DATA.minPrice,
|
||||
courseId: STEP_DATA.courseKey,
|
||||
processor: STEP_DATA.processors[0],
|
||||
succeeds: true
|
||||
});
|
||||
expectPaymentSubmitted( view, PAYMENT_PARAMS );
|
||||
expectPaymentSubmitted( view, {foo: 'bar'} );
|
||||
});
|
||||
|
||||
it( 'by default minimum price is selected if no suggested prices are given', function() {
|
||||
@@ -129,9 +130,10 @@ define([
|
||||
goToPayment( requests, {
|
||||
amount: STEP_DATA.minPrice,
|
||||
courseId: STEP_DATA.courseKey,
|
||||
processor: STEP_DATA.processors[0],
|
||||
succeeds: true
|
||||
});
|
||||
expectPaymentSubmitted( view, PAYMENT_PARAMS );
|
||||
expectPaymentSubmitted( view, {foo: 'bar'} );
|
||||
});
|
||||
|
||||
it( 'min price is always selected even if contribution amount is provided', function() {
|
||||
@@ -156,6 +158,7 @@ define([
|
||||
goToPayment( requests, {
|
||||
amount: STEP_DATA.minPrice,
|
||||
courseId: STEP_DATA.courseKey,
|
||||
processor: STEP_DATA.processors[0],
|
||||
succeeds: false
|
||||
});
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ var edx = edx || {};
|
||||
edx.student.account.EnrollmentInterface = {
|
||||
|
||||
urls: {
|
||||
orders: '/commerce/orders/',
|
||||
baskets: '/commerce/baskets/',
|
||||
},
|
||||
|
||||
headers: {
|
||||
@@ -26,7 +26,7 @@ var edx = edx || {};
|
||||
data = JSON.stringify(data_obj);
|
||||
|
||||
$.ajax({
|
||||
url: this.urls.orders,
|
||||
url: this.urls.baskets,
|
||||
type: 'POST',
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
data: data,
|
||||
|
||||
@@ -59,7 +59,7 @@ var edx = edx || {};
|
||||
function( price ) { return Boolean( price ); }
|
||||
),
|
||||
currency: el.data('course-mode-currency'),
|
||||
purchaseEndpoint: el.data('purchase-endpoint'),
|
||||
processors: el.data('processors'),
|
||||
verificationDeadline: el.data('verification-deadline'),
|
||||
courseModeSlug: el.data('course-mode-slug'),
|
||||
alreadyVerified: el.data('already-verified'),
|
||||
|
||||
@@ -69,7 +69,7 @@ function refereshPageMessage() {
|
||||
}
|
||||
|
||||
var submitToPaymentProcessing = function() {
|
||||
$("#pay_button").addClass('is-disabled').attr('aria-disabled', true);
|
||||
$(".payment-button").addClass('is-disabled').attr('aria-disabled', true);
|
||||
var contribution_input = $("input[name='contribution']:checked")
|
||||
var contribution = 0;
|
||||
if(contribution_input.attr('id') == 'contribution-other') {
|
||||
@@ -96,7 +96,7 @@ var submitToPaymentProcessing = function() {
|
||||
}
|
||||
},
|
||||
error:function(xhr,status,error) {
|
||||
$("#pay_button").removeClass('is-disabled').attr('aria-disabled', false);
|
||||
$(".payment-button").removeClass('is-disabled').attr('aria-disabled', false);
|
||||
showSubmissionError()
|
||||
}
|
||||
});
|
||||
@@ -290,7 +290,7 @@ function waitForFlashLoad(func, flash_object) {
|
||||
|
||||
$(document).ready(function() {
|
||||
$(".carousel-nav").addClass('sr');
|
||||
$("#pay_button").click(function(){
|
||||
$(".payment-button").click(function(){
|
||||
analytics.pageview("Payment Form");
|
||||
submitToPaymentProcessing();
|
||||
});
|
||||
@@ -306,7 +306,7 @@ $(document).ready(function() {
|
||||
// prevent browsers from keeping this button checked
|
||||
$("#confirm_pics_good").prop("checked", false)
|
||||
$("#confirm_pics_good").change(function() {
|
||||
$("#pay_button").toggleClass('disabled');
|
||||
$(".payment-button").toggleClass('disabled');
|
||||
$("#reverify_button").toggleClass('disabled');
|
||||
$("#midcourse_reverify_button").toggleClass('disabled');
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
var edx = edx || {};
|
||||
|
||||
(function( $, _, gettext ) {
|
||||
(function( $, _, gettext, interpolate_text ) {
|
||||
'use strict';
|
||||
|
||||
edx.verify_student = edx.verify_student || {};
|
||||
@@ -28,12 +28,45 @@ var edx = edx || {};
|
||||
};
|
||||
},
|
||||
|
||||
_getProductText: function( modeSlug, isUpgrade ) {
|
||||
switch ( modeSlug ) {
|
||||
case "professional":
|
||||
return gettext( "Professional Education Verified Certificate" );
|
||||
case "no-id-professional":
|
||||
return gettext( "Professional Education" );
|
||||
default:
|
||||
if ( isUpgrade ) {
|
||||
return gettext( "Verified Certificate upgrade" );
|
||||
} else {
|
||||
return gettext( "Verified Certificate" );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_getPaymentButtonText: function(processorName) {
|
||||
if (processorName.toLowerCase().substr(0, 11)=='cybersource') {
|
||||
return gettext('Pay with Credit Card');
|
||||
} else {
|
||||
// This is mainly for testing as no other processors are supported right now.
|
||||
// Translators: 'processor' is the name of a third-party payment processing vendor (example: "PayPal")
|
||||
return interpolate_text(gettext('Pay with {processor}'), {processor: processorName});
|
||||
}
|
||||
},
|
||||
|
||||
_getPaymentButtonHtml: function(processorName) {
|
||||
var self = this;
|
||||
return _.template(
|
||||
'<a class="next action-primary payment-button" id="<%- name %>" tab-index="0"><%- text %></a> '
|
||||
)({name: processorName, text: self._getPaymentButtonText(processorName)});
|
||||
},
|
||||
|
||||
postRender: function() {
|
||||
var templateContext = this.templateContext(),
|
||||
hasVisibleReqs = _.some(
|
||||
templateContext.requirements,
|
||||
function( isVisible ) { return isVisible; }
|
||||
);
|
||||
),
|
||||
self = this;
|
||||
|
||||
// Track a virtual pageview, for easy funnel reconstruction.
|
||||
window.analytics.page( 'payment', this.templateName );
|
||||
@@ -59,25 +92,41 @@ var edx = edx || {};
|
||||
this.setPaymentEnabled( true );
|
||||
}
|
||||
|
||||
// render the name of the product being paid for
|
||||
$( 'div.payment-buttons span.product-name').append(
|
||||
self._getProductText( templateContext.courseModeSlug, templateContext.upgrade )
|
||||
);
|
||||
|
||||
// create a button for each payment processor
|
||||
_.each(templateContext.processors, function(processorName) {
|
||||
$( 'div.payment-buttons' ).append( self._getPaymentButtonHtml(processorName) );
|
||||
});
|
||||
|
||||
// Handle payment submission
|
||||
$( '#pay_button' ).on( 'click', _.bind( this.createOrder, this ) );
|
||||
$( '.payment-button' ).on( 'click', _.bind( this.createOrder, this ) );
|
||||
},
|
||||
|
||||
setPaymentEnabled: function( isEnabled ) {
|
||||
if ( _.isUndefined( isEnabled ) ) {
|
||||
isEnabled = true;
|
||||
}
|
||||
$( '#pay_button' )
|
||||
$( '.payment-button' )
|
||||
.toggleClass( 'is-disabled', !isEnabled )
|
||||
.prop( 'disabled', !isEnabled )
|
||||
.attr('aria-disabled', !isEnabled);
|
||||
},
|
||||
|
||||
createOrder: function() {
|
||||
// This function invokes the create_order endpoint. It will either create an order in
|
||||
// the lms' shoppingcart or a basket in Otto, depending on which backend the request course
|
||||
// mode is configured to use. In either case, the checkout process will be triggered,
|
||||
// and the expected response will consist of an appropriate payment processor endpoint for
|
||||
// redirection, along with parameters to be passed along in the request.
|
||||
createOrder: function(event) {
|
||||
var paymentAmount = this.getPaymentAmount(),
|
||||
postData = {
|
||||
'processor': event.target.id,
|
||||
'contribution': paymentAmount,
|
||||
'course_id': this.stepData.courseKey,
|
||||
'course_id': this.stepData.courseKey
|
||||
};
|
||||
|
||||
// Disable the payment button to prevent multiple submissions
|
||||
@@ -98,21 +147,21 @@ var edx = edx || {};
|
||||
|
||||
},
|
||||
|
||||
handleCreateOrderResponse: function( paymentParams ) {
|
||||
// At this point, the order has been created on the server,
|
||||
handleCreateOrderResponse: function( paymentData ) {
|
||||
// At this point, the basket has been created on the server,
|
||||
// and we've received signed payment parameters.
|
||||
// We need to dynamically construct a form using
|
||||
// these parameters, then submit it to the payment processor.
|
||||
// This will send the user to a hosted order page,
|
||||
// where she can enter credit card information.
|
||||
// This will send the user to an externally-hosted page
|
||||
// where she can proceed with payment.
|
||||
var form = $( '#payment-processor-form' );
|
||||
|
||||
$( 'input', form ).remove();
|
||||
|
||||
form.attr( 'action', this.stepData.purchaseEndpoint );
|
||||
form.attr( 'action', paymentData.payment_page_url );
|
||||
form.attr( 'method', 'POST' );
|
||||
|
||||
_.each( paymentParams, function( value, key ) {
|
||||
_.each( paymentData.payment_form_data, function( value, key ) {
|
||||
$('<input>').attr({
|
||||
type: 'hidden',
|
||||
name: key,
|
||||
@@ -200,4 +249,4 @@ var edx = edx || {};
|
||||
|
||||
});
|
||||
|
||||
})( jQuery, _, gettext );
|
||||
})( jQuery, _, gettext, interpolate_text );
|
||||
|
||||
Reference in New Issue
Block a user