使用PHP从Windows应用商店验证IAP(应用内购买)XML收据

问题描述 投票:-1回答:1

我需要在应用内购买后验证Microsoft提供的收据XML。

MS示例正在为C ++编写。

如何在PHP中验证收据?

php xml in-app-purchase windows-store-apps verification
1个回答
0
投票
$verifyFailed = false;
            $doc = new \DOMDocument();

            $xml = '
            <Receipt Version="1.0" ReceiptDate="2012-08-30T23:08:52Z" CertificateId="b809e47cd0110a4db043b3f73e83acd917fe1336" ReceiptDeviceId="4e362949-acc3-fe3a-e71b-89893eb4f528">
                <ProductReceipt Id="6bbf4366-6fb2-8be8-7947-92fd5f683530" ProductId="Product1" PurchaseDate="2012-08-30T23:08:52Z" ExpirationDate="2012-09-02T23:08:49Z" ProductType="Durable" AppId="55428GreenlakeApps.CurrentAppSimulatorEventTest_z7q3q7z11crfr" />
                <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
                    <SignedInfo>
                        <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                        <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
                        <Reference URI="">
                            <Transforms>
                                <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
                            </Transforms>
                            <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
                            <DigestValue>Uvi8jkTYd3HtpMmAMpOm94fLeqmcQ2KCrV1XmSuY1xI=</DigestValue>
                        </Reference>
                    </SignedInfo>
                    <SignatureValue>TT5fDET1X9nBk9/yKEJAjVASKjall3gw8u9N5Uizx4/Le9RtJtv+E9XSMjrOXK/TDicidIPLBjTbcZylYZdGPkMvAIc3/1mdLMZYJc+EXG9IsE9L74LmJ0OqGH5WjGK/UexAXxVBWDtBbDI2JLOaBevYsyy+4hLOcTXDSUA4tXwPa2Bi+BRoUTdYE2mFW7ytOJNEs3jTiHrCK6JRvTyU9lGkNDMNx9loIr+mRks+BSf70KxPtE9XCpCvXyWa/Q1JaIyZI7llCH45Dn4SKFn6L/JBw8G8xSTrZ3sBYBKOnUDbSCfc8ucQX97EyivSPURvTyImmjpsXDm2LBaEgAMADg==</SignatureValue>
                </Signature>
            </Receipt>';

            // 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 = 'b809e47cd0110a4db043b3f73e83acd917fe1336';

            $publicKey =  getCertificate($certificateId);
            $objXMLSecDSig = new XMLSecurityDSig();
            $objDSig = $objXMLSecDSig->locateSignature($doc);

            if (!$objDSig) {
                $verifyFailed = true;
            }
            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;
            }

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

            if ($verifyFailed) {
                echo 'Validation failed.';
            } else {
                echo 'Successful verified';
            }

获得证书的功能:

function getCertificate($certID)
    {
        $ch = curl_init('https://lic.apps.microsoft.com/licensing/certificateserver/?cid=' . $certID);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);

        try {
            $publicKey = curl_exec($ch);
            curl_close($ch);
            return $publicKey;
        } catch (\Exception $exception) {
            echo 'Error retrieving cert: '.curl_errno($ch).' - '.curl_error($ch);
            return false;
        }
    }

您可以通过修改证书ID和/或ProductReceipt ID对其进行测试。

用实际购买中的XML替换XML。

© www.soinside.com 2019 - 2024. All rights reserved.