Проверка покупок (квитанций) Windows 8 с помощью PHP
Мне нужно проверить покупки в приложении, сделанные в приложениях Windows 8 на стороне сервера, используя PHP. Страница документации MSDN содержит пример только на C#. Прямо сейчас я потратил целый день на поиски способа сделать это на PHP. Безрезультатно. Во всем интернете есть только такие.ЧИСТЫЕ примеры по этой теме.
Я нашел некоторую частичную информацию о подписанном XML и x509, некоторых библиотеках (xmlseclibs - бесполезно, использует функции openssl_*, которые не поддерживают sha256; phpseclib - выглядит многообещающе, но их документация и примеры плохи без какой-либо помощи).
Возможно ли это как-то сделать, не изучив все о подписанном XML, RSA и x509? Прямо сейчас я прочитал почти все, но везде есть информация только о кодировке. Ничего о проверке.
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
}
Говори за себя. Мне нравится подход phpseclib "создайте свой собственный пример" к документации.
Тем не менее, я не думаю, что phpseclib действительно можно использовать в этом случае. Итак, у вас есть тег SignatureValue. Но что скрывает эта подпись? Что касается подписей XML, я понимаю, что подпись охватывает нормализованную форму XML. xmlseclibs нормализует XML-документ, но phpseclib этого не делает, так как это крипто-библиотека, а не XML-библиотека.