How to put a lock on a database table resource - php

I am building a financial web app, sort of an e-banking application. Whenever a transaction is being performed e.g Funds transfer, a transaction charge is deducted and updates the system account's earnings/balance by querying the current balance and adding up the deducted charge and then finally updating the balance field.
Now my problem is that when multiple transactions maybe 200 of them are simultaneously executing by different users with different accounts, there is a discrepancy between the total earnings balance that I expected from what is being actually registered in the system. I believe it has something to do with having to asynchronous nature of server-request or something, how can I prevent this??

There is transaction in codeigniter. you can refer Codeigniter Transaction
you can use as
$this->db->trans_start();
YOUR QUERY / QUERYS
$this->db->trans_complete();

Related

prevent concurrent request from a user

I have a question about concurrent request a user from different browser
Imagine we have balance in wallet for just buy one product, if a user request a product at the same time with two different browser, can user buy a product two times? if it is possible, how can I prevent the second action?
example:
user A balance : 100$
user A ----> mozila ----> request ----> product A50(price 100$)
user A ----> chrome ----> request ----> product A50(price 100$)
above request happen at the same time after that some process the amount of wallet decrease
You should perform these operations in SQL TRANSACTIONs having an appropriate isolation level. All of the operations performed within the transaction will be "all or nothing," which means that all of the changes take effect if you COMMIT and none of them do if you instead ROLLBACK. Furthermore, if two transactions attempt to touch the same row, one of them will either be forced to wait or will be turned away. Also, the other transaction will not see anything that hasn't yet been committed.
For instance, if you want to "deduct money from the user's account and apply it to an order," you would perform both updates in one transaction. So, "if everything worked, both updates happened instantaneously." And, "if it didn't work and the transaction was rolled back, nothing changed anywhere."
But it's important that you also test the user's balance within the same transaction! (Otherwise, there would be a "race" between testing the balance and proceeding with the sale.) Your logic might be something like this pseudocode:
BEGIN TRANSACTION with proper isolation level
Retrieve user's account.
If there isn't enough money:
ROLLBACK
exit
Else:
UPDATE user account to withdraw money.
UPDATE the invoice to show payment.
INSERT a new entry into the (financial ...) transaction log table.
COMMIT
This works as intended because the entire set of operations that occurs within the transaction is "atomic."
SQL servers vary slightly in their implementation of transactions but here is a web-page on the topic (covering MS SQL Server):
https://www.sqlserverlogexplorer.com/types-of-transaction-isolation-level/

How can I improve database design for my subscription based billing system?

I am moving from Credits-based billing system to Subscription-based billing system. Till now, I used to check the number of credits a user had and based on that; I used to E-mail user whether the renewal has been done or not. In the event of a first purchase, I used to activate a plan that user has selected.
I am now shifting to the subscription-based billing system in which I will store subscriptions with validity and I want to eliminate the credits part from the root. Here is the database schema for my new billing system. The issue with this schema is I can't process first purchase event as there is no solid way to know if a user is purchasing for the first time and if a user has paid the full amount or not. I am getting confused at each and every step of the change.
Let me explain what issue I am facing. While the transaction is being processed, the is_active flag in subscriptions remains null which means a user can't perform any action on my software. But when a transaction is processed, User will return to my website and my website will mark the transaction paid which means a user has paid but as there is no connection between transactions and subscriptions, How would I know when to mark a subscription paid. In TransactionController, Transactions will be processed and in SubscriptionController, Subscription will be processed.
I haven't created the connection between subscription and transaction because in that case, I'll have to allow nullable foreign keys in a transaction because transactions can be for extra services too!
I am getting more confused by thinking more about it. I don't know what's the issue here but I know there is some issue with database design. Any help is appreciated!
This is what comes into my mind:
Add an end date and is_autorenew to your subscription
Add create- and payment initiation dates to your transaction
I would create a new table , e.g. booking, which holds user information, billing address, price and payment method. Imagine a case, when a guest is subscribing or a user is changing his address or the product price changes. These values need to be genuine.
Create 1:1 relations between booking and subscription and subscription and transaction
Enrich your transaction with returned values from your payment provider, such as customer_id or transaction_id.
This could be your base DB-Model. Now when someone buys anything, you will create 3 entries: booking, subscription and transaction, if everything goes well. If is_autorenew && is_active are true, run a cronjob which renews the subscription automatically. You can use the transaction_id in your transaction table for that. I would create a whole new subscription then and link it to the booking and transaction. Set the old subscription to inactive afterwards.
Hope this will help you a little.
What if you add a field parent_id for your subscription table.
The relationship between subscription and transaction will be 1:1.
Also, I suggest you just activate the user membership immediately (if you can), it gives you the following advantages:
the user experience will not be affected due to the lag of the acknowledgement of the transaction.
the relation between subscription and transaction is created instantly when the user attempted to initial a subscription. You could fill in the transaction id later when you receive the transaction_id.
Hope I helped.
p.s. Is this relevant to php?

Sending Email in Future with specific condition - Laravel

I'm developing application using third party payment gateway to accept bank transfer.
The bank transfer is going to expire within 6 hours if the payment gateway don't receive any transfer from customer.
I want to send reminder email 1 hour before the expiration time.
At the moment, I'm using task scheduling every 15 minutes to check my transaction tables one by one. The transaction is growing and will be million transaction per day in short time.
This approach is not great because cron job is consuming huge memory and not effective. I need some advice to optimize the approach. Can anyone shed the light?
You want an additional table for all "pending" transactions. This way your cron job only reads pending transactions. Once the transaction has been completed, or it has expired, you remove the entry from the "pending" table.
The "pending" table would have only the few fields that necessary to know if the transfer is still pending. When reading this table you would "join" it to the main table to retrieve the rest of the information.

Generic database design for multiple gateways

I'm developing a website (with payments) that needs to support multiple payment gateways. I'm going to use omnipay package (thanks God there is a package to handle this) but now I was wondering what is the best way to store all the payment information in the database without binding it to a specific gateway.
My first idea is to have the following tables:
gateway(gateway_id, gateway_name,...)
payment(payment_id, payment_amount,...)
transaction(transaction_id, gateway_id, payment_id, transaction_reference, transaction_type transaction_status, transaction_request_data,
transaction_response_data...).
The type can be something like 'authorize', 'purchase', 'refund', 'void', etc and the status something like 'successful', 'failed', 'pending', etc.
In this way, I can have a list of gateways (Paypal, Stripe, TargetPay, WorldPay) and each payment can have multiple transactions (a payment attempt can fail at the first time and then be attempted again and work but then voided or refunded) but one transaction belongs to a single payment. Each transaction was executed using a specific gateway and this will also be stored.
I don't know if this is the best approach (maybe it's too simple?) and I would like to hear some other ideas.
Thanks!
Your initial structure is a good start. Other things that I would include are:
responses, which would hold the response messages sent back from the gateway in response to your purchase calls
callbacks. An increasing number of gateways supply POST messages on the notify url to the caller. These indicate change of status messages from the gateway such as cancelled transactions or chargebacks
refunds and voids, which I would store in a single table.
responses to the callbacks, refunds and voids, which you could store in the same table as the regular responses if you structured it correctly
Some of the data you would probably have to store as JSON blobs because the structure of messages from each gateway would be different. Some of the data you may want to encrypt, for example if it contains data that could identify a customer or perhaps a credit card
I believe the best answer is: it depends on how close the data provided / required by the gateway provided to each other. If these are close to each other, or you can map the various status types, then store all of these in a single transactions table. If not, then you need to maintain separate tables for each payment gateways.
However, even in the latter case I would have a single transactions table that consolidates the most important and common data accross all providers, such as amount, payment status, and store only the vendor specific data in their corresponding tables.

Prevent unauthroized calls to API

I am working on an API that can be used between my server and my iOS app. I have an SQL database that contains an Accounts table which includes a column called BALANCE.
People can make a real money deposit to my website through PayPal or I will be allowing them to send money orders. The problem is, when the PayPal SDK checks to make sure it was a legitimate deposit, then it credits that users account balance. When I receive the money order, I credit their balance via my website.
Each time the balance is credited, a call to my API happens. The thing is, I can do this over and over without actually getting PayPal deposits or money order deposits.
See, the users will transfer balances between each others accounts. So I don't need any help with making sure deposits were legit, I got that already. Right now a simple API call will transfer one balance amount over to another account without proof that the call was for a legitimate reason. I don't want to be able to have people somehow tap into the API and credit their own balance somehow. It needs to be where people can't just alter it.
So what can I put in place so that people cannot just tap into my API and credit their balance without actually sending money? Since this is real money, I am putting a lot of time into security.
You could authenticate with OAuth, which is what the majority of web service API's are using these days.
This tutorial may be of interest to you.

Categories