我需要验证使用PHP在Windows 8应用程序的服务器端做出应用内购买。 MSDN的文档页面只有在C#中的例子。 现在我已经寻找一种方式来做到这一点在PHP中度过了一整天。 没有成功。 所有在互联网上有关于这个主题只有.NET的例子。
我发现关于签署XML和X509的一些部分信息,一些库(xmlseclibs - 没用,使用openssl_ *功能不支持SHA256; phpseclib - 看起来很有希望,但他们的文档和例子是穷人没有帮助)。
是否有可能做到这一点不知何故没有了解签名的XML,RSA和X509的一切吗? 现在我读过几乎一切,但处处是只有编码信息。 一无所知验证。
我设法使用验证WP8 IAP收据xmlseclibs库。
另外,你需要支持PHP卷曲。
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的标准化形式。 xmlseclibsnormalizes一个XML文档,但phpseclib并不因为它是一个加密的lib - 不是一个XML库。