You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Roblox开发者产品购买异常:非200响应仍显示购买成功

Roblox开发者产品购买验证失败:返回NotProcessedYet仍显示购买成功的解决方案

问题场景

开发Roblox开发者产品购买系统时,通过向自定义服务器发送HTTP请求验证购买,预期当服务器返回的Code不为200时,返回Enum.ProductPurchaseDecision.NotProcessedYet阻止购买成功,但实际Roblox仍会标记购买成功,不符合需求。

核心问题分析

你的代码存在几个关键漏洞,导致Roblox无法正确识别你返回的决策:

  1. HTTP请求未做异常捕获:如果PostAsync请求超时、失败或抛出错误,函数会直接崩溃,无法返回NotProcessedYet,Roblox会自动重试,最终可能默认标记购买成功。
  2. 分支返回不完整:仅处理了目标产品ID的情况,其他产品ID的分支没有返回值,Roblox会使用默认逻辑处理。
  3. 响应Code类型不明确:如果服务器返回的Code是字符串类型(比如"404"而非数字404),response["Code"] == 200的判断会失效,错误地进入PurchaseGranted分支。

修复方案及代码修改

针对以上问题,修改代码如下:

local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")
local HTTPService = game:GetService("HttpService")

local for1monthid = -- 替换为你的产品ID

MarketplaceService.ProcessReceipt = function(receiptInfo)
    local plr = Players:GetPlayerByUserId(receiptInfo.PlayerId)
    if not plr then
        return Enum.ProductPurchaseDecision.NotProcessedYet
    end

    -- 仅处理目标产品ID
    if receiptInfo.ProductId == for1monthid then
        local url = "https://api.endpoint.com"
        local data = {
            userid = plr.UserId,
            receiptId = receiptInfo.ReceiptId -- 新增:传递收据ID用于重复验证
        }
        local encodedData = HTTPService:JSONEncode(data)
        
        -- 用pcall捕获HTTP请求异常
        local success, responseOrErr = pcall(function()
            return HTTPService:PostAsync(url, encodedData, Enum.HttpContentType.ApplicationJson, false)
        end)

        if not success then
            print("HTTP请求失败:" .. responseOrErr)
            return Enum.ProductPurchaseDecision.NotProcessedYet
        end

        -- 解析响应并处理类型问题
        local decodedResponse
        success, decodedResponse = pcall(function()
            return HTTPService:JSONDecode(responseOrErr)
        end)

        if not success then
            print("响应解析失败:" .. decodedResponse)
            return Enum.ProductPurchaseDecision.NotProcessedYet
        end

        -- 同时处理数字和字符串类型的Code
        local responseCode = tonumber(decodedResponse["Code"])
        if responseCode == 200 then
            print("验证通过,发放产品:" .. responseCode)
            -- 这里添加发放产品的逻辑(比如给玩家加道具/权限)
            return Enum.ProductPurchaseDecision.PurchaseGranted
        else
            print("验证失败,阻止购买:" .. decodedResponse["Code"])
            return Enum.ProductPurchaseDecision.NotProcessedYet
        end
    end

    -- 处理未匹配的产品ID,默认返回NotProcessedYet
    return Enum.ProductPurchaseDecision.NotProcessedYet
end

关键修改点说明

  • 添加pcall异常捕获:包裹PostAsync和JSONDecode,确保请求或解析失败时不会崩溃,稳定返回NotProcessedYet。
  • 处理响应Code类型:用tonumber()将响应中的Code转换为数字,避免字符串类型导致的判断错误。
  • 完整分支返回:在函数末尾添加默认返回,覆盖所有未匹配产品ID的情况。
  • 新增收据ID传递:将receiptInfo.ReceiptId发送到服务器,用于验证是否重复购买,避免重复发放产品(最佳实践)。

内容的提问来源于stack exchange,提问作者omamelo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 10:07:52