5

PHPを使用してサーバー側でWindows8アプリケーションで行われたアプリ内購入を確認する必要があります。MSDNのドキュメントページには、C#でのみ例があります。今、私はPHPでそれを行う方法を探して一日を過ごしました。失敗。インターネット全体で、このトピックに関する.NETの例のみがあります。

署名されたXMLとx509、いくつかのライブラリに関するいくつかの部分的な情報を見つけました(xmlseclibs-役に立たない、sha256をサポートしないopenssl_*関数を使用します;phpseclib-有望に見えますが、それらのドキュメントと例は助けがなく貧弱です)。

署名されたXML、RSA、x509についてすべてを学ぶことなく、どういうわけかそれを行うことは可能ですか?今、私はほとんどすべてを読みましたが、どこでもエンコーディングに関する情報だけです。検証については何もありません。

4

2 に答える 2

1

xmlseclibsライブラリを使用してWP8IAPレシートを確認することができました。

また、phpcurlを有効にする必要があります。

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
}
于 2014-06-23T14:21:43.033 に答える
-1

自分で話してください。phpseclibのドキュメントに対する「独自の例を作成する」アプローチが大好きです。

とはいえ、この場合、phpseclibを実際に使用できるとは思いません。つまり、SignatureValueタグがあります。しかし、その署名は何をカバーしていますか?XML署名では、署名がXMLの正規化された形式をカバーしていることを理解しています。xmlseclibsはXMLドキュメントを正規化しますが、phpseclibは暗号化libであるため、XMLlibではありません。

于 2012-12-03T22:37:43.540 に答える