{"id":9,"date":"2023-07-21T01:38:02","date_gmt":"2023-07-21T01:38:02","guid":{"rendered":"https:\/\/bitacora.lado.mx\/?p=9"},"modified":"2023-07-21T14:53:54","modified_gmt":"2023-07-21T14:53:54","slug":"crear-un-plugin-de-una-pasarela-de-pago-con-woocommerce","status":"publish","type":"post","link":"https:\/\/bitacora.lado.mx\/index.php\/2023\/07\/21\/crear-un-plugin-de-una-pasarela-de-pago-con-woocommerce\/","title":{"rendered":"Crear un plugin de una pasarela de pago con WooCommerce"},"content":{"rendered":"\n<p>Empecemos el tutorial de pasarela de pago.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><strong>Paso 1<\/strong>: Comenzamos creando un plugin<\/p>\n\n\n\n<p>En caso de que no lo sepas, los m\u00e9todos de pago personalizados son simplemente plugins. Por lo tanto, tenemos que crear uno.<\/p>\n\n\n\n<p>Para crear un plugin solo necesitas crear un archivo y agregar un par de l\u00edneas de c\u00f3digo dentro de \u00e9l.<\/p>\n\n\n\n<p>As\u00ed que, en la carpeta \/plugins, cre\u00e9 un archivo llamado misha-gateway.php y agregu\u00e9 el siguiente c\u00f3digo all\u00ed. En caso de que tu plugin tenga m\u00e1s de un archivo, col\u00f3calo en una carpeta con el mismo nombre, por ejemplo: misha-gateway\/misha-gateway.php.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php<br>\/*<br> * Plugin Name: WooCommerce Custom Payment Gateway<br> * Plugin URI: https:\/\/rudrastyh.com\/woocommerce\/payment-gateway-plugin.html<br> * Description: Acepta pagos con tarjeta de cr\u00e9dito en tu tienda.<br> * Author: Misha Rudrastyh<br> * Author URI: http:\/\/rudrastyh.com<br> * Version: 1.0.1<br> *\/<br><br><\/code><\/pre>\n\n\n\n<p>Una vez que lo hayas hecho, \u00a1el plugin aparecer\u00e1 en tu \u00e1rea de administraci\u00f3n! E incluso puedes activarlo.<\/p>\n\n\n\n<p>Paso 2: Las pasarelas de pago son clases de PHP. Aqu\u00ed est\u00e1 el esqueleto de la clase.<\/p>\n\n\n\n<p>As\u00ed que tenemos que crear una clase PHP personalizada para extender la clase WC_Payment_Gateway de WooCommerce.<\/p>\n\n\n\n<p>Cada m\u00e9todo de clase se describe a continuaci\u00f3n. Puedes comenzar copiando y pegando el siguiente c\u00f3digo en tu archivo principal del plugin.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/*\n * Este gancho de acci\u00f3n registra nuestra clase PHP como una pasarela de pago de WooCommerce\n *\/\nadd_filter( 'woocommerce_payment_gateways', 'misha_add_gateway_class' );\nfunction misha_add_gateway_class( $gateways ) {\n\t$gateways&#91;] = 'WC_Misha_Gateway'; \/\/ aqu\u00ed va el nombre de tu clase\n\treturn $gateways;\n}\n\n\/*\n * La propia clase, ten en cuenta que est\u00e1 dentro del gancho de acci\u00f3n plugins_loaded\n *\/\nadd_action( 'plugins_loaded', 'misha_init_gateway_class' );\nfunction misha_init_gateway_class() {\n\n\tclass WC_Misha_Gateway extends WC_Payment_Gateway {\n\n\t\t\/**\n\t\t * Constructor de la clase, m\u00e1s sobre esto en el Paso 3\n\t\t *\/\n\t\tpublic function __construct() {\n\n\t\t...\n\n\t\t}\n\n\t\t\/**\n\t\t * Opciones del plugin, las veremos en el Paso 3 tambi\u00e9n\n\t\t *\/\n\t\tpublic function init_form_fields(){\n\n\t\t...\n\t\n\t\t}\n\n\t\t\/**\n\t\t * Lo necesitar\u00e1s si deseas tu propio formulario personalizado para la tarjeta de cr\u00e9dito, el Paso 4 trata sobre esto\n\t\t *\/\n\t\tpublic function payment_fields() {\n\n\t\t...\n\t\t\t\t \n\t\t}\n\n\t\t\/*\n\t\t * CSS y JS personalizados, generalmente solo se requieren cuando decides tener un formulario personalizado para la tarjeta de cr\u00e9dito\n\t\t *\/\n\t\tpublic function payment_scripts() {\n\n\t\t...\n\t\n\t\t}\n\n\t\t\/*\n\t\t * Validaci\u00f3n de campos, m\u00e1s en el Paso 5\n\t\t *\/\n\t\tpublic function validate_fields() {\n\n\t\t...\n\n\t\t}\n\n\t\t\/*\n\t\t * Aqu\u00ed procesamos los pagos, todo sobre esto en el Paso 5\n\t\t *\/\n\t\tpublic function process_payment( $order_id ) {\n\n\t\t...\n\t\t\t\t\t\n\t\t}\n\n\t\t\/*\n\t\t * En caso de que necesites un webhook, como PayPal IPN, etc.\n\t\t *\/\n\t\tpublic function webhook() {\n\n\t\t...\n\t\t\t\t\t\n\t\t}\n\t}\n}<\/code><\/pre>\n\n\n\n<p>Si insertas el c\u00f3digo anterior &#8220;tal cual&#8221; en tu archivo del plugin, obtendr\u00e1s un error 500, porque este c\u00f3digo simplemente muestra la estructura de la clase del plugin, donde cada m\u00e9todo deber\u00eda estar.<\/p>\n\n\n\n<p>Paso 3: Opciones del Plugin de la Pasarela de Pago<\/p>\n\n\n\n<p>En el constructor de la clase:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Definimos las propiedades de la clase, como el ID y el nombre de la pasarela, l\u00edneas 23-33.<\/li>\n\n\n\n<li>Inicializamos la configuraci\u00f3n, l\u00edneas 35-39.<\/li>\n\n\n\n<li>Agregamos opciones a las propiedades de la clase, l\u00edneas 40-45.<\/li>\n\n\n\n<li>Guardamos las opciones, l\u00ednea 48.<\/li>\n\n\n\n<li>Agregamos JavaScript y CSS personalizados si es necesario, l\u00ednea 51.<\/li>\n<\/ul>\n\n\n\n<p>Tambi\u00e9n podemos registrar webhooks de la pasarela de pago en el constructor de la clase.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public function __construct() {\n\n\t$this-&gt;id = 'misha'; \/\/ ID del plugin de la pasarela de pago\n\t$this-&gt;icon = ''; \/\/ URL del icono que se mostrar\u00e1 en la p\u00e1gina de pago junto al nombre de tu pasarela\n\t$this-&gt;has_fields = true; \/\/ en caso de que necesites un formulario personalizado para la tarjeta de cr\u00e9dito\n\t$this-&gt;method_title = 'Misha Gateway';\n\t$this-&gt;method_description = 'Descripci\u00f3n de la pasarela de pago Misha'; \/\/ se mostrar\u00e1 en la p\u00e1gina de opciones\n\n\t\/\/ las pasarelas pueden admitir suscripciones, reembolsos, m\u00e9todos de pago guardados,\n\t\/\/ pero en este tutorial comenzaremos con pagos simples\n\t$this-&gt;supports = array(\n\t\t'products'\n\t);\n\n\t\/\/ M\u00e9todo con todos los campos de opciones\n\t$this-&gt;init_form_fields();\n\n\t\/\/ Cargar las configuraciones.\n\t$this-&gt;init_settings();\n\t$this-&gt;title = $this-&gt;get_option( 'title' );\n\t$this-&gt;description = $this-&gt;get_option( 'description' );\n\t$this-&gt;enabled = $this-&gt;get_option( 'enabled' );\n\t$this-&gt;testmode = 'yes' === $this-&gt;get_option( 'testmode' );\n\t$this-&gt;private_key = $this-&gt;testmode ? $this-&gt;get_option( 'test_private_key' ) : $this-&gt;get_option( 'private_key' );\n\t$this-&gt;publishable_key = $this-&gt;testmode ? $this-&gt;get_option( 'test_publishable_key' ) : $this-&gt;get_option( 'publishable_key' );\n\n\t\/\/ Este gancho de acci\u00f3n guarda las configuraciones\n\tadd_action( 'woocommerce_update_options_payment_gateways_' . $this-&gt;id, array( $this, 'process_admin_options' ) );\n\n\t\/\/ Necesitamos JavaScript personalizado para obtener un token\n\tadd_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );\n\t\n\t\/\/ Tambi\u00e9n puedes registrar un webhook aqu\u00ed\n\t\/\/ add_action( 'woocommerce_api_{nombre_del_webhook}', array( $this, 'webhook' ) );\n}\n\npublic function init_form_fields(){\n\n\t$this-&gt;form_fields = array(\n\t\t'enabled' =&gt; array(\n\t\t\t'title'       =&gt; 'Habilitar\/Deshabilitar',\n\t\t\t'label'       =&gt; 'Habilitar Pasarela Misha',\n\t\t\t'type'        =&gt; 'checkbox',\n\t\t\t'description' =&gt; '',\n\t\t\t'default'     =&gt; 'no'\n\t\t),\n\t\t'title' =&gt; array(\n\t\t\t'title'       =&gt; 'T\u00edtulo',\n\t\t\t'type'        =&gt; 'text',\n\t\t\t'description' =&gt; 'Esto controla el t\u00edtulo que el usuario ve durante el proceso de pago.',\n\t\t\t'default'     =&gt; 'Tarjeta de cr\u00e9dito',\n\t\t\t'desc_tip'    =&gt; true,\n\t\t),\n\t\t'description' =&gt; array(\n\t\t\t'title'       =&gt; 'Descripci\u00f3n',\n\t\t\t'type'        =&gt; 'textarea',\n\t\t\t'description' =&gt; 'Esto controla la descripci\u00f3n que el usuario ve durante el proceso de pago.',\n\t\t\t'default'     =&gt; 'Paga con tu tarjeta de cr\u00e9dito a trav\u00e9s de nuestra s\u00faper genial pasarela de pago.',\n\t\t),\n\t\t'testmode' =&gt; array(\n\t\t\t'title'       =&gt; 'Modo de prueba',\n\t\t\t'label'       =&gt; 'Habilitar modo de prueba',\n\t\t\t'type'        =&gt; 'checkbox',\n\t\t\t'description' =&gt; 'Activar el modo de prueba usando claves API de prueba.',\n\t\t\t'default'     =&gt; 'yes',\n\t\t\t'desc_tip'    =&gt; true,\n\t\t),\n\t\t'test_publishable_key' =&gt; array(\n\t\t\t'title'       =&gt; 'Clave p\u00fablica de prueba',\n\t\t\t'type'        =&gt; 'text'\n\t\t),\n\t\t'test_private_key' =&gt; array(\n\t\t\t'title'       =&gt; 'Clave privada de prueba',\n\t\t\t'type'        =&gt; 'password',\n\t\t),\n\t\t'publishable_key' =&gt; array(\n\t\t\t'title'       =&gt; 'Clave p\u00fablica en vivo',\n\t\t\t'type'        =&gt; 'text'\n\t\t),\n\t\t'private_key' =&gt; array(\n\t\t\t'title'       =&gt; 'Clave privada en vivo',\n\t\t\t'type'        =&gt; 'password'\n\t\t)\n\t);\n}\n\n<\/code><\/pre>\n\n\n\n<p>Paso 4: Formulario de Pago Directo<\/p>\n\n\n\n<p>Antes de implementar el c\u00f3digo a continuaci\u00f3n, por favor lee estos puntos clave:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Si est\u00e1s creando una pasarela de pago como PayPal, donde todas las acciones del usuario ocurren en el sitio web de la pasarela de pago, puedes omitir este paso, simplemente no agregues los m\u00e9todos payment_fields() y validate_fields() y contin\u00faa con el Paso 5.<\/li>\n\n\n\n<li>En este tutorial, asumimos que est\u00e1s utilizando un procesador de pagos que env\u00eda los datos de la tarjeta con su propia solicitud AJAX y te proporciona un token que puedes usar en PHP, as\u00ed que \u00a1no! agregues los atributos &#8220;name&#8221; a los campos del formulario de la tarjeta. As\u00ed es como funciona el proceso paso a paso:\n<ol class=\"wp-block-list\">\n<li>El cliente completa los datos de la tarjeta y hace clic en &#8220;Realizar Pedido&#8221;.<\/li>\n\n\n\n<li>Retrasamos el env\u00edo del formulario utilizando el evento checkout_place_order en WooCommerce y enviamos una solicitud AJAX con los datos de la tarjeta directamente a nuestro procesador de pagos.<\/li>\n\n\n\n<li>Si los detalles del cliente son correctos, el procesador devuelve un token y lo agregamos a nuestro formulario.<\/li>\n\n\n\n<li>Ahora podemos enviar el formulario (\u00a1en JS, por supuesto!).<\/li>\n\n\n\n<li>Usamos el token en PHP para capturar un pago a trav\u00e9s de la API del procesador de pagos.<\/li>\n<\/ol>\n<\/li>\n<\/ul>\n\n\n\n<p>4.1. Agregar scripts en cola<\/p>\n\n\n\n<p>En el Paso 2 ya hemos agregado el gancho de acci\u00f3n wp_enqueue_scripts y conectado el m\u00e9todo payment_scripts() a \u00e9l.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public function payment_scripts() {\n\n\t\/\/ solo necesitamos JavaScript para procesar un token en las p\u00e1ginas de carrito y pago, \u00bfverdad?\n\tif ( ! is_cart() &amp;&amp; ! is_checkout() &amp;&amp; ! isset( $_GET&#91;'pay_for_order'] ) ) {\n\t\treturn;\n\t}\n\n\t\/\/ si nuestra pasarela de pago est\u00e1 deshabilitada, tampoco tenemos que encolar JS\n\tif ( 'no' === $this-&gt;enabled ) {\n\t\treturn;\n\t}\n\n\t\/\/ no es necesario trabajar con los detalles de la tarjeta sin SSL a menos que tu sitio web est\u00e9 en modo de prueba\n\tif ( ! $this-&gt;testmode &amp;&amp; ! is_ssl() ) {\n\t\treturn;\n\t}\n\n\t\/\/ supongamos que es nuestro JavaScript del procesador de pagos que permite obtener un token\n\twp_enqueue_script( 'misha_js', 'https:\/\/www.mishapayments.com\/api\/token.js' );\n\n\t\/\/ y este es nuestro JS personalizado en el directorio de tu plugin que funciona con token.js\n\twp_register_script( 'woocommerce_misha', plugins_url( 'misha.js', __FILE__ ), array( 'jquery', 'misha_js' ) );\n\n\t\/\/ en la mayor\u00eda de los procesadores de pagos, tienes que usar la CLAVE P\u00daBLICA para obtener un token\n\twp_localize_script( 'woocommerce_misha', 'misha_params', array(\n\t\t'publishableKey' =&gt; $this-&gt;publishable_key\n\t) );\n\n\twp_enqueue_script( 'woocommerce_misha' );\n\n}\n\n<\/code><\/pre>\n\n\n\n<p>4.2. Obtener un token en JavaScript<\/p>\n\n\n\n<p>Antes que nada, quiero decir que para cada procesador de pagos, este c\u00f3digo podr\u00eda ser diferente, pero la idea principal es la misma. Aqu\u00ed est\u00e1 el contenido de tu archivo misha.js:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>var successCallback = function(data) {\n\n\tvar checkout_form = $( 'form.woocommerce-checkout' );\n\n\t\/\/ agregar un token a nuestro campo de entrada oculto\n\t\/\/ console.log(data) para encontrar el token\n\tcheckout_form.find('#misha_token').val(data.token);\n\n\t\/\/ desactivar el evento checkout_place_order\n\tcheckout_form.off( 'checkout_place_order', tokenRequest );\n\n\t\/\/ enviar el formulario ahora\n\tcheckout_form.submit();\n\n};\n\nvar errorCallback = function(data) {\n    console.log(data);\n};\n\nvar tokenRequest = function() {\n\n\t\/\/ aqu\u00ed estar\u00e1 la funci\u00f3n de la pasarela de pago que procesa todos los datos de la tarjeta desde tu formulario,\n\t\/\/ tal vez necesite tu Clave API p\u00fablica que est\u00e1 en misha_params.publishableKey\n\t\/\/ y activa successCallback() en caso de \u00e9xito y errorCallback en caso de error\n\treturn false;\n\t\t\n};\n\njQuery(function($){\n\n\tvar checkout_form = $( 'form.woocommerce-checkout' );\n\tcheckout_form.on( 'checkout_place_order', tokenRequest );\n\n});\n\n<\/code><\/pre>\n\n\n\n<p>4.3. Formulario con datos de la tarjeta<\/p>\n\n\n\n<p>Con el m\u00e9todo payment_fields() de la clase, puedes crear un formulario de pago con los campos de la tarjeta de cr\u00e9dito de esta manera:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public function payment_fields() {\n \n\t\/\/ bien, vamos a mostrar una descripci\u00f3n antes del formulario de pago\n\tif ( $this-&gt;description ) {\n\t\t\/\/ puedes agregar instrucciones para el modo de prueba, es decir, n\u00fameros de tarjetas de prueba, etc.\n\t\tif ( $this-&gt;testmode ) {\n\t\t\t$this-&gt;description .= ' MODO DE PRUEBA HABILITADO. En el modo de prueba, puedes usar los n\u00fameros de tarjeta enumerados en la &lt;a href=\"#\"&gt;documentaci\u00f3n&lt;\/a&gt;.';\n\t\t\t$this-&gt;description  = trim( $this-&gt;description );\n\t\t}\n\t\t\/\/ mostrar la descripci\u00f3n con etiquetas &lt;p&gt; etc.\n\t\techo wpautop( wp_kses_post( $this-&gt;description ) );\n\t}\n \n\t\/\/ Voy a usar echo() para mostrar el formulario, pero puedes cerrar las etiquetas PHP y mostrarlo directamente en HTML\n\techo '&lt;fieldset id=\"wc-' . esc_attr( $this-&gt;id ) . '-cc-form\" class=\"wc-credit-card-form wc-payment-form\" style=\"background:transparent;\"&gt;';\n \n\t\/\/ Agregar este gancho de acci\u00f3n si deseas que tu pasarela de pago personalizada lo admita\n\tdo_action( 'woocommerce_credit_card_form_start', $this-&gt;id );\n \n\t\/\/ Recomiendo usar IDs \u00fanicos, porque otras pasarelas podr\u00edan estar usando #ccNo, #expdate, #cvc\n\techo '&lt;div class=\"form-row form-row-wide\"&gt;&lt;label&gt;N\u00famero de tarjeta &lt;span class=\"required\"&gt;*&lt;\/span&gt;&lt;\/label&gt;\n\t\t&lt;input id=\"misha_ccNo\" type=\"text\" autocomplete=\"off\"&gt;\n\t\t&lt;\/div&gt;\n\t\t&lt;div class=\"form-row form-row-first\"&gt;\n\t\t\t&lt;label&gt;Fecha de vencimiento &lt;span class=\"required\"&gt;*&lt;\/span&gt;&lt;\/label&gt;\n\t\t\t&lt;input id=\"misha_expdate\" type=\"text\" autocomplete=\"off\" placeholder=\"MM \/ AA\"&gt;\n\t\t&lt;\/div&gt;\n\t\t&lt;div class=\"form-row form-row-last\"&gt;\n\t\t\t&lt;label&gt;C\u00f3digo de tarjeta (CVC) &lt;span class=\"required\"&gt;*&lt;\/span&gt;&lt;\/label&gt;\n\t\t\t&lt;input id=\"misha_cvv\" type=\"password\" autocomplete=\"off\" placeholder=\"CVC\"&gt;\n\t\t&lt;\/div&gt;\n\t\t&lt;div class=\"clear\"&gt;&lt;\/div&gt;';\n \n\tdo_action( 'woocommerce_credit_card_form_end', $this-&gt;id );\n \n\techo '&lt;div class=\"clear\"&gt;&lt;\/div&gt;&lt;\/fieldset&gt;';\n \n}\n\n<\/code><\/pre>\n\n\n\n<p>Paso 5: Procesar pagos<\/p>\n\n\n\n<p>5.1. Validar campos<\/p>\n\n\n\n<p>S\u00e9 que los campos de la p\u00e1gina de pago, como el nombre, deben validarse antes, pero esto es solo un ejemplo:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public function validate_fields(){\n \n\tif( empty( $_POST&#91; 'billing_first_name' ]) ) {\n\t\twc_add_notice(  '\u00a1Se requiere el nombre!', 'error' );\n\t\treturn false;\n\t}\n\treturn true;\n \n}\n<\/code><\/pre>\n\n\n\n<p>5.2. Capturar pagos con la API y establecer el estado del pedido<\/p>\n\n\n\n<p>Prep\u00e1rate para mucho texto \ud83d\ude43<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Una vez que obtengas el objeto de pedido con la funci\u00f3n wc_get_order(), puedes usar sus m\u00e9todos como get_billing_first_name(), get_billing_country(), get_billing_address_1(), etc., para obtener los detalles de facturaci\u00f3n y env\u00edo del cliente (por cierto, puedes encontrar todos los m\u00e9todos en includes\/class-wc-order.php, que est\u00e1 en la carpeta del plugin WooCommerce). Tambi\u00e9n puedes obtener los detalles de facturaci\u00f3n desde la matriz $_POST; en el momento de escribir este tutorial, no estoy seguro de cu\u00e1l es mejor.<\/li>\n\n\n\n<li>Puedes agregar notas al pedido con el m\u00e9todo $order-&gt;add_order_note(), puede ser notas para el cliente (se mostrar\u00e1n en el \u00e1rea de miembros) y notas privadas (solo en las p\u00e1ginas de edici\u00f3n de pedidos).<\/li>\n\n\n\n<li>Notas del pedido en las p\u00e1ginas de edici\u00f3n de pedidos.<\/li>\n\n\n\n<li>En este tutorial, consideramos el uso de pagos directos sin ir a los sitios web de las pasarelas de pago. Pero si, para tus prop\u00f3sitos, los clientes deben ir a un sitio web de pasarela de pago para completar su pago, debes omitir el Paso 4 y, en este paso, en lugar de capturar los pagos con wp_remote_post(), utiliza add_query_arg() para construir una URL de redireccionamiento correcta a la p\u00e1gina de pago de la pasarela de pago.<\/li>\n\n\n\n<li>Usa $order-&gt;get_total() para obtener el monto del pedido.<\/li>\n\n\n\n<li>No olvides cambiar $this-&gt;testmode en la url a 0 o 1 seg\u00fan corresponda.<\/li>\n\n\n\n<li>Despu\u00e9s de enviar una solicitud a la pasarela de pago, verifica la respuesta para ver si el pago se realiz\u00f3 correctamente. En mi caso, puedo verificarlo de esta manera: $response[&#8216;response&#8217;][&#8216;code&#8217;] == 200 &amp;&amp; $response[&#8216;response&#8217;][&#8216;message&#8217;] == &#8216;OK&#8217; (si uso wp_remote_post() para enviar una solicitud a la pasarela de pago, esta es la \u00fanica forma de verificar si la pasarela respondi\u00f3 correctamente). Si usas la API de WooCommerce REST, revisa la respuesta y toma la decisi\u00f3n adecuada.<\/li>\n\n\n\n<li>Si la respuesta de la pasarela de pago es correcta, actualiza el estado del pedido a &#8220;completado&#8221; y no lo redirijas a ninguna parte.<\/li>\n\n\n\n<li>En caso de que la respuesta de la pasarela de pago no sea la esperada, muestra un mensaje de error al cliente y no actualices el estado del pedido.<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>public function process_payment( $order_id ) {\n\n\tglobal $woocommerce;\n\n\t$order = wc_get_order( $order_id );\n\n\t\/\/ no dudes en agregar cualquier tipo de datos personalizados aqu\u00ed\n\t\/\/ no estoy seguro de cu\u00e1l es mejor - obtener el nombre desde el objeto de pedido o desde la matriz $_POST\n\t$customer_first_name = $_POST&#91; 'billing_first_name' ];\n\t$customer_country = $order-&gt;get_billing_country();\n\t$customer_address = $order-&gt;get_billing_address_1();\n\n\t\/\/ URL de la pasarela de pago (ejemplo)\n\t$url = 'https:\/\/example.com\/api\/charge';\n\n\t\/\/ Datos que enviaremos a la pasarela de pago\n\t$data = array(\n\t\t'customer_name'    =&gt; $customer_first_name,\n\t\t'customer_country' =&gt; $customer_country,\n\t\t'customer_address' =&gt; $customer_address,\n\t\t'amount'           =&gt; $order-&gt;get_total(),\n\t\t'token'            =&gt; $_POST&#91; 'misha_token' ]\n\t);\n\n\t\/\/ Aqu\u00ed enviamos una solicitud a la pasarela de pago\n\t$response = wp_remote_post( $url, array(\n\t\t'method'    =&gt; 'POST',\n\t\t'timeout'   =&gt; 90,\n\t\t'sslverify' =&gt; true,\n\t\t'headers'   =&gt; array(\n\t\t\t'Authorization' =&gt; 'Basic ' . base64_encode( $this-&gt;private_key . ':' ) \/\/ Otra opci\u00f3n: 'api_key' =&gt; $this-&gt;private_key,\n\t\t),\n\t\t'body'      =&gt; $data\n\t) );\n\n\tif ( is_wp_error( $response ) ) {\n\t\tthrow new Exception( __( 'Hubo un error al procesar su pago. Int\u00e9ntelo de nuevo.', 'misha' ) );\n\t}\n\n\tif ( 200 != wp_remote_retrieve_response_code( $response ) ) {\n\t\tthrow new Exception( __( 'Hubo un error al procesar su pago. Int\u00e9ntelo de nuevo.', 'misha' ) );\n\t}\n\n\t$response = json_decode( wp_remote_retrieve_body( $response ) );\n\n\t\/\/ Si la respuesta de la pasarela de pago es correcta, actualizamos el estado del pedido a \"completado\"\n\tif ( 'succeeded' === $response-&gt;status ) {\n\n\t\t\/\/ pagar el pedido (aqu\u00ed y despu\u00e9s de actualizar el estado del pedido)\n\t\t$order-&gt;payment_complete();\n\n\t\t\/\/ a\u00f1adir nota\n\t\t$order-&gt;add_order_note(\n\t\t\t'\u00a1Gracias por su pago! Recibimos ' . $response-&gt;amount . ' ' . $response-&gt;currency . '. ID de transacci\u00f3n: ' . $response-&gt;id\n\t\t);\n\n\t\t\/\/ quitar carrito\n\t\t$woocommerce-&gt;cart-&gt;empty_cart();\n\n\t\t\/\/ redirigir a la p\u00e1gina de confirmaci\u00f3n del pedido\n\t\treturn array(\n\t\t\t'result'   =&gt; 'success',\n\t\t\t'redirect' =&gt; $this-&gt;get_return_url( $order )\n\t\t);\n\n\t} else {\n\n\t\t\/\/ agregar una nota de error, esto no se muestra al cliente\n\t\t$order-&gt;add_order_note(\n\t\t\t'ERROR: transacci\u00f3n fallida con ID de transacci\u00f3n ' . $response-&gt;id\n\t\t);\n\n\t\t\/\/ devuelve un error si el pago no se pudo procesar\n\t\tthrow new Exception( __( 'Hubo un error al procesar su pago. Int\u00e9ntelo de nuevo.', 'misha' ) );\n\n\t}\n\n}\n<\/code><\/pre>\n\n\n\n<p>Eso es! Si sigues este tutorial paso a paso, deber\u00edas obtener tu pasarela de pago personalizada y funcional. Toma en cuenta que este es solo un ejemplo y, en realidad, puede haber m\u00e1s desaf\u00edos durante el proceso de desarrollo. Tambi\u00e9n recuerda que el c\u00f3digo del procesador de pagos real puede ser diferente, y necesitar\u00e1s adaptarlo en consecuencia.<\/p>\n\n\n\n<p>Espero que esto te ayude a crear tu propia pasarela de pago personalizada para WooCommerce. \u00a1Buena suerte en tu proyecto! Si tienes alguna pregunta o necesitas m\u00e1s ayuda, no dudes en preguntar. \u00a1Feliz desarrollo!<\/p>\n\n\n\n<p>Tomado en parte de: https:\/\/rudrastyh.com\/woocommerce\/payment-gateway-plugin.html<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Empecemos el tutorial de pasarela de pago. Paso 1: Comenzamos creando un plugin En caso de que no lo sepas, los m\u00e9todos de pago personalizados son simplemente plugins. Por lo tanto, tenemos que crear uno. Para crear un plugin solo necesitas crear un archivo y agregar un par de l\u00edneas de c\u00f3digo dentro de \u00e9l. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-9","post","type-post","status-publish","format-standard","hentry","category-woocommerce"],"_links":{"self":[{"href":"https:\/\/bitacora.lado.mx\/index.php\/wp-json\/wp\/v2\/posts\/9","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bitacora.lado.mx\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bitacora.lado.mx\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bitacora.lado.mx\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bitacora.lado.mx\/index.php\/wp-json\/wp\/v2\/comments?post=9"}],"version-history":[{"count":3,"href":"https:\/\/bitacora.lado.mx\/index.php\/wp-json\/wp\/v2\/posts\/9\/revisions"}],"predecessor-version":[{"id":14,"href":"https:\/\/bitacora.lado.mx\/index.php\/wp-json\/wp\/v2\/posts\/9\/revisions\/14"}],"wp:attachment":[{"href":"https:\/\/bitacora.lado.mx\/index.php\/wp-json\/wp\/v2\/media?parent=9"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bitacora.lado.mx\/index.php\/wp-json\/wp\/v2\/categories?post=9"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bitacora.lado.mx\/index.php\/wp-json\/wp\/v2\/tags?post=9"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}