|
| 1 | +# Merchant Fee Deductible |
| 2 | + |
| 3 | +The `MerchantFeeDeductible` interface allows you to deduct fees from the merchant's payout instead of adding them to the customer's payment. This means customers pay only the listed product price, while merchants receive the product price minus the fee. |
| 4 | + |
| 5 | +## How It Works |
| 6 | + |
| 7 | +By default, when using the `Taxable` interface, fees are added to the customer's payment: |
| 8 | + |
| 9 | +- **Product price:** $100 |
| 10 | +- **Fee:** 5% |
| 11 | +- **Customer pays:** $105 ($100 + $5 fee) |
| 12 | +- **Merchant receives:** $100 |
| 13 | + |
| 14 | +When using `MerchantFeeDeductible`, fees are deducted from the merchant's payout: |
| 15 | + |
| 16 | +- **Product price:** $100 |
| 17 | +- **Fee:** 5% |
| 18 | +- **Customer pays:** $100 |
| 19 | +- **Merchant receives:** $95 ($100 - $5 fee) |
| 20 | + |
| 21 | +## User Model |
| 22 | + |
| 23 | +Add the `CanPay` trait and `Customer` interface to your User model. |
| 24 | + |
| 25 | +> The trait `CanPay` already inherits `HasWallet`, reuse will cause an error. |
| 26 | +
|
| 27 | +```php |
| 28 | +use Bavix\Wallet\Traits\CanPay; |
| 29 | +use Bavix\Wallet\Interfaces\Customer; |
| 30 | + |
| 31 | +class User extends Model implements Customer |
| 32 | +{ |
| 33 | + use CanPay; |
| 34 | +} |
| 35 | +``` |
| 36 | + |
| 37 | +## Item Model |
| 38 | + |
| 39 | +Add the `HasWallet` trait and implement both `ProductInterface` (or `ProductLimitedInterface`) and `MerchantFeeDeductible` interfaces to your Item model. |
| 40 | + |
| 41 | +The `MerchantFeeDeductible` interface extends `Taxable`, so you need to implement the `getFeePercent()` method. |
| 42 | + |
| 43 | +```php |
| 44 | +use Bavix\Wallet\Traits\HasWallet; |
| 45 | +use Bavix\Wallet\Interfaces\Customer; |
| 46 | +use Bavix\Wallet\Interfaces\MerchantFeeDeductible; |
| 47 | +use Bavix\Wallet\Interfaces\ProductLimitedInterface; |
| 48 | + |
| 49 | +class Item extends Model implements ProductLimitedInterface, MerchantFeeDeductible |
| 50 | +{ |
| 51 | + use HasWallet; |
| 52 | + |
| 53 | + public function canBuy(Customer $customer, int $quantity = 1, bool $force = false): bool |
| 54 | + { |
| 55 | + /** |
| 56 | + * If the service can be purchased once, then |
| 57 | + * return !$customer->paid($this); |
| 58 | + */ |
| 59 | + return true; |
| 60 | + } |
| 61 | + |
| 62 | + public function getAmountProduct(Customer $customer): int|string |
| 63 | + { |
| 64 | + return 100; |
| 65 | + } |
| 66 | + |
| 67 | + public function getMetaProduct(): ?array |
| 68 | + { |
| 69 | + return [ |
| 70 | + 'title' => $this->title, |
| 71 | + 'description' => 'Purchase of Product #' . $this->id, |
| 72 | + ]; |
| 73 | + } |
| 74 | + |
| 75 | + /** |
| 76 | + * Specify the percentage of the amount. For example, the product costs $100, the fee is 5%. |
| 77 | + * With MerchantFeeDeductible, customer pays $100, merchant receives $95. |
| 78 | + * |
| 79 | + * Minimum 0; Maximum 100 |
| 80 | + */ |
| 81 | + public function getFeePercent(): float|int |
| 82 | + { |
| 83 | + return 5.0; // 5% |
| 84 | + } |
| 85 | +} |
| 86 | +``` |
| 87 | + |
| 88 | +## Payment Process |
| 89 | + |
| 90 | +Find the user and check the balance. |
| 91 | + |
| 92 | +```php |
| 93 | +$user = User::first(); |
| 94 | +$user->balance; // 100 |
| 95 | +``` |
| 96 | + |
| 97 | +Find the goods and check the cost. |
| 98 | + |
| 99 | +```php |
| 100 | +$item = Item::first(); |
| 101 | +$item->getAmountProduct($user); // 100 |
| 102 | +``` |
| 103 | + |
| 104 | +The user can buy a product. With `MerchantFeeDeductible`, the customer only needs to pay the product price (no fee added). |
| 105 | + |
| 106 | +```php |
| 107 | +$user->pay($item); // success, customer pays $100 (product price) |
| 108 | +$user->balance; // 0 |
| 109 | +``` |
| 110 | + |
| 111 | +After payment: |
| 112 | +- Customer balance: $0 (paid $100) |
| 113 | +- Merchant balance: $95 (received $100 - $5 fee) |
| 114 | +- Transfer fee: $5 |
| 115 | + |
| 116 | +## Combining with MinimalTaxable and MaximalTaxable |
| 117 | + |
| 118 | +You can combine `MerchantFeeDeductible` with `MinimalTaxable` or `MaximalTaxable` interfaces to set minimum or maximum fee limits. |
| 119 | + |
| 120 | +```php |
| 121 | +use Bavix\Wallet\Traits\HasWallet; |
| 122 | +use Bavix\Wallet\Interfaces\Customer; |
| 123 | +use Bavix\Wallet\Interfaces\MerchantFeeDeductible; |
| 124 | +use Bavix\Wallet\Interfaces\MinimalTaxable; |
| 125 | +use Bavix\Wallet\Interfaces\ProductInterface; |
| 126 | + |
| 127 | +class Item extends Model implements ProductInterface, MerchantFeeDeductible, MinimalTaxable |
| 128 | +{ |
| 129 | + use HasWallet; |
| 130 | + |
| 131 | + public function getAmountProduct(Customer $customer): int|string |
| 132 | + { |
| 133 | + return 100; |
| 134 | + } |
| 135 | + |
| 136 | + public function getMetaProduct(): ?array |
| 137 | + { |
| 138 | + return [ |
| 139 | + 'title' => $this->title, |
| 140 | + 'description' => 'Purchase of Product #' . $this->id, |
| 141 | + ]; |
| 142 | + } |
| 143 | + |
| 144 | + public function getFeePercent(): float|int |
| 145 | + { |
| 146 | + return 0.03; // 3% |
| 147 | + } |
| 148 | + |
| 149 | + public function getMinimalFee(): int|string |
| 150 | + { |
| 151 | + return 5; // 3%, minimum 5 |
| 152 | + } |
| 153 | +} |
| 154 | +``` |
| 155 | + |
| 156 | +#### Example with Minimal Fee |
| 157 | + |
| 158 | +Find the user and check the balance. |
| 159 | + |
| 160 | +```php |
| 161 | +$user = User::first(); |
| 162 | +$user->balance; // 100 |
| 163 | +``` |
| 164 | + |
| 165 | +Find the goods and check the cost. |
| 166 | + |
| 167 | +```php |
| 168 | +$item = Item::first(); |
| 169 | +$item->getAmountProduct($user); // 100 |
| 170 | +``` |
| 171 | + |
| 172 | +The user can buy a product. With `MerchantFeeDeductible` and `MinimalTaxable`: |
| 173 | +- Customer pays: $100 (product price, no fee added) |
| 174 | +- Merchant receives: $95 ($100 - $5 minimal fee) |
| 175 | + |
| 176 | +```php |
| 177 | +$user->pay($item); // success, customer pays $100 |
| 178 | +$user->balance; // 0 |
| 179 | +``` |
| 180 | + |
| 181 | +## Gifts |
| 182 | + |
| 183 | +The `MerchantFeeDeductible` interface also works with gift payments. When gifting a product, the customer pays only the product price, and the merchant receives the product price minus the fee. |
| 184 | + |
| 185 | +```php |
| 186 | +$santa = User::first(); |
| 187 | +$child = User::find(2); |
| 188 | + |
| 189 | +$item = Item::first(); |
| 190 | +$item->getAmountProduct($santa); // 100 |
| 191 | + |
| 192 | +// Santa deposits only the product price |
| 193 | +$santa->deposit(100); |
| 194 | +$santa->balance; // 100 |
| 195 | + |
| 196 | +// Gift the product |
| 197 | +$transfer = $santa->wallet->gift($child, $item); |
| 198 | + |
| 199 | +// Santa's balance: 0 (paid $100) |
| 200 | +// Child received the product |
| 201 | +// Merchant balance: $95 (received $100 - $5 fee) |
| 202 | +``` |
| 203 | + |
| 204 | +## Refunds |
| 205 | + |
| 206 | +When refunding a purchase made with `MerchantFeeDeductible`, the customer receives back what the merchant received (product price minus fee), not what the customer originally paid. |
| 207 | + |
| 208 | +```php |
| 209 | +$user = User::first(); |
| 210 | +$item = Item::first(); |
| 211 | + |
| 212 | +// Customer pays $100, merchant receives $95 |
| 213 | +$user->pay($item); |
| 214 | +$user->balance; // 0 |
| 215 | +$item->balance; // 95 |
| 216 | + |
| 217 | +// Refund |
| 218 | +$user->refund($item); |
| 219 | +$user->balance; // 95 (what merchant received) |
| 220 | +$item->balance; // 0 |
| 221 | +``` |
| 222 | + |
| 223 | +## Direct Transfers |
| 224 | + |
| 225 | +When transferring directly to a product that implements `MerchantFeeDeductible`, the fee is deducted from the recipient's deposit. |
| 226 | + |
| 227 | +```php |
| 228 | +$user = User::first(); |
| 229 | +$item = Item::first(); // implements MerchantFeeDeductible |
| 230 | + |
| 231 | +$user->deposit(100); |
| 232 | +$user->balance; // 100 |
| 233 | + |
| 234 | +// Transfer to merchant |
| 235 | +$transfer = $user->transfer($item, 100); |
| 236 | + |
| 237 | +// User balance: 0 |
| 238 | +// Merchant balance: 95 ($100 - $5 fee) |
| 239 | +``` |
| 240 | + |
| 241 | +## Key Differences from Taxable |
| 242 | + |
| 243 | +| Feature | Taxable | MerchantFeeDeductible | |
| 244 | +|---------|---------|----------------------| |
| 245 | +| Customer pays | Product price + fee | Product price only | |
| 246 | +| Merchant receives | Product price | Product price - fee | |
| 247 | +| Fee location | Added to customer payment | Deducted from merchant payout | |
| 248 | +| Use case | Customer covers transaction costs | Merchant covers transaction costs | |
| 249 | + |
| 250 | +It's simple! |
| 251 | + |
0 commit comments