Using Shippo and PHP to produce shipping labels - php

I almost got it working perfectly, except for generating the labels.
I have this code to generate the rates, which works great:
//Wait for rates to be generated
$attempts = 0;
while (($shipment["object_status"] == "QUEUED" || $shipment["object_status"] == "WAITING") && $attempts < 10)
{
$shipment = Shippo_Shipment::retrieve($shipment["object_id"]);
$attempts +=1;
}
//Get all rates for shipment.
$rates = Shippo_Shipment::get_shipping_rates(array('id'=> $shipment["object_id"]));
$json = json_decode($rates, true);
foreach ($json["results"] as $key)
{
$amount = $key["amount"];
$servicelevel = $key["servicelevel_name"];
$objid = $key["object_id"];
}
As I go through each of the results, I assign them to variables for the different service levels and allow the user to select which shipping method they want to use. I pass the $objid to the next page to produce the label using the following code:
//Write the object_id to a variable
$var = $shiparray[1];
$transaction = Shippo_Transaction::create(array('rate'=>$var));
echo $transaction["object_status"] ."<br>";
// Wait for carrier to create shipping label
$attempts = 0;
while (($transaction["object_status"] == "QUEUED" || $transaction["object_status"] == "WAITING") && $attempts < 10)
{
$transaction = Shippo_Transaction::retrieve($transaction["object_id"]);
$attempts += 1;
}
echo $transaction["object_status"] ."<br>";
// Retrieve label url and tracking number or error message
if ($transaction["object_status"] == "SUCCESS")
{
echo($transaction["label_url"]);
echo("\n");
echo($transaction["tracking_number"]);
}
else
{
echo( $transaction["messages"] );
}
This just produces an error, though. Am I passing the wrong value to produce the label? Should I be using a value produced for the shipment rather then the rate?

this is Simon from Shippo. The link you've posted is actually the Rates response, not the Transaction (it's an array of many Rates, thus the length).
I've quickly checked your account and for your most recent transaction attempts, there's an error message "Rate can't be purchased because the Shippo account doesn't have valid billing settings.". This is because your Shippo user account doesn't have any credit card information, but you're trying to purchase labels in production.
You can enter a valid credit card here https://goshippo.com/user/billing/. The request should work fine as soon as your credit card has been saved!
Let me know if you have any further questions, always happy to help!

Related

How to use break or contnue

I have an array of admission and each student has multiple entry of payment.
Like Admission=[1,2,3,4,5,6] this is admission ids,
and Payment=[[1->1,5,6,2],[2->2,3],[3->4,7,8] this is admission id->payment_ids
foreach($admission as $a)
{
$payment=DB::table('payement')->where('admission_id',$a->admission_id)->get();
foreach($payment as $p)
{
// Here i wan if payment_date <= today_date
// 1. Add all payment
// 2. Else Go to the next admission id
}
}
It sounds like you're looking for something like this:
foreach($admission as $a)
{
$payment = DB::table('payment')->where('admission_id', $a->admission_id)->get();
$totalPayment = 0;
foreach($payment as $p)
{
if (\Carbon\Carbon::parse($p->payment_date)->lessThanOrEqualTo(\Carbon\Carbon::now())) {
$totalPayment += $p->amount;
}
}
}
Inside of the foreach loop on $payment the code above uses Carbon to compare the dates. It looks like you're using Laravel's Eloquent so you should have Carbon available in your application since it's a Laravel dependency. I use Carbon to compare the dates because it knows more about dates than I do.
Next, if it's true that payment_date is less than or equal to the current date then it will add it to the $totalPayment for that admission. Otherwise, it will move onto the next payment. This presumably makes using continue or break unnecessary unless I am misunderstanding something.
I'm not sure what you want to do with $totalPayment. Right now it will be calculated for each admission and then lost.
If you want to find the total payment across all admissions you should move $totalPayment = 0 to the line above foreach($admission as $a).
If you want to find the total payment for each admission you could set a totalPayment on each admission $a->total_payment = $totalPayment. I would then change $totalPayment = 0 to $a->total_payment = 0 and change $totalPayment += $p->amount to $a->totalPayment += $p->amount.

Php-Reports Stripe Building

First question on here as an enthusiast trying to get this to work.
Using the open source project by jdorn PHP-Reports and following the stripe custom reporting tutorials.
The report never returns, what I am trying to achieve is custom Stripe payments reporting using the Stripe API to return all charges, to then display in a nice table 😀
Here is my paymentreport.php code
<?php
//My Payments Report
//This connects to the Stripe Payments api and shows a list of charges
//VARIABLE: { name: "count", display: "Number of Charges" }
// Set your secret key: remember to change this to your live secret key in production
\Stripe\Stripe::setApiKey('StripeTestCodeAPIKEY');
if($count > 100 || $count < 1) throw new Exception("Number of Charges must be between 1 and 100");
// Retrieve a list of 50 most recent charges
$charges = \Stripe\Charge::all(array(
'limit' => 50
));
// Loop through each charge
foreach ($charges->data as $charge) {
// Get the required charge information and assign to variables
$id = $charge->id;
$description = $charge->description;
$created = gmdate('Y-m-d H:i', $charge->created); // Format the time
$amount = $charge->amount/100; // Convert amount from cents to dollars
$currency = $charge->currency;
$rows = array();
foreach($charges as $charge) {
$rows[] = array(
'Charge Id'=>$charge->id,
'Amount'=>number_format($charge->amount/100,2),
'Date'=>date('Y-m-d',$charge->created)
);
}
echo json_encode($rows);
?>
There are a few problems here-- you accept a $count-variable that's never used. I think what you're trying to do is this:
$charges = \Stripe\Charge::all(array(
'limit' => $count
));
Additionally, you've got a loop at the bottom that's broken. You've got to remove the second foreach and move the $rows = array(); outside of the first loop.
Finally, the last call $rows[] = array(...) should probably also include the variables you captured above. Does that make sense?

Quickbooks - Select all payments for an invoice

I am trying to query for all payments assigned to an invoice using the consolibyte quickbooks php toolkit. I was hoping I could pull these back using a query but so far the only way I can see to do it is by grabbing all payments and then looping through and checking what is within the LinkedTxn array and checking if it has a type of 'Invoice' and that the 'TxnId' value matches my stored invoice id. What I have so far is this which gets the payments but is obviously not an option going forward as there may be tens of thousands of payments in the system:
public function getAllPaymentsForInvoice(Invoice $invoice)
{
$query = "SELECT * FROM Payment";
$payments = $this->qbPaymentService->query($this->context, $this->realm, $query);
$lines = [];
foreach ($payments as $payment) {
$num_lines = $payment->countLine();
for ($i = 0; $i < $num_lines; $i++) {
$line = $payment->getLine($i);
$txnId = $this->parseResponse($line->getLinkedTxn()->getTxnId());// convert {-1} to 1
$txnType = $line->getLinkedTxn()->getTxnType();
if ($txnType == 'Invoice' && $txnId == $invoice->qb_ref) {
$lines[] = $line;
}
}
}
return $lines;
}
Can anyone push me in the direction of a better way?
There's no easy, one-liner way to do this using the QuickBooks Online API. This just isn't something that QuickBooks Online itself supports.
There are two separate approaches you could take to optimize what you're doing.
The payments applied should always be for the same customer as the invoices, so you can change your query to SELECT * FROM Payment WHERE CustomerRef = 'xyz' where xyz is the CustomerRef from the invoice. Then, use your existing code to check exactly which invoices payments are applied to.
Use the CDC functionality to keep a cached copy of all payments in your own database, and query your own database for the information instead (a normal SQL database is considerably more flexible and query-able than what QuickBooks Online offers).
The CDC functionality is specifically designed to allow you to keep an accurate, cached copy of the QuickBooks data in your own application, specifically to address situations like you're running into. You pass it a timestamp, and it gives you everything that has changed since that timestamp. By remembering the date/time you last ran the ->cdc(...) method, you can continually get lightweight updates to any objects that have changed since you last queried them.
<?php
$CDCService = new QuickBooks_IPP_Service_ChangeDataCapture();
// What types of objects do you want to get?
$objects = array(
'Payment',
'Invoice',
);
// The date they should have been updated after
$timestamp = QuickBooks_Utilities::datetime($datetime_you_last_called_cdc_method);
$cdc = $CDCService->cdc($Context, $realm,
$objects,
$timestamp);
// You would cache all the stuff you get back here
print_r($cdc);
Docs links:
https://github.com/consolibyte/quickbooks-php/blob/master/docs/partner_platform/example_app_ipp_v3/example_cdc.php
https://developer.intuit.com/docs/0100_accounting/0300_developer_guides/change_data_capture
The question is quite old, anyway, in case someone else is looking for answer:
$InvoiceService = new QuickBooks_IPP_Service_Invoice();
// $invoices = $InvoiceService->query($Context, $realm, "SELECT * FROM Invoice STARTPOSITION 1 MAXRESULTS 10");
// If, we have QB Invoice # i.e.DocNumber
$invoice_no = 1001;
$invoices = $InvoiceService->query($Context, $realm, "SELECT * FROM Invoice WHERE DocNumber = '$invoice_no' ");
foreach ($invoices as $Invoice)
{
$txnId = 0;
if (is_object($Invoice->getLinkedTxn()) && $Invoice->getLinkedTxn()->getTxnType() == 'Payment') {
$txnId = $Invoice->getLinkedTxn()->getTxnId();
}
print('Invoice # '.$Invoice->getDocNumber().' has a total of $'.$Invoice->getTotalAmt().' and Linked Payment ID: ' . $txnId . "\n");
}

Why does eWAY Payment Gateway Lineitems show $0.00 price in the invoice section?

I have integrated eWAY payment gateway. The payments are handled successfully. The problem is that I can not display prices for lineitems correctly in the invoice section of the payment page. Currently all of them appear as $0.00.
This is what I coded to achieve above. I'm just setting lineitems via a loop:
if (!empty($summary_data)) {
for ($i = 0; $i < count($summary_data); $i++) {
$customizations = implode(', ',array_merge($summary_data[$i]['additions'], $summary_data[$i]['minuses'], $summary_data[$i]['extra_info']));
$customizations = !(empty($customizations))?" [".$customizations. "] ":$customizations;
$desc = $summary_data[$i]['name'].$customizations;
$item = new eWAY\LineItem();
$item->SKU = "SKU" . $i;
$item->Description = $desc;
$item->Quantity = 1;
$item->UnitCost = $summary_data[$i]['price'];
$item->Tax = 0;
$item->Total = $summary_data[$i]['price'];
$request->Items->LineItem[$i] = $item;
}
}
Can you please point out what have I missed?
This issue can occur when passing through an invalid value. Please ensure you are passing through the amount in cents value. E.g. to pass $100, pass "10000"
If you require further assistance you can contact the local eWAY team 24/7 via phone or via our LiveChat on our websites.

PDO 'too many connections' when I select all rows from DB

I am trying to write a function that verifies a bank transaction amount against all purchases linked to that transaction. It is possible to link a purchase to more than one transaction and for more than one purchase to link to the same transaction.
The function works by totalling the transactions in question, then running a DB query to select all purchases, then checking each purchase to see if it references any of the transactions in question. It then totals the amount of all purchases linked to any of the transactions and reconciles it by checking if the two totals add up.
My problem is that I always get a 'too many connections' error when I get all the purchases from the database. It's fine if I limit the search, but I need all of them in order for the function to work.
I either need to fix the connection overload issue somehow write the query to only search for purchases containing those transactions - but I'm not sure how to do that.
The transactions are comma separated in a column of the purchase entry.
Interestingly, if the list of purchases is called via AJAX it works fine. But if the page (including other prior connections) is loaded statically - it doesn't work. I'm assuming that because the AJAX is loading one thing, there are no prior connections in that instance.
It is quite a complicated system so this may not be very helpful on its own:
public static function verify($ids, $return = NULL) {
// Transaction total
$transactions = explode(",",$ids);
$transTotal = 0;
foreach($transactions as $transaction) {
$transTotal = $transTotal + self::get($transaction,"amount");
}
// Expense/item total
$accounts = AccItem::getAll("all");
$itemTotal = 0;
foreach($accounts as $item) {
$translink = explode(",",$item->transaction_ids);
if(array_intersect($transactions, $translink)) {
$itemTotal = $itemTotal + AccItem::calculate($item->id,"total") + AccItem::calculate($item->id,"tax");
}
}
unset($accounts);
if($transTotal == $itemTotal or $transTotal + $itemTotal == 0) {
if($return) return 'check';
if(!$return) echo '<abbr title="Transaction verified."><i class="fa fa-check-circle"></i></abbr>';
} else {
if(!$return) echo '<abbr title="Transaction amount mismatch!"><i class="fa fa-exclamation-circle"></i></abbr>';
}
}
And here is the getAll function:
public static function getAll($chart_id, $date_from = 0, $date_to = 9999999999999) {
$db = new Data;
if($chart_id == "all") {
$sql = $db->query("SELECT * FROM mc_account_items WHERE date_incurred >= :date_from AND date_incurred <= :date_to ORDER BY date_incurred DESC");
} else {
$sql = $db->query("SELECT * FROM mc_account_items WHERE chart_id = :chart_id AND date_incurred >= :date_from AND date_incurred <= :date_to ORDER BY date_incurred DESC");
$sql->bindParam(":chart_id", $chart_id);
}
$sql->bindParam(":date_from", $date_from);
$sql->bindParam(":date_to", $date_to);
$sql->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE,'AccItem');
$sql->execute();
return $sql->fetchAll();
//unset($db);
}
So I read into things a bit more, turns out I wanted a persistent connection as it was the same connection every time. Instead of opening a new one it will just use the cached connection.
PDO::ATTR_PERSISTENT => true

Categories