After searching a lot of articles i couldn't find a solution for my problem.
I have integrated ApplePay button on my site and successfuly made transactions in sandbox mode. I'm using authorize.net php SDK to generate the request. The problems started when i switched to live. The message from authorize.net is "There was an error processing the payment data. Required fields are missing from decrypted data"
Here what i have done:
Note that if i switch back to sandbox mode, the transaction passes without issues.
The request and the failed response follows:
Request:
{
"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"
}
]
}
}
}
}
Response:
{
"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."
}
]
}
}
What am i missing?
EDIT:
Here is the code regarding sending opaqueData from 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:
I added email and phone and ip address in the request with same result. The modified request follows:
{
"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"
}
]
}
}
}
}
This is most probably due to a data issue in OpaqueData field which comes from ApplePay side. So my suggestion is to print that token in logfile, then decrypt the same using one of the following libraries to manually check whether all data present there. You can do the same for both the Sandbox environment and Live environment. So you will see any difference in token data.
https://github.com/PayU-EMEA/apple-pay
https://github.com/etsy/applepay-php
This is how it does using etsy applepay-php library.
You'll need a 'Payment Processing Certificate' and a private key from Apple (referred to as merch.cer and priv.p12 below). You can generate these at Apple's Dev Center. You'll also need an example payment token generated on an end-user device and the timestamp at which it was generated. An RSA-encrypted token should look like this:
{
"data": "<base64>",
"header": {
"applicationData": "<hex_optional>"
"wrappedKey": "<base64>",
"publicKeyHash": "<base64>",
"transactionId": "<hex>"
},
"signature": "<base64>",
"version": "RSA_v1"
}
Demo
$ # 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>
Please tell me how to set up Apple Pay transactions via Authorize.net in PHP? I'm going to use the sample code provided by the official Authorize.net documentation
. You used it too. But I don't understand if this code is enough to do everything? Or does it need to be supplemented with something, for example, JavaScript code? And where can I get the dataValue for the request? They write that it is generated based on the Apple Pay JSON token. But where can I get this token?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With