[php] Apple Pay-authorize.net은 샌드 박스가 작동하는 경우에만 오류 153을 반환합니다.

많은 기사를 검색 한 후 내 문제에 대한 해결책을 찾지 못했습니다.

내 사이트에 ApplePay 버튼을 통합 했으며 샌드 박스 모드에서 성공적으로 거래했습니다 . authorize.net PHP SDK를 사용하여 요청을 생성하고 있습니다. 라이브로 전환했을 때 문제가 시작되었습니다. authorize.net의 메시지는 ” 결제 데이터를 처리하는 중에 오류가 발생했습니다. 해독 된 데이터에서 필수 필드가 누락되었습니다

여기 내가 한 일 :

  1. live authorize.net 계정에서 결제 처리 인증서를 하나 변경했습니다.
  2. authorize.net 결제를 처리하는 데 사용하는 자격 증명을 결제 프로세스 인증서를 얻은 동일한 라이브 계정으로 변경했습니다.
  3. 실제 신용 카드로 라이브 애플 장치를 사용하십시오.
  4. 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로 인코딩되어야합니다.

답변