Difference between revisions of "Money"

From Second Life Wiki
Jump to navigation Jump to search
(Added caveat)
(Added Aditi warning)
 
(14 intermediate revisions by 7 users not shown)
Line 1: Line 1:
{{LSL_Function/warning|Security|Always (''ALWAYS!'') check the amount paid.}}{{LSL_Event
{{LSL_Event
|inject-1={{LSL_Function/warning|Security|'''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.'''}}
|event_id=20
|event_id=20
|event_delay
|event_delay
Line 5: Line 6:
|p1_type=key|p1_name=id|p1_desc=who paid
|p1_type=key|p1_name=id|p1_desc=who paid
|p2_type=integer|p2_name=amount|p2_desc=the amount paid
|p2_type=integer|p2_name=amount|p2_desc=the amount paid
|event_desc=Triggered when money is paid to the prim in the '''amount''' by '''id'''.
|event_desc=Triggered when money is paid to the prim in the {{LSLP|amount}} by {{LSLP|id}}.
|event_footnote
|event_footnote
|constants
|constants
|spec=When money is paid to the prim, the money is given to the object's owner.<br/>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]]).<br.>
|spec=When money is paid to the prim, the money is given to the object's owner.<br/>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.<br>
Don't forget to turn on the pay-behavior of the prims/objects involved.<br/>
Don't forget to turn on the pay-behavior of the prims/objects involved.<br/>
The pay buttons should be configured in most applications where money is being transfered ([[llSetPayPrice]]), it makes paying money to the object easier.
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.
|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.
* Money cannot be paid to an attachment.
|examples=<lsl>integer price = 10;
* '''Money() does not check if it is running on the Testing Grid!''' If you are writing a vendor that does networking, be sure to check that it was not payed aditi grid by doing <code>if(llSubStringIndex(llGetEnv("simulator_hostname"), ".aditi.") == -1)</code> or by checking if [[llHTTPRequest]]'s <code>X-SecondLife-Shard</code> header does not equal "Testing".
|examples=
This example shows the simplest tip-jar and shows how little code is needed to receive unverified amounts of money.
<source lang="lsl2">


default
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!");
    }
}
</source>
Next level of tip jar, advising owner, keeping a running total, and with floating text to show status.
<source lang="lsl2">
integer Total;
string  OwnerName;
default
{
    on_rez( integer sparam )
    {
        llResetScript();
    }
     state_entry()
     state_entry()
     {
     {
         llSetPayPrice(PAY_HIDE, [PAY_HIDE ,PAY_HIDE, PAY_HIDE, PAY_HIDE]);
         OwnerName = llKey2Name( llGetOwner() );
         llRequestPermissions(llGetOwner(), PERMISSION_DEBIT);
         llSetText( OwnerName + "'s Tip Jar.\nAny tips gratefully received!\nL$0 Donated so far", <.2, 1, .6>, 1);
     }
     }
     run_time_permissions(integer perm)
 
     money(key id, integer amount)
     {
     {
         if(perm & PERMISSION_DEBIT)
         Total += amount;
            state cash;
        // 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 );
     }
     }
}
}
</source>
An elementary vendor with money validation and refund capability
<source lang="lsl2">
// Give the first item in this object's inventory to anyone who pays the price


state cash
integer price = 10;      // The price needed to purchase the item
 
default
{
{
     state_entry()
     state_entry()
     {
     {
         llSetPayPrice(price, [price, PAY_HIDE, PAY_HIDE, PAY_HIDE]);
        // 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);
     }
     }
     money(key id, integer amount)
    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)
         if (amount < price)
         {
         {   // Customer has not paid enough
             llGiveMoney(id, amount);
             llInstantMessage(id, "That's not enough money.");
             llInstantMessage(id, "You paid "+(string)amount+", which is the wrong price, the price is: "+(string)price);
             llGiveMoney(id, amount);  // Refund the money they paid
            return;
         }
         }
         else
         if (amount > price)
         {
         {   // Customer paid too much. Refund the excess
             llInstantMessage(id, "You paid the right price");
            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 );
     }
     }
}</lsl>
    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]);
 
        // In practice, the following line would be preferable and almost fully guards against a wrong amount being paid
        // - except in the rare event that the price is changed while a transaction is in progress, or a user with a hacked viewer
        //  llSetPayPrice(PAY_HIDE, [price ,PAY_HIDE, PAY_HIDE, PAY_HIDE]);
    }
}
</source>
|helpers
|helpers
|also_header
|also_header
|also_events
|also_events
|also_functions={{LSL DefineRow||[[llGiveMoney]]|Give money to another avatar}}
|also_functions={{LSL DefineRow||[[llTransferLindenDollars]]|Give money to another avatar with transaction confirmation}}
{{LSL DefineRow||[[llGiveMoney]]|Give money to another avatar}}
{{LSL DefineRow||[[llSetPayPrice]]|Configure the pay buttons}}
{{LSL DefineRow||[[llSetPayPrice]]|Configure the pay buttons}}
|also_articles
|also_articles

Latest revision as of 08:25, 27 June 2017

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.
  • Money() does not check if it is running on the Testing Grid! If you are writing a vendor that does networking, be sure to check that it was not payed aditi grid by doing if(llSubStringIndex(llGetEnv("simulator_hostname"), ".aditi.") == -1) or by checking if llHTTPRequest's X-SecondLife-Shard header does not equal "Testing".
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.

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!");
    }
}

Next level of tip jar, advising owner, keeping a running total, and with floating text to show status.

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 );
    }
}

An elementary vendor with money validation and refund capability

// 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]);

        // In practice, the following line would be preferable and almost fully guards against a wrong amount being paid
        // - except in the rare event that the price is changed while a transaction is in progress, or a user with a hacked viewer
        //  llSetPayPrice(PAY_HIDE, [price ,PAY_HIDE, PAY_HIDE, PAY_HIDE]);
    }
}

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 );