Проверка покупок (квитанций) Windows 8 с помощью PHP


Мне нужно проверить покупки в приложении, сделанные в приложениях Windows 8 на стороне сервера, используя PHP. Страница документации MSDN содержит пример только на C#. Прямо сейчас я потратил целый день на поиски способа сделать это на PHP. Безрезультатно. Во всем интернете есть только такие.ЧИСТЫЕ примеры по этой теме.

Я нашел некоторую частичную информацию о подписанном XML и x509, некоторых библиотеках (xmlseclibs - бесполезно, использует функции openssl_*, которые не поддерживают sha256; phpseclib - выглядит многообещающе, но их документация и примеры плохи без какой-либо помощи).

Возможно ли это как-то сделать, не изучив все о подписанном XML, RSA и x509? Прямо сейчас я прочитал почти все, но везде есть информация только о кодировке. Ничего о проверке.

Author: neubert, 2012-12-02

2 answers

Мне удалось проверить получение WP8 IAP с помощью библиотеки xmlseclibs.

Кроме того, вам нужно включить php curl.

do {
    $doc = new DOMDocument();

    $xml = $_POST['receipt_data']; // your receipt xml here!

    // strip unwanted chars - IMPORTANT!!!
    $xml = str_replace(array("\n","\t", "\r"), "", $xml);
    //some (probably mostly WP8) receipts have unnecessary spaces instead of tabs
    $xml = preg_replace('/\s+/', " ", $xml);
    $xml = str_replace("> <", "><", $xml);

    $doc->loadXML($xml);
    $receipt = $doc->getElementsByTagName('Receipt')->item(0);
    $certificateId = $receipt->getAttribute('CertificateId');

    $ch = curl_init("https://lic.apps.microsoft.com/licensing/certificateserver/?cid=$certificateId");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);

    $publicKey = curl_exec($ch);
    $errno = curl_errno($ch);
    $errmsg = curl_error($ch);
    curl_close($ch);

    if ($errno != 0) {
        $verifyFailed = true;
        break;
    }

    // Verify xml signature
    require('./xmlseclibs.php');
    $objXMLSecDSig = new XMLSecurityDSig();
    $objDSig = $objXMLSecDSig->locateSignature($doc);
    if (!$objDSig) {
        $verifyFailed = true;
        break;
    }
    try {
        $objXMLSecDSig->canonicalizeSignedInfo();
        $retVal = $objXMLSecDSig->validateReference();
        if (!$retVal) {
            throw new Exception("Error Processing Request", 1);
        }
        $objKey = $objXMLSecDSig->locateKey();
        if (!$objKey) {
            throw new Exception("Error Processing Request", 1);
        }
        $key = NULL;
        $objKeyInfo = XMLSecEnc::staticLocateKeyInfo($objKey, $objDSig);
        if (! $objKeyInfo->key && empty($key)) {
            $objKey->loadKey($publicKey);
        }
        if (!$objXMLSecDSig->verify($objKey)) {
            throw new Exception("Error Processing Request", 1);
        }
    } catch (Exception $e) {
        $verifyFailed = true;
        break;
    }

    $productReceipt = $doc->getElementsByTagName('ProductReceipt')->item(0);
    $prodictId = $productReceipt->getAttribute('ProductId');
    $purchaseDate = $productReceipt->getAttribute('PurchaseDate');
} while(0);

if ($verifyFailed) {
    // invalid receipt
} else {
    // valid receipt
}
 1
Author: Stackia, 2014-06-23 14:21:43

Говори за себя. Мне нравится подход phpseclib "создайте свой собственный пример" к документации.

Тем не менее, я не думаю, что phpseclib действительно можно использовать в этом случае. Итак, у вас есть тег SignatureValue. Но что скрывает эта подпись? Что касается подписей XML, я понимаю, что подпись охватывает нормализованную форму XML. xmlseclibs нормализует XML-документ, но phpseclib этого не делает, так как это крипто-библиотека, а не XML-библиотека.

 -1
Author: neubert, 2012-12-03 22:37:43