GoPymes's Blog

Woocommerce : Actualizar order review mediante AJAX en el checkout page – Parte 1

order view mediante ajax

No sé si se han dado cuenta que cuando eliges otra pasarela de pago, eliges otro pais u otro departamento en tu página checkout, la tabla “order review” se actualiza mediante AJAX.

Debido a que toda tienda tiene sus propias reglas de negocio, es necesario, a veces, agregar algún impuesto, algún costo de envío, o quizas un descuento dependiendo de la información proporcionada (pais de envío, tipo de pasarela de pago, etc), para ello queremos que el order view se actualice a nuestras necesidades y conveniencia.

El encargado de capturar y enviar la información necesaria para ser procesada mediante ajax es checkout.min.js, el cual también se encarga de recibir la data resultante y reemplazarla en el “order view
No voy a explicar todo el proceso que hace checkout.min.js ya que se encarga de muchas cosas más, pero si quieren ver el código en forma ordenada, vean su versión developer llamado checkout.js que es lo mismo.

URL: http://{TUWEB}/wp-content/plugins/woocommerce/assets/js/frontend/checkout.min.js

Los pasos que explico son a partir de Woocoommerce 2.2.x para arriba, ya que para versiones anteriores a 2.1.x el checkout.min.js tiene diferente estructura, ya sabes como woothemes le gusta cambiar cosas de una versión a otra.

Ventana del Order View

“Order View” se compone de 2 partes, la parte de costos y las pasarelas de pago, aquí una imágen.

order view

 

Observando a checkout.js

Observando un poco del código de checkout.js rescatamos:

1
this.$checkout_form.on( 'input change', 'select.shipping_method, input[name^=shipping_method], #ship-to-different-address input, .update_totals_on_change select, .update_totals_on_change input[type=radio]', this.trigger_update_checkout );

 

Este pequeño código hace referencia al evento “change” que se refiere a cuando cambia de valor algo, es aplicado casi siempre a input tipo “SELECT” y si te das cuenta a la derecha, explica los inputs que espera realicen el evento “change”, entre ellos el que vamos a rescatar es “.update_totals_on_change select” ya que en nuestro ejemplo vamos a usar un “SELECT”

 

En conclusión: Si un input del tipo “.update_totals_on_change select” realiza un evento “change”, este script empieza a funcionar.


Como ven, este script llama a la funcion “trigger_update_checkout” y este a su ves llama a “update_checkout” y para finalizar lo que nos interesa es el llamado a “update_checkout_action” el cual tiene la llamada AJAX via POST, y también coloca el resultado en el “order view”.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
update_checkout_action: function() {
if ( wc_checkout_form.xhr ) {
wc_checkout_form.xhr.abort();
}

if ( $( 'form.checkout' ).size() === 0 ) {
return;
}

var shipping_methods = [];

$( 'select.shipping_method, input[name^=shipping_method][type=radio]:checked, input[name^=shipping_method][type=hidden]' ).each( function( index, input ) {
shipping_methods[ $( this ).data( 'index' ) ] = $( this ).val();
} );

var payment_method = $( '#order_review input[name=payment_method]:checked' ).val(),
country = $( '#billing_country' ).val(),
state = $( '#billing_state' ).val(),
postcode = $( 'input#billing_postcode' ).val(),
city = $( '#billing_city' ).val(),
address = $( 'input#billing_address_1' ).val(),
address_2 = $( 'input#billing_address_2' ).val(),
s_country,
s_state,
s_postcode,
s_city,
s_address,
s_address_2;

if ( $( '#ship-to-different-address input' ).is( ':checked' ) ) {
s_country = $( '#shipping_country' ).val();
s_state = $( '#shipping_state' ).val();
s_postcode = $( 'input#shipping_postcode' ).val();
s_city = $( '#shipping_city' ).val();
s_address = $( 'input#shipping_address_1' ).val();
s_address_2 = $( 'input#shipping_address_2' ).val();
} else {
s_country = country;
s_state = state;
s_postcode = postcode;
s_city = city;
s_address = address;
s_address_2 = address_2;
}

$( '.woocommerce-checkout-payment, .woocommerce-checkout-review-order-table' ).block({
message: null,
overlayCSS: {
background: '#fff',
opacity: 0.6
}
});

var data = {
action: 'woocommerce_update_order_review',
security: wc_checkout_params.update_order_review_nonce,
shipping_method: shipping_methods,
payment_method: payment_method,
country: country,
state: state,
postcode: postcode,
city: city,
address: address,
address_2: address_2,
s_country: s_country,
s_state: s_state,
s_postcode: s_postcode,
s_city: s_city,
s_address: s_address,
s_address_2: s_address_2,
post_data: $( 'form.checkout' ).serialize()
};

wc_checkout_form.xhr = $.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: data,
success: function( data ) {
// Always update the fragments
if ( data && data.fragments ) {
$.each( data.fragments, function ( key, value ) {
$( key ).replaceWith( value );
$( key ).unblock();
} );
}

// Check for error
if ( 'failure' == data.result ) {

var $form = $( 'form.checkout' );

if ( 'true' === data.reload ) {
window.location.reload();
return;
}

$( '.woocommerce-error, .woocommerce-message' ).remove();

// Add new errors
if ( data.messages ) {
$form.prepend( data.messages );
} else {
$form.prepend( data );
}

// Lose focus for all fields
$form.find( '.input-text, select' ).blur();

// Scroll to top
$( 'html, body' ).animate( {
scrollTop: ( $( 'form.checkout' ).offset().top - 100 )
}, 1000 );

}

// Trigger click e on selected payment method
$( '.woocommerce-checkout' ).find( 'input[name=payment_method]:checked' ).trigger( 'click' );

// Fire updated_checkout e
$( 'body' ).trigger( 'updated_checkout' );
}

});
},

El post se ha hecho muy largo, vamos a dejarlo aqui por mientras y continuamos en una 2da parte donde mostraremos la parte frontend.

 

Leave a Reply

Your email address will not be published. Required fields are marked *