Difference between revisions of "Money"

From Second Life Wiki
Jump to navigation Jump to search
m (linky)
(Replace 3rd script which has always been faulty, and which demonstrated inappropriate permission handling. (Maybe it was OK in 2007))
Line 48: Line 48:
         Total += amount;
         Total += amount;
         // Shortcut 'cheat' to avoid multiple casts when constructing a message including non-string items
         // Shortcut 'cheat' to avoid multiple casts when constructing a message including non-string items
         string str = (string) [OwnerName, "'s Tip Jar.\nPlease tip if you are so inclined!\n$L", amount, " Was donated last!\n$L", Total, " Donated so far" ];
         string str = (string) [OwnerName, "'s Tip Jar.\nPlease tip if you are so inclined!\nL$", amount, " Was donated last!\nL$", Total, " Donated so far" ];
         llSetText(str, <1,1,1>, 1);
         llSetText(str, <1,1,1>, 1);
         llInstantMessage(id,"Thanks for the tip!");
         llInstantMessage(id,"Thanks for the tip!");
Line 55: Line 55:
}
}
</lsl>
</lsl>
This example verifies the amount received (but without giving the user a clue as to the expected amount. Oh, and it doesn't actually work).
An elementary vendor with money validation and refund capability
<lsl>
<lsl>
integer price = 10;
// Give the first item in this object's inventory to anyone who pays the price
 
integer price = 10;     // The price needed to purchase the item


default
default
Line 63: Line 65:
     state_entry()
     state_entry()
     {
     {
        // Turn off pay options so no money can be received until we are ready
         llSetPayPrice(PAY_HIDE, [PAY_HIDE ,PAY_HIDE, PAY_HIDE, PAY_HIDE]);
         llSetPayPrice(PAY_HIDE, [PAY_HIDE ,PAY_HIDE, PAY_HIDE, PAY_HIDE]);
 
        // Request Debit Permissions from the owner so refunds can be given
         key owner = llGetOwner();
         llRequestPermissions(llGetOwner(), PERMISSION_DEBIT);
         llRequestPermissions(owner, PERMISSION_DEBIT);
    }
    on_rez(integer p)
    {
         llResetScript();               // Reset script on rezzing. Will thus register any change of owner.
     }
     }
 
     money(key id, integer amount)       // Some money has been received and has gone to this object's owner
     money(key id, integer amount)
     {
     {
        if (amount == price)
        {
            llInstantMessage(id, "You paid " + (string)price + " L$.");
            return;
        }
        key owner = llGetOwner();
        key permKey = llGetPermissionsKey();
        integer perm = llGetPermissions();
        if (permKey != owner)
            return;
        if (!(perm & PERMISSION_DEBIT))
            return;
         if (amount < price)
         if (amount < price)
         {
         {   // Customer has not paid enough
             llInstantMessage(id, "That's not enough money.");
             llInstantMessage(id, "That's not enough money.");
             llGiveMoney(id, amount);
             llGiveMoney(id, amount);  // Refund the money they paid
            return;
         }
         }
         else if (price < amount)
         if (amount > price)
         {
         {   // Customer paid too much. Refund the excess
             integer change = amount - price;
             integer change = amount - price;
             llInstantMessage(id, "You paid more than " + (string)price + " L$, "
             llInstantMessage(id, "You paid more than L$" + (string)price
                                + "your change is " + (string)change + " L$.");
                + " your change is L$" + (string)change );
             llGiveMoney(id, change);
             llGiveMoney(id, change);
         }
         }
        // Customer has paid at least the right amount. Give them the item.
        string ItemName = llGetInventoryName(INVENTORY_OBJECT, 0);
        llGiveInventory(id, ItemName);
        llInstantMessage(id, "Please accept your purchase worth L$" + (string) price );
     }
     }
     run_time_permissions(integer perm)
     run_time_permissions(integer perm)
     {
     {
        // If Debit permissions are granted, set up the pay price for this single-price vendor
         if(perm & PERMISSION_DEBIT)
         if(perm & PERMISSION_DEBIT)
             llOwnerSay("Setup complete");
             llSetPayPrice(price, [PAY_HIDE ,PAY_HIDE, PAY_HIDE, PAY_HIDE]);
     }
     }
}
}

Revision as of 14:42, 13 January 2013

Emblem-important-red.png Security Warning!

When writing a vendor, Always (ALWAYS!) check the amount paid in your money() event. Preconfigured payment amounts from llSetPayPrice() are only a suggestion to the client. The client can still send L$0 or any positive integer. Never trust the client software to be secure. This is not important, of course, for a simple tipjar

Description

Event: money( key id, integer amount ){ ; }

Triggered when money is paid to the prim in the amount by id.

• key id who paid
• integer amount the amount paid

Specification

When money is paid to the prim, the money is given to the object's owner.
If the object is owned by or deeded to a group it is divvied up amongst the group members immediately (which is why groups can't grant PERMISSION_DEBIT). Only members of a role that has the "Accounting/Pay group liabilities and receive group dividends" attribute will receive money.
Don't forget to turn on the pay-behavior of the prims/objects involved.
The pay buttons should be configured in most applications where money is being transfered (llSetPayPrice), it makes paying money to the object easier.

Caveats

  • This event cannot be triggered by a call to llGiveMoney because llGiveMoney cannot be used by one object to pay another object.
  • Money cannot be paid to an attachment.
All Issues ~ Search JIRA for related Bugs

Examples

This example shows the simplest tip-jar and shows how little code is needed to receive unverified amounts of money. <lsl>

default {

   money(key id, integer amount)      // Some money has been received (and has been paid into the owner's account) 
   {
       // Thank the giver for their tip
       llInstantMessage(id, "Thanks for the L$"  + (string) amount + " tip!");
   }

} </lsl> Next level of tip jar, advising owner, keeping a running total, and with floating text to show status. <lsl> integer Total; string OwnerName;

default {

   on_rez( integer sparam )
   {
       llResetScript();
   }
   state_entry()
   {
       OwnerName = llKey2Name( llGetOwner() );
       llSetText( OwnerName + "'s Tip Jar.\nAny tips gratefully received!\nL$0 Donated so far", <.2, 1, .6>, 1);
   }
   money(key id, integer amount)
   {
       Total += amount;
       // Shortcut 'cheat' to avoid multiple casts when constructing a message including non-string items
       string str = (string) [OwnerName, "'s Tip Jar.\nPlease tip if you are so inclined!\nL$", amount, " Was donated last!\nL$", Total, " Donated so far" ];
       llSetText(str, <1,1,1>, 1);
       llInstantMessage(id,"Thanks for the tip!");
       llInstantMessage(llGetOwner(), llKey2Name(id) + " donated L$" + (string) amount );
   }

} </lsl> An elementary vendor with money validation and refund capability <lsl> // Give the first item in this object's inventory to anyone who pays the price

integer price = 10; // The price needed to purchase the item

default {

   state_entry()
   {
       // Turn off pay options so no money can be received until we are ready
       llSetPayPrice(PAY_HIDE, [PAY_HIDE ,PAY_HIDE, PAY_HIDE, PAY_HIDE]);
       // Request Debit Permissions from the owner so refunds can be given
       llRequestPermissions(llGetOwner(), PERMISSION_DEBIT);
   }
   on_rez(integer p)
   {
       llResetScript();                // Reset script on rezzing. Will thus register any change of owner.
   }
   money(key id, integer amount)        // Some money has been received and has gone to this object's owner
   {
       if (amount < price)
       {   // Customer has not paid enough
           llInstantMessage(id, "That's not enough money.");
           llGiveMoney(id, amount);   // Refund the money they paid
           return;
       }
       if (amount > price)
       {   // Customer paid too much. Refund the excess
           integer change = amount - price;
           llInstantMessage(id, "You paid more than L$" + (string)price
               + "  your change is L$" + (string)change );
           llGiveMoney(id, change);
       }
       // Customer has paid at least the right amount. Give them the item.
       string ItemName = llGetInventoryName(INVENTORY_OBJECT, 0);
       llGiveInventory(id, ItemName);
       llInstantMessage(id, "Please accept your purchase worth L$" + (string) price );
   }
   run_time_permissions(integer perm)
   {
       // If Debit permissions are granted, set up the pay price for this single-price vendor
       if(perm & PERMISSION_DEBIT)
           llSetPayPrice(price, [PAY_HIDE ,PAY_HIDE, PAY_HIDE, PAY_HIDE]);
   }

} </lsl>

See Also

Functions

•  llTransferLindenDollars Give money to another avatar with transaction confirmation
•  llGiveMoney Give money to another avatar
•  llSetPayPrice Configure the pay buttons

Deep Notes

Signature

event void money( key id, integer amount );