-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TR-92: add 3DS #6
Open
apetrovici
wants to merge
39
commits into
slogsdon:add-gift-support
Choose a base branch
from
apetrovici:feature/tr-92-gpapi-integration-3ds
base: add-gift-support
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 12 commits
Commits
Show all changes
39 commits
Select commit
Hold shift + click to select a range
6e83199
TR-92: add 3DS
apetrovici c077afb
TR-92: updates
apetrovici 96917a1
TR-92: 3ds requests updates
apetrovici 9885a79
TR-92: config access token permissions update
apetrovici 1996e0c
TR-92: fix comma
apetrovici 3d8dfa9
Merge branch 'add-gift-support' into feature/tr-92-gpapi-integration-3ds
apetrovici 6a47514
TR-92: update 3ds js lib
apetrovici e97115c
TR-92: remove unused namespace
apetrovici 8d94d9a
TR-92: handle 3DS1
apetrovici c7e34a7
TR-92: update endpoints
apetrovici cf47953
TR-92: update endpoints
apetrovici 5452152
TR-92: updated 3ds lib to handle 3DS1
apetrovici d97c54e
TR-92: remove wc notices removal
apetrovici 665f524
TR-92: gateway config updates
apetrovici 8a92e9b
TR-92: hosted fields style changes
apetrovici c21358e
TR-92: add namespace
apetrovici b827d51
TR-92: add capture action only for authorize
apetrovici 32a024f
TR-92: disable add payment method if admin option not set to allow
apetrovici 7533e79
TR-92: updates styles and errors
apetrovici bf249bf
TR-92: bug fix toggle buttons only when gateway selected
apetrovici 2eb3508
TR-92: bug fix
apetrovici 73c3fa9
TR-92: display error thrown by init auth
apetrovici 1bdbd17
TR-92: update 3ds requests
apetrovici f16251b
TR-92: block form on place order submit
apetrovici b7c044d
TR-92: format refund amount
apetrovici 036054f
TR-92: fix bug
apetrovici 76292f0
TR-92: set country on config
apetrovici 359a8fc
TR-92: fix 3DS block on submit
apetrovici 8e7e55e
TR-92: bug fix for add payment method
apetrovici 617832b
TR-92: update readme
apetrovici 977ad13
TR-92: update readme
apetrovici b97ec1c
TR-92: no valdation for order pay
apetrovici 628ffd6
TR-92: Error: Your plugin and author URIs are the same
apetrovici dd37ec1
TR-92: bug fix uncaught exception
apetrovici c7bf126
TR-92: bug fix
apetrovici f393717
TR-92: remove 3DS check for add payment method
apetrovici 9d8030f
TR-92: bug fix remove notices from previous calls
apetrovici dd6951d
TR-92: add WP review feedback
apetrovici c8e076e
TR-92: include js scripts correctly
apetrovici File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
.globalpayments iframe { | ||
min-height: 3.6rem; | ||
} | ||
|
||
div[id^="GlobalPayments-overlay-"] { | ||
z-index: 1001 !important; | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,14 +4,16 @@ | |
$, | ||
wc_checkout_params, | ||
GlobalPayments, | ||
globalpayments_secure_payment_fields_params | ||
GlobalPayments3DS, | ||
globalpayments_secure_payment_fields_params, | ||
globalpayments_secure_payment_threedsecure_params | ||
) { | ||
/** | ||
* Frontend code for Global Payments in WooCommerce | ||
* | ||
* @param {object} options | ||
*/ | ||
function GlobalPaymentsWooCommerce(options) { | ||
function GlobalPaymentsWooCommerce( options, threeDSecureOptions ) { | ||
|
||
/** | ||
* Card form instance | ||
|
@@ -26,18 +28,37 @@ | |
* @type {string} | ||
*/ | ||
this.id = options.id; | ||
|
||
/** | ||
* Payment field options | ||
* | ||
* @type {object} | ||
*/ | ||
this.fieldOptions = options.field_options; | ||
|
||
/** | ||
* Payment gateway options | ||
* | ||
* @type {object} | ||
*/ | ||
this.gatewayOptions = options.gateway_options; | ||
|
||
/** | ||
* 3DS endpoints | ||
*/ | ||
this.threedsecure = threeDSecureOptions.threedsecure; | ||
|
||
/** | ||
* Order info | ||
*/ | ||
this.order = threeDSecureOptions.order; | ||
|
||
/** | ||
* | ||
* @type {null} | ||
*/ | ||
this.tokenResponse = null; | ||
|
||
this.attachEventHandlers(); | ||
}; | ||
|
||
|
@@ -64,12 +85,18 @@ | |
// Order Pay + Add payment method | ||
if ( $( document.body ).hasClass( 'woocommerce-order-pay' ) || $( 'form#add_payment_method' ).length > 0 ) { | ||
$( document ).ready( this.renderPaymentFields.bind( this ) ); | ||
if ( 'globalpayments_gpapi' === this.id) { | ||
$( document ).ready( this.threeDSSecure.bind( this ) ); | ||
} | ||
return; | ||
} | ||
|
||
// Checkout | ||
if ( wc_checkout_params.is_checkout ) { | ||
$( document.body ).on( 'updated_checkout', this.renderPaymentFields.bind( this ) ); | ||
if ( 'globalpayments_gpapi' === this.id) { | ||
$( document.body ).on( 'updated_checkout', this.threeDSSecure.bind( this ) ); | ||
} | ||
return; | ||
} | ||
}, | ||
|
@@ -198,7 +225,7 @@ | |
return; | ||
} | ||
|
||
console.log(response); | ||
this.tokenResponse = JSON.stringify(response); | ||
|
||
var that = this; | ||
|
||
|
@@ -232,6 +259,165 @@ | |
}); | ||
}, | ||
|
||
/** | ||
* Validate mandatory checkout fields | ||
* | ||
* @returns {boolean} | ||
*/ | ||
validateFields: function() { | ||
if ( ! $( '#billing_first_name' ).val() | ||
|| ! $( '#billing_last_name' ).val() | ||
|| ! $( '#billing_address_1' ).val() | ||
|| ! $( '#billing_city' ).val() | ||
|| ! $( '#billing_postcode' ).val() | ||
|| ! $( '#billing_phone' ).val() | ||
|| ! $( '#billing_email' ).val() ) { | ||
this.showPaymentError( 'Please fill in the required fields.' ); | ||
return false; | ||
} | ||
|
||
if ( ! this.isValidZipCode( $( '#billing_postcode' ).val() ) ) { | ||
this.showPaymentError( 'Billing ZIP is not a valid postcode / ZIP. ' ); | ||
return false; | ||
} | ||
|
||
return true; | ||
}, | ||
|
||
/** | ||
* Validate zipcode | ||
* | ||
* @param {String} zipcode | ||
* @return {Boolean} | ||
*/ | ||
isValidZipCode: function ( zipcode ) { | ||
let pattern = /^[a-zA-Z0-9-\s]{1,16}$/; | ||
|
||
return pattern.test(zipcode); | ||
}, | ||
|
||
/** | ||
* 3DS Process | ||
*/ | ||
threeDSSecure: function () { | ||
const { | ||
checkVersion, | ||
initiateAuthentication, | ||
ChallengeWindowSize, | ||
} = GlobalPayments.ThreeDSecure; | ||
|
||
const checkVersionButton = $( this.getPlaceOrderButtonSelector() ); | ||
if ( ! checkVersionButton ) { | ||
console.error( 'Warning! Place Order button cannot be loaded' ); | ||
return; | ||
} | ||
|
||
// handle 3DS 2.0 workflow | ||
const start3DS = async (e) => { | ||
e.preventDefault(); | ||
|
||
if ( wc_checkout_params.is_checkout && ! this.validateFields() ) { | ||
return; | ||
} | ||
|
||
try { | ||
versionCheckData = await checkVersion(this.threedsecure.checkEnrollmentUrl, { | ||
tokenResponse: this.tokenResponse, | ||
wcTokenId: $( 'input[name="wc-' + this.id + '-payment-token"]:checked', this.getForm() ).val(), | ||
amount: this.order.amount, | ||
currency: this.order.currency, | ||
challengeWindow: { | ||
windowSize: ChallengeWindowSize.Windowed500x600, | ||
displayMode: 'lightbox', | ||
hide: false, | ||
}, | ||
}); | ||
|
||
// Card holder not enrolled in 3D Secure, continue the WooCommerce flow. | ||
if (versionCheckData.enrolled === "NOT_ENROLLED") { | ||
$( this.getForm() ).submit(); | ||
return; | ||
} | ||
|
||
//Something went wrong with CheckEnrolment request on server side | ||
if (versionCheckData.error) { | ||
this.showPaymentError( versionCheckData.message ); | ||
return; | ||
} | ||
} catch ( e ) { | ||
console.error( e.reasons ); | ||
this.showPaymentError( e.reasons[0].message ); | ||
return; | ||
} | ||
|
||
if ( "ONE" === versionCheckData.version ) { | ||
this.createInputElement( 'serverTransId', versionCheckData.serverTransactionId ); | ||
this.createInputElement( 'PaRes', versionCheckData.challenge.response.data.PaRes ); | ||
$( this.getForm() ).submit(); | ||
return; | ||
} | ||
|
||
try { | ||
authenticationData = await initiateAuthentication(this.threedsecure.initiateAuthenticationUrl, { | ||
tokenResponse: this.tokenResponse, | ||
wcTokenId: $( 'input[name="wc-' + this.id + '-payment-token"]:checked', this.getForm() ).val(), | ||
versionCheckData: versionCheckData, | ||
challengeWindow: { | ||
windowSize: ChallengeWindowSize.Windowed500x600, | ||
displayMode: 'lightbox', | ||
}, | ||
order: this.order, | ||
}); | ||
|
||
switch (authenticationData.result) { | ||
case "SUCCESS_AUTHENTICATED": | ||
case "AUTHENTICATION_SUCCESSFUL": | ||
// frictionless authentication success | ||
this.createInputElement( 'serverTransId', authenticationData.serverTransactionId ); | ||
$( this.getForm() ).submit(); | ||
return; | ||
case "CHALLENGE_REQUIRED": | ||
// challenge authentication success | ||
if (authenticationData.challenge.response.data.transStatus == "Y") { | ||
this.createInputElement( 'serverTransId', versionCheckData.serverTransactionId); | ||
$( this.getForm() ).submit(); | ||
return; | ||
} | ||
// challenge authentication failure | ||
this.showPaymentError('3DS Authentication failed. Please try again!'); | ||
return; | ||
case "NOT_AUTHENTICATED": | ||
case "FAILED": | ||
default: | ||
this.showPaymentError('3DS Authentication failed. Please try again!'); | ||
return; | ||
} | ||
} catch (e) { | ||
console.error( e ); | ||
this.showPaymentError( e.reasons ); | ||
return; | ||
} | ||
|
||
return false; | ||
}; | ||
|
||
checkVersionButton.on('click', start3DS ); | ||
}, | ||
|
||
createInputElement: function ( name, value ) { | ||
var inputElement = (document.getElementById( this.id + '-' + name )); | ||
|
||
if ( ! inputElement) { | ||
inputElement = document.createElement( 'input' ); | ||
inputElement.id = this.id + '-' + name; | ||
inputElement.name = this.id + '[' + name + ']'; | ||
inputElement.type = 'hidden'; | ||
this.getForm().appendChild( inputElement ); | ||
} | ||
|
||
inputElement.value = value; | ||
}, | ||
|
||
/** | ||
* Places/submits the order to WooCommerce | ||
* | ||
|
@@ -307,6 +493,28 @@ | |
$( '.' + this.id + '.' + fieldType + ' .validation-error' ).show(); | ||
}, | ||
|
||
/** | ||
* Shows payment error and scrolls to it | ||
* | ||
* @param {string} message Error message | ||
* | ||
* @returns | ||
*/ | ||
showPaymentError: function ( message ) { | ||
var $form = $( this.getForm() ); | ||
|
||
this.unblockOnError(); | ||
|
||
// Remove notices from all sources | ||
$( '.woocommerce-error, .woocommerce-message' ).remove(); | ||
apetrovici marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
$form.prepend( '<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-updateOrderReview woocommerce-error">' + message + '</div>' ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are there any exposed WooCommerce JS methods for displaying error messages so we don't have to keep this in sync with WC? |
||
|
||
$( 'html, body' ).animate( { | ||
scrollTop: ( $form.offset().top - 100 ) | ||
}, 1000 ); | ||
}, | ||
|
||
/** | ||
* Handles errors from the payment field iframes | ||
* | ||
|
@@ -613,7 +821,7 @@ | |
} | ||
}; | ||
|
||
new GlobalPaymentsWooCommerce( globalpayments_secure_payment_fields_params ); | ||
new GlobalPaymentsWooCommerce( globalpayments_secure_payment_fields_params, globalpayments_secure_payment_threedsecure_params ); | ||
}( | ||
/** | ||
* Global `jQuery` reference | ||
|
@@ -633,10 +841,22 @@ | |
* @type {any} | ||
*/ | ||
(window).GlobalPayments, | ||
/** | ||
* Global `GlobalPayments` reference | ||
* | ||
* @type {any} | ||
*/ | ||
(window).GlobalPayments.ThreeDSecure, | ||
/** | ||
* Global `globalpayments_secure_payment_fields_params` reference | ||
* | ||
* @type {any} | ||
*/ | ||
(window).globalpayments_secure_payment_fields_params | ||
(window).globalpayments_secure_payment_fields_params, | ||
/** | ||
* Global `globalpayments_secure_payment_threedsecure_params` reference | ||
* | ||
* @type {any} | ||
*/ | ||
(window).globalpayments_secure_payment_threedsecure_params || {} | ||
)); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't use const/let, async/await, or arrow functions due to older browser incompatibilities (e.g. IE 11).