Apple Pay: authorize.net devuelve el error 153 solo cuando está activo, sandbox funciona

14

Después de buscar muchos artículos, no pude encontrar una solución para mi problema.

He integrado el botón ApplePay en mi sitio y he realizado transacciones con éxito en modo sandbox . Estoy usando authorize.net php SDK para generar la solicitud. Los problemas comenzaron cuando me cambié a vivir. El mensaje de authorize.net es " Hubo un error al procesar los datos de pago. Faltan campos obligatorios en los datos descifrados "

Aquí lo que he hecho:

  1. Cambió el certificado de procesamiento de pagos con uno de la cuenta live authorize.net
  2. Cambié las credenciales que estoy usando para procesar pagos de authorize.net a la misma cuenta real en la que obtuve el certificado de proceso de pago
  3. Use un dispositivo Apple con tarjeta de crédito real.
  4. Estoy usando el procesador First Data Nashville como procesador CC que admite ApplePay

Tenga en cuenta que si vuelvo al modo sandbox, la transacción se realiza sin problemas.

La solicitud y la respuesta fallida son las siguientes:

Solicitud:

{ 
    "createTransactionRequest":{ 
        "merchantAuthentication":{ 
            "name":"xxxxxxxxx",
            "transactionKey":"xxxxxxxxxxx"
        },
        "clientId":"sdk-php-2.0.0",
        "refId":"ref1575669789",
        "transactionRequest":{ 
            "transactionType":"authOnlyTransaction",
            "amount":"14.08",
            "payment":{ 
                "opaqueData":{ 
                    "dataDescriptor":"COMMON.APPLE.INAPP.PAYMENT",
                    "dataValue":"eyJ2ZXJzaW9u...Q1OSJ9fQ=="
                }
            },
            "order":{ 
                "invoiceNumber":"63059-191206",
                "description":"xxxxxxxxx, xxxxxxxxxxxx v9.0.12 (Order# 63059-191206)"
            },
            "customer":{ 
                "type":"individual",
                "email":""
            },
            "billTo":{ 
                "firstName":"xxxxxxx",
                "lastName":"xxxxxxx",
                "address":"xxxx San Remo Cir ",
                "city":"Vista",
                "state":"CA",
                "zip":"92084",
                "country":"US"
            },
            "retail":{ 
                "marketType":0,
                "deviceType":8
            },
            "transactionSettings":{ 
                "setting":[ 
                    { 
                        "settingName":"duplicateWindow",
                        "settingValue":"60"
                    }
                ]
            }
        }
    }
}

Respuesta:

{
    "transactionResponse":{
        "responseCode":"3",
        "authCode":"",
        "avsResultCode":"P",
        "cvvResultCode":"",
        "cavvResultCode":"",
        "transId":"0",
        "refTransID":"",
        "transHash":"",
        "testRequest":"0",
        "accountNumber":"",
        "accountType":"",
        "errors":[
            {
                "errorCode":"153",
                "errorText":"There was an error processing the payment data. Required fields are missing from decrypted data."
            }
        ],
        "transHashSha2":"",
        "SupplementalDataQualificationIndicator":0
    },
    "refId":"ref1575669789",
    "messages":{
        "resultCode":"Error",
        "message":[
            {
                "code":"E00027",
                "text":"The transaction was unsuccessful."
            }
        ]
    }
}

¿Qué me estoy perdiendo?

EDITAR:

Aquí está el código con respecto al envío de opaqueData desde ApplePay

$transactionMode = $cc_authorize_mode == $this->MODE_TEST ? \net\authorize\api\constants\ANetEnvironment::SANDBOX : \net\authorize\api\constants\ANetEnvironment::PRODUCTION;
$merchantAuthentication = new AnetAPI\MerchantAuthenticationType();
$merchantAuthentication->setName($cc_authorize_loginid);
$merchantAuthentication->setTransactionKey($cc_authorize_txnkey);

// Set the transaction's refId
$refId = 'ref' . time();
$phoneNumber = ! empty($co_b_phone) ? $co_b_phone : $co_phone;
$customerEmail = ! empty($co_b_email) ? $co_b_email : $co_email;
$ip = lloader()->getUtilByName('ip')->getClientIp();

// Create order information
$order = new AnetAPI\OrderType();
$order->setInvoiceNumber($order_number);
$order->setDescription($this->getOrderPostedByMessage($id_order, $order_number));

// Set the customer's Bill To address
$customerAddress = new AnetAPI\CustomerAddressType();
$customerAddress->setFirstName($co_ccholder_firstname);
$customerAddress->setLastName($co_ccholder_lastname);
if (! empty($co_b_company)) { $customerAddress->setCompany($co_b_company); }
$customerAddress->setAddress($co_b_address." ".$co_b_address2);
$customerAddress->setCity($co_b_city);
$bState = f_isUSState($co_b_state) ? $STATES_XX[$co_b_state] : $STATES[$co_b_state];
$customerAddress->setState($bState);
$customerAddress->setZip($co_b_zip);
$customerAddress->setCountry($countriesISO2[$co_country]);
$customerAddress->setPhoneNumber($phoneNumber);
$customerAddress->setEmail($customerEmail);

// Set the customer's identifying information
$customerData = new AnetAPI\CustomerDataType();
$customerData->setType("individual");
if ( ! empty($member_row['id'])) { $customerData->setId($member_row['id']); }
$customerData->setEmail($customerEmail);


// Add values for transaction settings
$duplicateWindowSetting = new AnetAPI\SettingType();
$duplicateWindowSetting->setSettingName("duplicateWindow");
$duplicateWindowSetting->setSettingValue("60");

// Create a TransactionRequestType object and add the previous objects to it
$transactionRequestType = new AnetAPI\TransactionRequestType();
$transactionRequestType->setCustomerIP($ip);
$transactionRequestType->setTransactionType($this->api_trtype_map[$transactionType]);
if (empty($this->applePayPaymentData)) {
            // Normal CC request
            // Create the payment data for a credit card
            ...
} else {
    $retail = new AnetAPI\TransRetailInfoType();
    $retail->setMarketType('0');
    $retail->setDeviceType('8');
    $transactionRequestType->setRetail($retail);

    // Apple Pay Token Request
    $op = new AnetAPI\OpaqueDataType();
    $op->setDataDescriptor("COMMON.APPLE.INAPP.PAYMENT");
    $paymentToken = base64_encode($this->applePayPaymentData);
    $op->setDataValue($paymentToken);
    $payment = new AnetAPI\PaymentType();
    $payment->setOpaqueData($op);
}

$transactionRequestType->setAmount($grandTotal);
$transactionRequestType->setOrder($order);
$transactionRequestType->setPayment($payment);
$transactionRequestType->setBillTo($customerAddress);
$transactionRequestType->setCustomer($customerData);
$transactionRequestType->addToTransactionSettings($duplicateWindowSetting);

// Assemble the complete transaction request
$request = new AnetAPI\CreateTransactionRequest();
$request->setMerchantAuthentication($merchantAuthentication);
$request->setRefId($refId);
$request->setTransactionRequest($transactionRequestType);

// Create the controller and get the response
$controller = new AnetController\CreateTransactionController($request);
$response = $controller->executeWithApiResponse($transactionMode);
if ($response != null) {
    if ($response->getMessages()->getResultCode() == "Ok") {
       ...
       if ($tresponse != null && $tresponse->getMessages() != null) {
          ...
          return true;
       } else {
          if ($tresponse->getErrors() != null) {
             ...
          }
       }
        ...
    }
    ...
}

EDIT2:

Agregué correo electrónico y teléfono y dirección IP en la solicitud con el mismo resultado. La solicitud modificada sigue:

{ 
"createTransactionRequest":{ 
    "merchantAuthentication":{ 
        "name":"**********",
        "transactionKey":"***************"
    },
    "clientId":"sdk-php-2.0.0",
    "refId":"ref1576180306",
    "transactionRequest":{ 
        "transactionType":"authOnlyTransaction",
        "amount":"14.08",
        "payment":{ 
            "opaqueData":{ 
                "dataDescriptor":"COMMON.APPLE.INAPP.PAYMENT",
                "dataValue":"eyJ2ZXJzaW9uIj...DFiZiJ9fQ=="
            }
        },
        "order":{ 
            "invoiceNumber":"63117-191212",
            "description":"******************* v9.0.12 (Order# 63117-191212)"
        },
        "customer":{ 
            "type":"individual",
            "email":"*********@gmail.com"
        },
        "billTo":{ 
            "firstName":"Gabe",
            "lastName":"Garcia",
            "address":"********* Cir ",
            "city":"Vista",
            "state":"CA",
            "zip":"92084",
            "country":"US",
            "phoneNumber":"**************",
            "email":"**********@gmail.com"
        },
        "customerIP":"************",
        "retail":{ 
            "marketType":"0",
            "deviceType":"8"
        },
        "transactionSettings":{ 
            "setting":[ 
                { 
                    "settingName":"duplicateWindow",
                    "settingValue":"60"
                }
            ]
        }
    }
}

}

bksi
fuente
1
¿Intentaste regenerar certificados?
Mully
1
Sí, regeneré los certificados de procesamiento de pagos una docena de veces, incluso recreé la identidad del comerciante en la cuenta de Apple.
bksi
1
transactionRequest -> customer -> el correo electrónico está vacío, es posible que sea necesario configurarlo, ¿se puede configurar a pedido?
Jannes Botis
1
¿Puedes publicar el código relacionado con la configuración del campo "opaqueData"? Donde debería estar el token codificado en base64 recibido de la billetera ApplePay.
DinushaNT
2
@Roadowl cuál es el problema. Edité la publicación. Tenga en cuenta que el mismo código funciona en modo sandbox. También se genera la solicitud y se puede ver. No hace mucho con la forma en que se genera, creo.
bksi

Respuestas:

3

Esto probablemente se deba a un problema de datos en el campo OpaqueData que proviene del lado ApplePay. Entonces, mi sugerencia es imprimir ese token en el archivo de registro, luego descifrarlo usando una de las siguientes bibliotecas para verificar manualmente si todos los datos están allí. Puede hacer lo mismo tanto para el entorno Sandbox como para el entorno Live. Entonces verá cualquier diferencia en los datos de token.

https://github.com/PayU-EMEA/apple-pay

https://github.com/etsy/applepay-php


Así es como se hace usando la biblioteca etsy applepay-php .

Necesitará un 'Certificado de procesamiento de pagos' y una clave privada de Apple (denominada merch.cer y priv.p12 a continuación). Puede generarlos en el Centro de desarrollo de Apple. También necesitará un token de pago de ejemplo generado en un dispositivo de usuario final y la marca de tiempo en la que se generó. Un token cifrado con RSA debería verse así:

{
 "data": "<base64>",
 "header": {
     "applicationData": "<hex_optional>"
     "wrappedKey": "<base64>",
     "publicKeyHash": "<base64>",
     "transactionId": "<hex>"
 },
 "signature": "<base64>",
 "version": "RSA_v1"
}

Manifestación

$ # Copy in your payment processing cert and test token
$ cd examples
$ cp /secret/place/merch.cer .
$ cp /secret/place/token.json .
$
$ # Extract private key from cert
$ openssl pkcs12 -export -nocerts -inkey merch.key -out priv.p12 -password 'pass:'
$
$ # Get intermediate and root certs from Apple
$ wget -O int.cer 'https://www.apple.com/certificateauthority/AppleAAICAG3.cer'
$ wget -O root.cer 'https://www.apple.com/certificateauthority/AppleRootCA-G3.cer'
$
$ # Verify chain of trust
$ openssl x509 -inform DER -in merch.cer -pubkey > pub.pem
$ openssl x509 -inform DER -in root.cer > root.pem
$ openssl x509 -inform DER -in int.cer > int_merch.pem
$ openssl x509 -inform DER -in merch.cer >> int_merch.pem
$ openssl verify -verbose -CAfile root.pem int_merch.pem # should output OK
$
$ # Run demo
$ cd ..
$ php -denable_dl=on -dextension=`pwd`/modules/applepay.so examples/decrypt.php -p <privkey_pass> -c examples/token.json -t <time_of_transaction>
DinushaNT
fuente
Sí, ese es mi próximo paso. Tengo que generar mis certificados de procesamiento de pagos para poder hacerlo.
bksi
@bksi, ¿podrías descifrar los tokens?
DinushaNT
Lamentablemente todavía no. Estoy intentando usar github.com/PayU-EMEA/apple-pay
bksi
-1

Como se menciona aquí

Un par de cosas para mirar:

  • La ID de comerciante de Apple que ingrese en nuestro sitio debe ser idéntica a la que creó en el sitio de Apple. Si es diferente, no podremos descifrar los datos de pago.
  • Debe ser una transacción de comercio electrónico. Confirme que su cuenta de puerta de enlace esté configurada como una cuenta sin tarjeta.
  • Los datos enviados deben estar codificados en base64. Por lo que puedo decir, lo estás haciendo bien, pero vuelve a comprobarlo. No sé si el BLOB
    que está recuperando ya está codificado en base64, pero tal vez verifique dos veces para asegurarse de que no lo esté codificando dos veces.
  • El campo opaqueData NO debe ser justo token.paymentData.data. Más bien, debería ser una Base64-encodedcadena JSON que represente la totalidad token.paymentData object.

Se produjo un error al procesar los datos de pago.

  • Se deben especificar ambos parámetros opacos.
  • No puede incluir el número de tarjeta o la fecha de vencimiento.
  • No puede incluir datos de seguimiento.
  • Debe ser una transacción de comercio electrónico. Confirme que su cuenta de puerta de enlace esté configurada como una cuenta de Tarjeta no presente.
  • La transacción debe ser autorización o autorización y capturar el tipo de transacción.
  • No puede incluir datos 3DS.
  • Debe enviar datos que puedan descifrarse con éxito.
  • Los datos descifrados deben pertenecer al comerciante que envía la solicitud.
  • Los datos enviados deben estar codificados en base64.
Vignesh Kumar A
fuente
Gracias por las sugerencias Todos ellos se aplican. No estoy seguro de que haya notado que todas las transacciones pasan cuando está en modo sandbox. Creé una identificación de comerciante completamente nueva y la usé para las transacciones con el mismo resultado. Luego probé la misma identificación nuevamente en sandbox y las transacciones están pasando.
bksi
@bksi He actualizado la respuesta. Asegúrese de haber completado todas las listas de verificación y aún enfrenta el problema, luego intente Rehacer todo el proceso desde la creación de un nuevo identificador de paquete, ID de comerciante, registrándolo en el ID de paquete y en el portal de autorización, generando una nueva CSR desde el portal de autorización y crear un nuevo certificado de procesamiento de pagos en el desarrollador de Apple y usar el tipo de pago 3DS
Vignesh Kumar A