14

在搜索了很多文章后,我找不到解决我的问题的方法。

我在我的网站上集成了 ApplePay 按钮,并在沙盒模式下成功进行了交易。我正在使用 authorize.net php SDK 来生成请求。当我切换到生活时,问题就开始了。来自 authorize.net 的消息是“处理付款数据时出错。解密数据中缺少必填字段

这是我所做的:

  1. 将付款处理证书更改为来自 live authorize.net 帐户的证书
  2. 将我用于处理 authorize.net 付款的凭据更改为我获得付款流程证书的同一个真实账户
  3. 使用带有真实信用卡的实时苹果设备。
  4. 我正在使用 First data Nashville 处理器作为支持 ApplePay 的 CC 处理器

请注意,如果我切换回沙盒模式,事务将毫无问题地通过。

请求和失败的响应如下:

要求:

{ 
    "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) {
             ...
          }
       }
        ...
    }
    ...
}

编辑2:

我在请求中添加了电子邮件、电话和 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"
                }
            ]
        }
    }
}

}

4

2 回答 2

3

这很可能是由于来自 ApplePay 端的 OpaqueData 字段中的数据问题。所以我的建议是在日志文件中打印该令牌,然后使用以下库之一对其进行解密,以手动检查那里是否存在所有数据。您可以对 Sandbox 环境和 Live 环境执行相同的操作。因此,您将看到令牌数据的任何差异。

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>
于 2019-12-15T11:26:03.100 回答
0

正如这里提到的

有几件事要看:

  • 您输入到我们网站的 Apple 商家 ID 必须与您在 Apple 网站上创建的相同。如果不同,我们将无法解密支付数据。
  • 必须是电子商务交易。确认您的网关帐户设置为无卡帐户。
  • 提交的数据必须是 base64 编码的。据我所知,您这样做是对的,但请仔细检查。我不知道
    您返回的 BLOB 是否已经经过 base64 编码,但可能会仔细检查以确保您没有对其进行双重编码。
  • opaqueData字段不应该只是token.paymentData.data. 相反,它应该是一个Base64-encodedJSON 字符串,代表整个token.paymentData object.

处理付款数据时出错。

  • 必须指定两个不透明参数。
  • 您不能包含卡号或到期日期。
  • 您不能包含轨迹数据。
  • 必须是电子商务交易。确认您的网关帐户设置为无卡帐户。
  • 交易必须是授权或授权并捕获类型的交易。
  • 不能包含 3DS 数据。
  • 您必须提交可以成功解密的数据。
  • 解密后的数据必须属于提交请求的商家。
  • 提交的数据必须是 base64 编码的。
于 2019-12-13T08:42:38.567 回答