많은 기사를 검색 한 후 내 문제에 대한 해결책을 찾지 못했습니다.
내 사이트에 ApplePay 버튼을 통합 했으며 샌드 박스 모드에서 성공적으로 거래했습니다 . authorize.net PHP SDK를 사용하여 요청을 생성하고 있습니다. 라이브로 전환했을 때 문제가 시작되었습니다. authorize.net의 메시지는 ” 결제 데이터를 처리하는 중에 오류가 발생했습니다. 해독 된 데이터에서 필수 필드가 누락되었습니다 “
여기 내가 한 일 :
- live authorize.net 계정에서 결제 처리 인증서를 하나 변경했습니다.
- authorize.net 결제를 처리하는 데 사용하는 자격 증명을 결제 프로세스 인증서를 얻은 동일한 라이브 계정으로 변경했습니다.
- 실제 신용 카드로 라이브 애플 장치를 사용하십시오.
- ApplePay를 지원하는 CC 프로세서로 First data Nashville 프로세서를 사용하고 있습니다.
샌드 박스 모드로 다시 전환하면 트랜잭션이 문제없이 전달됩니다.
요청과 실패한 응답은 다음과 같습니다.
의뢰:
{
"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"
}
]
}
}
}
}
응답:
{
"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."
}
]
}
}
내가 무엇을 놓치고 있습니까?
편집하다:
다음은 ApplePay에서 opaqueData 전송에 관한 코드입니다
$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 :
동일한 결과로 요청에 이메일과 전화 및 IP 주소를 추가했습니다. 수정 된 요청은 다음과 같습니다.
{
"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"
}
]
}
}
}
}
답변
이것은 아마도 ApplePay 측에서 오는 OpaqueData 필드의 데이터 문제 때문일 것입니다. 그래서 내 제안은 해당 토큰을 로그 파일로 인쇄 한 다음 다음 라이브러리 중 하나를 사용하여 동일한 암호를 해독하여 모든 데이터가 있는지 수동으로 확인하는 것입니다. 샌드 박스 환경과 라이브 환경 모두에 대해 동일한 작업을 수행 할 수 있습니다. 따라서 토큰 데이터에 차이가 있습니다.
https://github.com/PayU-EMEA/apple-pay
https://github.com/etsy/applepay-php
이것이 etsy applepay-php 라이브러리를 사용하는 방법 입니다.
Apple의 ‘지급 처리 인증서’와 개인 키가 필요합니다 (아래의 merch.cer 및 priv.p12 참조). Apple의 개발자 센터에서이를 생성 할 수 있습니다. 최종 사용자 장치에서 생성 된 지불 토큰 예제와 생성 된 타임 스탬프도 필요합니다. RSA 암호화 토큰은 다음과 같아야합니다.
{
"data": "<base64>",
"header": {
"applicationData": "<hex_optional>"
"wrappedKey": "<base64>",
"publicKeyHash": "<base64>",
"transactionId": "<hex>"
},
"signature": "<base64>",
"version": "RSA_v1"
}
데모
$ # 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>
답변
여기에 언급 된 바와 같이
살펴볼 사항 :
- 당사 사이트에 입력 한 Apple 판매자 ID는 Apple 사이트에서 생성 한 Apple 판매자 ID와 동일해야합니다. 다른 경우 결제 데이터를 해독 할 수 없습니다.
- 전자 상거래 여야합니다. 게이트웨이 계정이 카드가없는 계정으로 설정되어 있는지 확인하십시오.
- 제출 된 데이터는 base64로 인코딩되어야합니다. 내가 알 수있는 한, 당신은 올바르게하고 있지만 다시 확인하십시오.
돌아 오는 BLOB 가 이미 base64로 인코딩되어 있는지 알 수 없지만 더블 인코딩하지 않는지 다시 확인하십시오.
- opaqueData 필드는 그냥해서는 안됩니다
token.paymentData.data
. 오히려Base64-encoded
전체를 나타내는 JSON 문자열 이어야합니다token.paymentData object
.
결제 데이터를 처리하는 중에 오류가 발생했습니다.
- 두 불투명 매개 변수를 모두 지정해야합니다.
- 카드 번호 나 만료 날짜를 포함 할 수 없습니다.
- 트랙 데이터는 포함 할 수 없습니다.
- 전자 상거래 여야합니다. 게이트웨이 계정이 존재하지 않는 카드 계정으로 설정되어 있는지 확인하십시오.
- 거래는 승인 또는 거래 유형을 승인하고 캡처해야합니다.
- 3DS 데이터는 포함 할 수 없습니다.
- 성공적으로 해독 할 수있는 데이터를 제출해야합니다.
- 해독 된 데이터는 요청을 제출 한 판매자에게 속해야합니다.
- 제출 된 데이터는 base64로 인코딩되어야합니다.