31 Oktober 2026 · 2 menit baca
ProcessReceipt yang benar: jangan sampai pembelian pemain hilang
Pemain yang sudah membayar Robux tapi tidak menerima barang adalah masalah serius. Ini cara menulis ProcessReceipt yang aman untuk Developer Product.
Setiap kali pemain membeli Developer Product, Roblox memanggil callback MarketplaceService.ProcessReceipt di server game Anda. Tugas callback ini sederhana tapi kritis: memberikan barang yang dibeli, lalu memberi tahu Roblox bahwa pembelian sudah selesai diproses.
Aturan utamanya
Kembalikan Enum.ProductPurchaseDecision.PurchaseGranted hanya setelah barang benar-benar diberikan dan tercatat. Bila ada yang gagal, kembalikan Enum.ProductPurchaseDecision.NotProcessedYet. Roblox akan mencoba memanggil callback lagi nanti, misalnya saat pemain bergabung kembali.
Kesalahan yang sering terjadi
- Mengembalikan
PurchaseGrantedsebelum data tersimpan. Bila server mati di tengah jalan, pemain kehilangan barang yang sudah dibayar. - Memberikan barang dua kali karena callback dipanggil ulang untuk pembelian yang sama.
- Membuat lebih dari satu
ProcessReceipt. Callback ini hanya boleh di-set sekali di satu script server.
Contoh struktur
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
local COIN_PACKS = {
[123456789] = 500, -- ganti dengan ID Developer Product Anda
}
MarketplaceService.ProcessReceipt = function(receipt)
local player = Players:GetPlayerByUserId(receipt.PlayerId)
if not player then
-- Pemain sudah keluar: proses lagi saat ia kembali.
return Enum.ProductPurchaseDecision.NotProcessedYet
end
local amount = COIN_PACKS[receipt.ProductId]
if not amount then
return Enum.ProductPurchaseDecision.NotProcessedYet
end
-- grantAndSave: tambahkan koin, catat receipt.PurchaseId sebagai sudah diberikan,
-- lalu simpan ke DataStore. Kembalikan true hanya bila penyimpanan berhasil.
local ok = grantAndSave(player, receipt.PurchaseId, amount)
if not ok then
return Enum.ProductPurchaseDecision.NotProcessedYet
end
return Enum.ProductPurchaseDecision.PurchaseGranted
endCegah pemberian ganda dengan PurchaseId
Setiap pembelian punya receipt.PurchaseId yang unik. Simpan daftar PurchaseId yang sudah diproses di data pemain. Saat callback dipanggil, cek dulu: bila PurchaseId sudah ada, langsung kembalikan PurchaseGranted tanpa memberikan barang lagi.
Uji sebelum rilis
- Uji pembelian di Studio; pembelian di Studio tidak memotong Robux sungguhan.
- Simulasikan kegagalan penyimpanan dan pastikan callback mengembalikan
NotProcessedYet. - Coba skenario pemain keluar tepat setelah membeli.
Penutup
Pembelian yang selalu sampai membangun kepercayaan, dan kepercayaan membuat pemain mau membeli lagi. Butuh sistem pembelian yang andal? Lihat layanan Scripting & Sistem.