ios – Cannot confirm Apple receipt because of the measurement

0
1
ios – Cannot confirm Apple receipt because of the measurement


I am attempting to setup fee processing for my iOS app. As soon as the fee receipt is generated in iOS – we ship it to Node.JS backend buy_subscription endpoint, which verifies receipt utilizing VerifyAppleReceipt perform, generates order knowledge to be inserted into DB utilizing generateOrderData perform. Nevertheless, when I attempt to buy my auto-renewable subscription – I consistently get backend error:

PayloadTooLargeError: request entity too massive
    at readStream 
    at getRawBody 
    at learn 
    at jsonParser 
    at Layer.deal with [as handle_request] 
    at trim_prefix 
    at 
    at Operate.process_params 
    at subsequent 
    at expressInit

In some unspecified time in the future previously I used to be in a position to course of the acquisition appropriately and write generated knowledge into DB.
I think the scale of receipt has one thing to do with it. Since I take advantage of Apple sandbox account for testing – each sandbox buy generates 6 purchases in latest_receipt_info of Apple Receipt (5 minutes * 6 renewals = 1 month of sandox). So presently my poor receipt has 254 operations in it.

const verifyAppleReceipt = async (receiptData) => {
        addLog(`[verifyAppleReceipt] Beginning verification`);
        addLog(`[verifyAppleReceipt] Receipt preview: ${receiptData.substring(0, 20)}...`);
        
        const requestPayload = {
            'receipt-data': receiptData,
            'password': 'exampleData',
            'exclude-old-transactions': true
        };
        addLog(`[verifyAppleReceipt] Payload keys: ${Object.keys(requestPayload).be a part of(',')}`);

        strive {
            addLog(`[verifyAppleReceipt] Requesting manufacturing endpoint...`);
            let response = await axios.submit('https://purchase.itunes.apple.com/verifyReceipt', requestPayload);
            addLog(`[verifyAppleReceipt] Manufacturing response standing: ${response.knowledge.standing}`);
            
            if (response.knowledge.standing === 21007) {
                addLog(`[verifyAppleReceipt] 21007 = Sandbox receipt, switching to sandbox endpoint...`);
                response = await axios.submit('https://sandbox.itunes.apple.com/verifyReceipt', requestPayload);
                addLog(`[verifyAppleReceipt] Sandbox response standing: ${response.knowledge.standing}`);
            }
            return response.knowledge;
        } catch (error) {
            addLog(`[verifyAppleReceipt] Error: ${error.message}`);
            throw error;
        }
    };

    async perform generateOrderData({ parsedReceipt, uid, receiptData, productId, quantity, isAutoRenewable }) {
        strive {
            const transaction = parsedReceipt.latest_receipt_info?.slice(-1)[0] || parsedReceipt.receipt?.in_app?.slice(-1)[0];
            if (!transaction) throw new Error('No legitimate transaction present in receipt');

            const order_id = `APPLE${transaction.transaction_id}`;
            const transactionDate = new Date(parseInt(transaction.purchase_date_ms));

            console.log("[GENERATE ORDER] Getting member information for:", uid);
            const memResult = await executeQuery(`SELECT idx FROM MemberInfo WHERE id = N'${uid}'`);

            if (!Array.isArray(memResult) || memResult.size === 0) throw new Error('Person not discovered');
            const mem_idx = memResult[0].idx;

            const item_settle_choice = isAutoRenewable ? 1 : (quantity === 1 ? 1 : quantity === 6 ? 2 : quantity === 12 ? 3 : 0);

            console.log("[GENERATE ORDER] Getting present product information for:", mem_idx);
            const existingProResult = await executeQuery(`SELECT pro_date_start FROM tv_myitem_tb WHERE mem_idx = ${mem_idx}`);

            const existingProStart = existingProResult?.[0]?.pro_date_start;
            const pro_date_start = existingProStart || transactionDate;

            const daysToAdd = isAutoRenewable ? 3 : (typeof quantity === 'quantity' ? 30 * quantity : 0);
let pro_date_end = DateTime.fromJSDate(transactionDate).plus({ days: daysToAdd }).toJSDate();

            const worth = isAutoRenewable ? 13000 : (quantity === 1 ? 13000 : quantity === 6 ? 70000 : quantity === 12 ? 120000 : 0);

            return {
                order_id,
                regdate: transactionDate,
                item_settle_choice,
                mem_idx,
                mem_id: uid,
                pro_date_start,
                pro_date_end,
                receiptData,
                productId,
                worth
            };
        } catch (error) {
            console.error("[GENERATE ORDER] Error:", error);
            throw error;
        }
    }

    perform toUTCFromLocal(date) {
        return DateTime.fromJSDate(date).toUTC();  // Converts a JavaScript Date object to a Luxon DateTime object and returns UTC
    }

    router.submit("/buy_subscription", async perform (req, res) {
        strive {
            const { uid, receiptData, productId } = req.physique;
            console.log("[BUY MEMBERSHIP] Beginning buy for:", uid);

            const existingOrder = await executeQuery(`SELECT order_idxx FROM web_pay_apple_log WHERE productId = N'${productId}' AND receiptData = N'${receiptData}'`);

            if (Array.isArray(existingOrder) && existingOrder.size > 0) {
                return res.finish('{"rtnCd":"fail","rtnMsg":["Duplicate receipt detected"]}');
            }

            const appleResponse = await verifyAppleReceipt(receiptData);
            if (appleResponse.standing !== 0) throw new Error("Verification failed");

            const orderData = await generateOrderData({ parsedReceipt: appleResponse, uid, receiptData, productId, isAutoRenewable: true });

            const checkQuery = `SELECT pro_date_count FROM tv_myitem_tb WHERE pro_code="915" AND mem_idx = ${orderData.mem_idx}`;
            console.log("[BUY MEMBERSHIP] Checking present membership:", checkQuery);
            const checkResult = await executeQuery(checkQuery);

            const proDateCount = checkResult?.[0]?.pro_date_count || 0;

            if (proDateCount === 0) {
                const insertQuery = `
                    INSERT INTO tv_myitem_tb(mem_idx, mem_id, pro_cate, pro_code, pro_name, pro_gubun, pro_date_count, dnis, pro_date_start, pro_date_end)
                    SELECT idx, id, 1, '915', N'정회원 자동결제', 2, 1, '15', GETDATE(), DATEADD(dd, 3, GETDATE()) 
                    FROM MemberInfo WHERE idx = ${orderData.mem_idx}
                `;
                console.log("[BUY MEMBERSHIP] Inserting new membership:", insertQuery);
                await executeQuery(insertQuery);
            } else {
                const updateQuery = `
                    UPDATE tv_myitem_tb 
                    SET pro_date_end = DATEADD(dd, 3, GETDATE()) 
                    WHERE mem_idx = ${orderData.mem_idx} AND pro_code="915"
                `;
                console.log("[BUY MEMBERSHIP] Updating present membership:", updateQuery);
                await executeQuery(updateQuery);
            }

            const logQuery = `
                INSERT INTO web_pay_apple_log(order_idxx, id, cd_value, item_settle_choice, item_code_idx, item_name, cd_info, website, productId, receiptData, mem_idx)
                VALUES (N'${orderData.order_id}', N'${orderData.mem_id}', ${orderData.worth}, ${orderData.item_settle_choice}, '915', N'정회원 자동결제', '1', 'land', N'${orderData.productId}', N'${orderData.receiptData}', ${orderData.mem_idx})
            `;
            console.log("[BUY MEMBERSHIP] Logging transaction:", logQuery);
            await executeQuery(logQuery);

            res.finish('{"rtnCd":"success","rtnMsg":[""]}');
        } catch (error) {
            console.error("[BUY MEMBERSHIP] Error:", error);
            res.finish('{"rtnCd":"fail","rtnMsg":["Error processing payment"]}');
        }
    });

Since I do not see any debug logging – I think that no matter buy_membership does fails earlier than something is executed and I can not determine it out.

Any suggestions? I simply must confirm the receipt, parse it and get TransactionDate from it.

LEAVE A REPLY

Please enter your comment!
Please enter your name here