PHP/MySQL result to process multiple records - php

I am currently building a payment module which processes a customers account once a month. I have a query which gets all the customer payment items for the given month, sums the amount and then sends the data to the payment gateway. This works great and I receive back confirmation from the bank yes or no. If yes I then need to update all the items which were in the request with the invoice number. I am getting the sum using a while loop and this is performed before the request is sent. The gateway can only process a single request and I don't want to loop through each invoice item for each request, I would rather perform a single request for all outstanding invoice items.
Some code is:
$get_payment_items_query = mysql_query("SELECT * FROM tbl_invoice_item WHERE billing_cycle = date");
while($get_payment_items_result = mysql_fetch_assoc($get_payment_items_query)){
$invoice_amount = $invoice_amount + $get_payment_items_result['payment_amount'];
}
then later after I get the response back from the bank I am adding a record to the invoice table and getting the invoice id and then do:
$update_payment_item_query = mysql_query("UPDATE tbl_invoice_item SET status = '" . PAYMENTCOMPLETE . "', invoice_id = '$invoice_id' WHERE invoice_item_id = '" . $get_payment_items_result['invoice_item_id'] . "'");
This only updates a single record because the update query is outside the while loop. I know there is a way to store the record identifier in a string/array and perform a single update query but I don't really know the name for something like that so haven't been able to find an example.
I hope that makes sense but here is some more detail.
There are 5 items ready to be invoiced. I get the total amount of the 5 items. I then make a single request to the payment gateway to charge for the 5 items. The bank send back a response yes or no. If yes, I then generate an invoice id for the payment. I then need to update the 5 items with the newly created invoice id. The updating the 5 items in a single query is where I am stuck.
Thanks in advance.

I do not know if I understand your question right but you could use a sub-query in your where. Use the first query in where of second query:
WHERE invoice_item_id IN (SELECT invoice_item_id FROM tbl_invoice_item WHERE billing_cycle = date)

Found the solution. I am using a WHERE IN clause.
In the while loop I create a variable to hold the items which need to be updated
$invoice_item_id .= $get_payment_items_result['invoice_item_id'] . ',';
I then remove the last comma using substring_replace then in the update query I use
WHERE invoice_item_id IN (" . $invoice_item_array . ")
Seems to work OK.

Related

Calculate total due in php codigniter

I have a small billing software written in php CodeIgniter. This is how i save values when i submit a payment
<?php
public function addPayment() {
$id = $this->input->post('id');
$client_id = $this->input->post('client_id');
$date = strtotime($this->input->post('date_from_addpayment'));
$description = $this->input->post('description');
$cash_pending = $this->input->post('cash_pending');
$cash_recevied = $this->input->post('cash_recevied');
$balance = $cash_pending - $cash_recevied;
?>
When each transaction occur I want to sum all the due of the client at that time and save it in balance table in MySQL.
My PHPMySQL structure of payment column is as follow:
https://i.stack.imgur.com/ELJrL.png
I just want when user ADD THE PAYMENT then balance due at that time display in this column.
Screenshot: https://i.imgur.com/raboF4M.png
To my understanding, balance, due, cash_pending - all 3 field relates - refers to the same figure - the amount that is pending. What i believe is you need to restructure the code for a bit.
You need to have a table maintaining clients balance (like current one you have). Just u can remove cash_pending / due fields.
You then need to have another table that will record in transactions of all the cash received. And as and when the cash is received, you can just substract that amount from the balance for the client.
In case any excess amount needs to be added for something like cash given or so - that you can add to the clients balance field back. So all the time - you have a proper balance figure for the client and also have a record of all the cash received from the user.
First of all before ending the php tag close your function's curly bracket.
In your table id is auto increment so do not need to take id as a input to store in database.
put all required fields as your table structure like this.
$data = array('client_id'=>$client_id, 'date'=>$date,
'description'=>$description, 'cash_recevied'=>$cash_recevied, 'cash_pending'=>$cash_pending,
'due'=>$due );
$this->load->model('Your-model-name');
$this->your-model-name->function-name($data);
Now call your model. and then in your model do this
function FunctionName($data){
return $this->db->insert('tablename', $data);
}

CS-Cart The transaction was not sent to the host because of a duplicate order id

I'm using Menoris payment processor on CS-Cart v 4.3.9, a while ago this error has become more frequent "Payment processor response: The transaction was not sent to the host because of a duplicate order id".
I don't understand why is it happening, so I don't know where to look, I have tried to trigger the error myself but couldn't.
Check you table cscart_orders and have a look at those IDs.
I dont think you've reched the maximum limit of mysql entries in cscart_order to be duplicate (16777215 - is the maximum value for the field with the integer type).
In my opinion the problem is where you send data, consider to ask them for that.
Check this too: http://forum.cs-cart.com/topic/45830-issue-with-order-id/
Please change the code and create an unique order id for each time a customer try to pay the order, something like
ex: 12345_1
where order_id = 12345 and 1 order_repaid value
you can check how 2checkout payment gateway is doing for example ;) app/payments/2checkout.php
...
$cart_order_id = ($order_info['repaid']) ? ($order_id .'_'. $order_info['repaid']) : $order_id;
...
if Monoris doesn't accept for order_id to be string than you will need to generate and unique order_id for each time customer try to buy and attach to order_id in this way on payment return you will be able to get the real order_id and compete the payment
*[duplicate order id] - issue is happening when a customer goes to Monoris payment page and customer click cancel or get back to website and after that he goes again to pay the order
Thanks all for your answers, i have managed to solve this by adding a time stamp next to the order id
'order_id' => $processor_data['processor_params']['order_prefix'] . $order_info['order_id'] .'_'. date("G:i:s"),

Using two where clauses in MYSQL UPDATE query using PHP

Working on a lightweight invoicing system and I'm trying to update my 'items' table correctly without fully succeeding.
Once an invoice is saved, I need to mark the items as paid that were purchased so far that day for that buyer.
Right now this is my query:
$markitemspaidquery = "UPDATE solditems SET paidstatus='paid', paidtime='$date' WHERE buyerid='$buyer_id'";
This updates the records for the buyer correctly, but the problem is it will mark EVERY item in the table for that buyer 'paid'; even if it is from 3 days ago.
How can I use a query kind of like this one or achieve this affect?
$markitemspaidquery = "UPDATE solditems SET paidstatus='paid', paidtime='$date' WHERE buyerid='$buyer_id' AND DATE(timesold)=CURDATE() AND paidstatus='unpaid'";
In all reality, everything should be paid by the end of the day anyway because of the way the company works, but I would like to know for future reference since it's just using up unnecessary resources to update every item for the buyer.
Here is an example with order by and limit
update questions
set prepStatus=1,status_bef_change=status,cv_bef_change=closeVotes,max_cv_reached=greatest(max_cv_reached,closeVotes)
where status='O' and prepStatus = 0
order by qId desc
limit 900;
There is a flaw in your datamodel. You have items sold and invoices but no connection between them.
So you muddle your way through be saying: when there is an invoice on a day for a customer it must be an invoice exactly covering all items on that very day bought by that customer. This is a rule you are kind of making up - the database doesn't tell you this.
So have a reference in your sold items table to the invoice table. Once an invoice is entered in the system it must be linked to all items sold it includes. Thus the update is easy, or better not necessary, as it is not the sigle item sold which is paid, but the invoice. So the sold items shouldn't have columns paidstatus and paidtime, but the invoice should.
UPDATE: Here is an example for a working data model. Each item has an invoice number which is null at first. Once the customer checks out an invoice is written and all the customer's items without an invoice number get this new invoice number. The invoice's total amount is the sum of its items. I.e. you don't store the sum redundantly.
auction_item
auction_item_no - primary key
customer_no - not null
description - not null
price - not null
invoice_no - nullalble (null as long as not checked out)
invoice
invoice_no - composite primary key part 1
customer_no - composite primary key part 2
date_time - not null

Hide variable in URL

I am working on a OpenCart based eCommerce website and would like to know how to hide the variables passed in a URL. The reason I want to do this is that we allow the customer to print their invoice at the end of a successful transaction and the structure of the URL is as follows:-
http://www.mywebsite.com/invoice/standard&order_id=1000010
Now the thing is, if you change the last value of the order_id to anything else or even change any of the other digits, it will show you the invoice for that order number and if that order_id belongs to another customer, it will show their details to this customer.
So now what I would like to know is that is there a good way to encrypt this url and decrypt it on the server-side to complete the request without showing the user order_id.
Please let me know if you need anymore info and I'll try and add it to my question.
I don't have experience with Opencart, but chances are it checks whether the current user is logged in, and displays the invoice only if it belongs to them.
If that is not the case, the underlying problem should be fixed instead, and access to invoices limited to the customer (e.g. through a login system), instead of creating security through obscurity.
You shouldn't need to do this really, instead you should be validating the logged in user for that invoice within the model/DB File.
For example....
I assume as it stands, your DB query would be similar to this:
$this->db->query("SELECT * FROM `" . DB_PREFIX . "order` WHERE order_id = `" . (int)$order_id . "`");
You should check also check the customer_id:
$this->db->query("SELECT * FROM `" . DB_PREFIX . "order` WHERE order_id = `" . (int)$order_id . "` AND customer_id = '" . (int)$this->customer->getId() . "'");
If the invoice is not owned by that customer, then no results would be found.
I haven't worked with Opencart but I believe the order_id being displayed in the URL is not the big problem. The major issue here is that other users can view another user's invoice. You have to perform access control for non-public pages like these. ONLY allow the owner to look at their own invoice.
Now to answer your question, to prevent your order_id from being shown on the URL, you need to use POST data, currently you are using GET. You can access POST data using $_POST.
This is not a standard feature, and as such you should contact the developer of the extension. If your store allows guest checkouts, then the URL should contain a random key of some sort, or the e-mail address attached to the order for instance to validate that the request is from an authorised user only. If the order is for a registered user then the customer_id assigned to the order should be validated against the current logged in user, and redirected to a login if the user is not logged in

What is the best way to increment invoice ID?

I'm developing a simple invoice system using PHP and MySQL.
My initial thought was to use ID (auto incremented) for invoice ID. But that will not work.
A temporary invoice is created when user commits an order to my Payment Service Provider.
If the transaction fails, I need to delete the temporary invoice.
The problem is that the invoice has been created and given and ID - and by law, I'm not allowed to delete any invoices that has been given a invoice number. So I need to add another column 'invoice_id' and add an ID after successful transaction.
Multiple users may do a purchase at the same time.
My question is, how can I make sure to retrieve the last created invoice ID and increment this?
Should I use a $_SESSION[]for storing invoice_id? Or should I retrieve latest ID from DB? If retrieving from DB, should I lock the table for this transaction?
Any guidance much appreciated.
Create a temporary table for invoices which have not been processes.
Once the invoice has been processed, move over to permanent table and assign an invoice id using the AUTO_INCREMENT option in mysql
This will allow for two tables, one for unprocessed and the other for processed. You can also place an id field to keep track of the movement from temp -> perm
I wouldn't delete it, I would just cancel it. Additional usually after a failed transaction the trader reminds the customer to pay, which is not possible, when the invoice doesn't exist anymore.
One approach would be to keep the invoice in session until the payment has been approved. If the payment is not approved, the invoice will die with the user's session.
Another approach would be to create a holding table for pending invoices. When payment is approved, simply move the data into the invoice table.
And the last approach, go ahead and create the invoice in the invoice table, but soft delete it if the payment fails. Just set a flag, deleted = 1 and in all your procs add "where deleted = 0".
I would generate purely random invoice numbers. Simplest strategy:
md5(uniqid())
But still – storing unfinished invoices in the database sounds more sane.
Also the random factor will make guessing the invoice number more difficult.

Categories