¿Cómo funciona el proceso de firmado?

  • Para validar que la información sea enviada desde la persona que corresponda, esta se verifica a través de una firma generada por el algoritomo HMAC SHA256.
    • Para generar esta firma se necesita una Clave Electrónica Token Secret que es generada al crear el servicio en Pago Fácil.
    • Como bien dice su nombre, esta clave ES SECRETA y no debe ser compartida con nadie, ya que esto podría causar que la información del estado de la transacción no sea fidedigna hacia el comercio.
    • Este proceso no es complejo pero es importante seguir los pasos en orden para que no se vuelva frustrante.

Proceso de Firmado

  • Se debe de obtener un arreglo con todas las variables que comiencen con x_ desde el body del POST
  • Este arreglo se debe de ordenar de manera alfabética.
  • Una vez obtenido el arreglo, se crea un string con todas las variables y sus valores concatenados.
  • El string resultante se firma con el algoritmo SHA256 mencionado anteriormente.

Ejemplos de código para firmado

Los siguientes códigos no ignoran objetos, por lo que, se le deben pasar sólo los parámetros de la transacción que figuran como obligatorios.

const crypto = require('crypto');

function signPayload(payload, secret, prefix = "x_", signature = "signature") {
  
    //El arreglo SIEMPRE debe de estar ordenado antes de firmar.
    let sortedArray = Object.entries(payload).sort();
    
    let payloadFirmado = "";
    let firma = prefix + signature;
    let mensaje = "";
  
    for (let index = 0; index < sortedArray.length; index++) {
        console.log(sortedArray[index]);
        if (sortedArray[index][0] != firma) {
            mensaje += sortedArray[index][0] + sortedArray[index][1];
        }
    }
  
    let hmac = crypto.createHmac('sha256', secret);
    hmac.setEncoding('hex');
    hmac.write(mensaje);
    hmac.end();
    payloadFirmado = hmac.read();
    return payloadFirmado;
}
const crypto = require('crypto-js');

function signPayload(payload, secret, prefix = "x_", signature = "signature") {
    //El arreglo SIEMPRE debe de estar ordenado antes de firmar.
    let sortedArray = Object.entries(payload).sort();
    
    let payloadFirmado = "";
    let firma = prefix + signature;
    let mensaje = "";
  
    for (let index = 0; index < sortedArray.length; index++) {
        console.log(sortedArray[index]);
        if (sortedArray[index][0] != firma) {
            mensaje += sortedArray[index][0] + sortedArray[index][1];
        }
    }
  
    let hash = crypto.HmacSHA256(mensaje, secret);
    payloadFirmado = hash.toString(crypto.enc.Hex);
    return payloadFirmado;
}
def sign(fields, key=@key)
    Digest::HMAC.hexdigest(fields.sort.join, key, Digest::SHA256)
  end
function firmarArreglo($arreglo) {
    //Ordeno Arreglo
    ksort($arreglo);
    //Concateno Arreglo
    $mensaje = $this->concatenarArreglo($arreglo);
    //Firmo Mensaje
    $mensajeFirmado = $this->firmarMensaje($mensaje, $this->ct_token_secret);
    //Guardo y retorno el mensaje firmado
    $this->ct_firma = $mensajeFirmado;
    return $mensajeFirmado;
}
function firmarMensaje($mensaje, $claveCifrado) {
    $mensajeFirmado = hash_hmac('sha256', $mensaje, $claveCifrado);
    return $mensajeFirmado;
}
public function concatenarArreglo($arreglo) {
    $resultado = "";
    foreach ($arreglo as $field => $value) {
        $resultado .= $field . $value;
    }
    return $resultado;
}
<?php
require_once(__DIR__ . '/vendor/autoload.php');
use PSTPagoFacil\SignatureHelper; //using Pago Fácil SignatureHelper Library


$tokenService = 'TOKEN_SERVICE'; // put your Token Service here
$tokenSecret = 'TOKEN_SECRET';  // put your Token Secret here
$x_reference = (int) microtime(true); //Just a random number as an example 
$x_session_id = (int) microtime(true); //Just a random number as an example 
$sHelper = new SignatureHelper($tokenSecret);

// Building the trx

$trxBody = [
    "x_account_id"=> $tokenService,
    "x_amount"=> 1000,
    "x_currency"=> "CLP",
    "x_reference"=> $x_reference,
    "x_customer_email"=> "[email protected]",
     "x_url_complete"=> "https://postman-echo.com/post",
    "x_url_cancel"=> "https://postman-echo.com/post",
    "x_url_callback"=> "https://postman-echo.com/post",
     "x_shop_country"=> "CL",
    "x_session_id"=> "$x_session_id"
];

// Signing trx with 

$firma = $sHelper->signPayload($trxBody);
$x_signature = $sHelper->signPayload($trxBody);
$trxBody["x_signature"] = $x_signature;

// Posting Signed trx with Pago Fácil SignatureHelper Library
$payload = json_encode($trxBody);
// print_r($payload); //payload ready to be sent

$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://apis-dev.pgf.cl/trxs",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => $payload,
  CURLOPT_HTTPHEADER => [
    "Accept: application/json",
    "Content-Type: application/json"
  ],
]);

// Requesting the Response
$response = curl_exec($curl);

$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
    $jsonResponse = json_decode($response);

    print_r ($jsonResponse); //here you can see the JSON Response Object

/*  0 gateway
    1 webpay
    2 khipu max 5mm
    3 multicaja error
    4 pago 46
    5 mach
*/

    // $url = $jsonResponse->data->payUrl[0]->url; // here you choose your payUrl
    // echo $url,"\n\n";
}
import requests
import hashlib
import hmac
import json
import time
import webbrowser
import tokens
import pprint


encoding = 'utf-8'
x_account_id = tokens.tokenServiceDev #Put your Token Service
x_amount = str(b'1000', encoding)
x_currency = str(b'CLP', encoding)
x_reference = str(time.time()) #Just a random number as an example 
x_customer_email = str(b'[email protected]', encoding)
x_url_complete = str(b'https://www.pagofacil.cl', encoding)
x_url_cancel = str(b'https://www.pagofacil.cl', encoding)
x_url_callback = str(b'https://callback.domain.com', encoding)
x_shop_country = str(b'CL', encoding)
x_session_id = str(b'1', encoding) #Just a random number as an example 



object='x_account_id'+x_account_id+'x_amount'+x_amount+'x_currency'+x_currency+'x_customer_email'+x_customer_email+'x_reference'+x_reference+'x_session_id'+x_session_id+'x_shop_country'+x_shop_country+'x_url_callback'+x_url_callback+'x_url_cancel'+x_url_cancel+'x_url_complete'+x_url_complete
payload = object.encode('utf-8')
key = tokens.tokenSecretDev #Put your Token Secret


# Generate the hash.
signature = hmac.new(key,payload,hashlib.sha256).hexdigest()
x_signature =  signature
url = tokens.dev # Put the Enviroment Endpoint (dev or Prod)
payload = {
  'x_account_id' : x_account_id ,
  'x_amount' : int(x_amount), 
  'x_currency' : x_currency, 
  'x_reference' : x_reference , 
  'x_customer_email' : x_customer_email, 
  'x_url_complete' : x_url_complete, 
  'x_url_cancel' : x_url_cancel, 
  'x_url_callback' : x_url_callback ,
  'x_shop_country' : x_shop_country, 
  'x_session_id' : x_session_id, 
  'x_signature' : x_signature 
}

jpayload = json.dumps(payload)
headers = {
    'accept': "application/json",
    'content-type': "application/json"
    }

response = requests.request("POST", url, data=jpayload, headers=headers)
"""
0 gateway
1 webpay
2 khipu max 5mm
3 multicaja
4 pago 46
5 mach
"""
chosenPayUrl = response.json()['data']['payUrl'][0]['url']  # here you choose your payUrl
pprint.pprint(response.json())#Here you can see the response
webbrowser.open(chosenPayUrl)


Recuerda que puedes unirte a nuestra comunidad de desarrolladores en Discord!