I am working with OpenERP 7's XML-RPC API and I am trying to validate an invoice and apply a payment but I can't figure out what model I should be using.
I have successfully created an invoice and added lines. There doesn't seem to be anything in account.invoice and account.payment.term and payment.order do not seem to work either.
Any help would be appreciated.
Hi i figured out how to validate payment to an invoice automatically via XML-RPC using php.
This how openERP invoice workflow works for the payment.
When you create an invoice, payment to this invoice is done by a voucher i.e. model account.voucher is used to apply a payment to an invoice. So when you create an invoice and validate it, the invoice changes status to open of which you can now access the "customer payments" menu and enter the customer name, the onchange_partner_id() function defined in account.voucher is executed to make a calculation of all the invoices the currently enter partner has open for payments.
Then when you enter the payment to make in "Paid Amount" field, onchange_payment() function is executed to allocate the amount paid to different open invoices of the selected partner.
And when you click validate on the payment form, automatically openerp pays the invoice and marks it as paid.
This therefore means you should atleast understand how openerp handles invoices and payments to that invoice by studying the python code in modules account and account_voucher To make the long story short, this is the code that i used.
First create an invoice for a particular partner and validate it. make sure that you partner has a valid phone number set in res.partner model. (Just create it using openerp forms)
************** php code **********
<?php
error_reporting(1);
/*
* TODO
* Improve on handling of server responses. Success and Failures
*/
date_default_timezone_set('Europe/Moscow');
include_once("openerp_models.php");
/////////////////////////////////////////////////////////////////////
//confirm that a username and password is set
if (isset($_SERVER['PHP_AUTH_USER']) && $_SERVER['PHP_AUTH_PW']) {
//password and username -- Basic Authentication
$username = $_SERVER['PHP_AUTH_USER'];
$password = $_SERVER['PHP_AUTH_PW'];
///important parameters
$phone_no = $_REQUEST['sender_phone']; //get the mobile number. Use this number to get the partner information.
$amount = $_REQUEST['amount']; // get amount from url
$amount_again = $_REQUEST['amount']; //this will be displayed to the paying client. $amount above is reduced to zero hence
//we create another amount variable to show the customer with success message.
$payment_ref = $_REQUEST['k2_transaction_id']; // get this from url
$firstname = $_REQUEST['first_name'];
$lastname = $_REQUEST['last_name'];
$middlename = $_REQUEST['middle_name'];
$service_name = $_REQUEST['service_name'];
$business_number = $_REQUEST['business_number'];
$transaction_reference = $_REQUEST['transaction_reference'];
$internal_transaction_id = $_REQUEST['internal_transaction_id'];
$transaction_timestamp = $_REQUEST['transaction_timestamp'];
$transaction_type = $_REQUEST['transaction_type'];
$account_number = $_REQUEST['account_number'];
$currency = $_REQUEST['currency'];
$signature = $_REQUEST['signature'];
//openerp instance, pass login,password,dbname and serverURL
$kengen_model = new OpenERPXmlrpc($username, $password, 'copia_training_db', 'http://127.0.0.1:8069/xmlrpc/');
/* TODO UNCOMMENT THIS CODE FOR ACTUAL TESTING WITH KOPOKOPO SERVER
* We will then authorize kopokopo to continue with record creation. But before that,
* we should make sure that the request is actually coming from kopokopo using the signature value sent.
* To learn more see https://app.kopokopo.com/push_api
*
//set up base string
$base_string = "account_number=".$account_number."&amount=".$amount."&business_number=".$business_number."&"
. "currency=".$currency."&first_name=".$firstname."&internal_transaction_id=".$internal_transaction_id."&"
. "last_name=".$lastname."&middle_name=".$middlename."&sender_phone=".$phone_no."&service_name=".$service_name."&transaction_reference=".$transaction_reference."&"
. "transaction_timestamp=".$transaction_timestamp.""
. "transaction_type=".$transaction_type." ";
//get the symmetric key from table keys.api. This key should be copied from Your KopoKopo Account
$get_key = $kengen_model->search('keys.api', 'provider_name', '=', 'KopoKopo') ;
$key_id = $get_key[0];
$key_value = '' ;
//we read
$read_keys = $kengen_model->read('keys.api', [$key_id]);
//loop
foreach ($read_keys as $keys => $values) {
$value = $values->scalarval();
// print_r($value);
// print '<br/>';
//$myarray [] = array($value['name']->scalarval());
$key_value = $value['key_value']->scalarval();
}
// print $key_value; exit;
//data to use
$hash_data = hash_hmac('sha256', $base_string, $key_value, true);
//generate our own signature to compare with
$signature_to_test = base64_encode($hash_data) ;
///test if the parameter $signature passed by KopoKopo is equal to $signature_to_test
// print $signature_to_test;
* TODO, DO the actual testing with Real KEY_VALUE and Request from kopokopo and only allow execution if
* $signature_to_test = $signature else return an access denied status
*/
/////////////////////////////////////////
/* We retrieve the payment journal for kopokopo. We will
* use the journal code to retrieve the journal id.
* The code for kopokopo should be KPKPJ
*/
$get_jrnl_code = $kengen_model->search('account.journal', 'code', '=', 'KPKPJ') ;
$journal_id = $get_jrnl_code[0]; //kopokopo journal
/*
* We retrieve the account_id to pay to. This code is code for KopoKopo Account
* should be static i.e. 2040 is the account unless otherwise specified.
*/
$get_acc_code = $kengen_model->search('account.account', 'code', '=', '2040') ;
$account_id = $get_acc_code[0]; //kopokopo account
//for this record to appear on list of customer payment
$type = 'receipt';
//
/* TODO
* after a successful login, we must authorize this user. We do this to make sure that
* the request if coming from kopokopo server.
*/
//now search for the partner using phone/mobile number parameter
$search_partner = $kengen_model->search('res.partner', 'phone', '=', $phone_no);
//check to make sure that the customer exists
//create an array
$ids = array();
//loop through the $search content and assign its contents to the $ids
for ($i = 0; $i <= count($search_partner); $i++) {
// print $search_partner[$i];
$ids [] = $search_partner[$i];
}
// if a user exist we continue processing
if (count($ids[0]) > 0) {
//perform a read, by picking the first item on the array
$read = $kengen_model->read('res.partner', [$ids[0]]);
// print_r($read);
$myarray = null;
$client_name = '';
//this foreach loop with only loop once. hence just retrieve the client name and amount saved
// in openerp
foreach ($read as $keys => $values) {
$value = $values->scalarval();
// print '<br/>';
//$myarray [] = array($value['name']->scalarval());
$client_name = $value['name']->scalarval();
}
/////////////////////////////////////////////////////
//get invoices, pass partner_id and invoice status which is open for unpaid invoices
//get invoices to retrieve the journal id
$get_invoices = $kengen_model->getPartnetInvoices('account.voucher', $ids[0], 'open');
$retrieved_pay_account_id = 0;
$pay_journal_id = 0;
$period_id = 0;
foreach ($get_invoices as $keys => $values) {
$value = $values->scalarval();
$retrieved_pay_account_id = $value[4]->scalarval();
$pay_journal_id = $value[5]->scalarval();
$period_id = $value[6]->scalarval();
$move_id = $value[7]->scalarval();
}
// print $retrieved_account_id;
/////////////////////////////////////////////////////
//fields to create
$account_voucher_fields = array(
'partner_id' => $ids[0],
'amount' => $amount,
'reference' => $payment_ref,
'journal_id' => $journal_id,
'account_id' => $account_id,
// 'move_id' => $move_id ,
// 'journal_id'=> $retrieved_journal_id,
'type' => $type);
//voucher payment
$create_kopokopo_payment = $kengen_model->createRecord($account_voucher_fields, 'account.voucher');
//we get the total amount of invoice available for this customer.
$total_invoices_amount = $kengen_model->getPartnetInvoices('account.voucher', $ids[0], 'open');
$invoice_totals = 0;
foreach ($total_invoices_amount as $keys => $values) {
$value = $values->scalarval();
$invoice_totals += $value[3]->scalarval();
///
}
// print 'invoice totals is '.$invoice_totals ;
//voucher line payment
//we will retrieve all invoices available for this partner
//get invoices, pass partner_id and invoice status which is open for unpaid invoices
$invoices = $kengen_model->getPartnetInvoices('account.voucher', $ids[0], 'open');
//loop through available invoices. Remember that a customer can have more than one open invoice
$total_credit = 0;
foreach ($invoices as $keys => $values) {
$value = $values->scalarval();
$number = $value[1]->scalarval();
$invoice_amount_to_pay = $value[3]->scalarval();
/*
* To undestand how this code works look at account.voucher model in openerp
* function recompute_voucher_lines(). This openerp function calculates voucher lines given
* a particular payment.
*/
$min_amount = min($invoice_amount_to_pay, $amount);
//
/* print 'x';
print 'on existing invoices in ELSE IF >>>' . ($min_amount);
print '<br/>';
print 'amount_unreconciled is >>>' . ($invoice_amount_to_pay);
print '<br/>';
print 'total_credit is >>>' . $amount;
print '<br/>'; */
///
//reduce amount paid
$amount -= $min_amount;
//convert amount into int
$amount_to_allocate = intval($min_amount);
// print $amount_total ;
///get invoice move line ids
$new_number = str_replace('/', '', $number); //convert the invoice line
$move_ids = $kengen_model->search('account.move.line', 'ref', '=', $new_number);
/////
$account_voucher_line_fields = array(
'partner_id' => $ids[0],
'voucher_id' => $create_kopokopo_payment, //last id inserted in account.voucher
'account_id' => $retrieved_pay_account_id,
'move_line_id' => $move_ids[0],
'amount' => $amount_to_allocate,
'type' => 'cr',
'name' => $number,);
//////
$create_kopokopo_line_payment = $kengen_model->createRecord($account_voucher_line_fields,
'account.voucher.line');
}
/*
* we validate the payment. We access method button_proforma_voucher declared in model account.voucher
* This methods validates an invoice payment and does reconcilation process for us if the user has paid
* fully else the method reconciles invoice partially.
*/
$validate_voucher_payment = $kengen_model->call_function_func('account.voucher',
'button_proforma_voucher', array($create_kopokopo_payment));
//customer found. Return a json response for KopoKopo
$message = "Thank you " . $client_name . " for your payment of Ksh " . $amount_again . ". We value your business";
// see doc # https://app.kopokopo.com/push_api
$success_response = array("status" => "01", "description" => "Accepted",
"subscriber_message" => $message);
echo json_encode($success_response);
return json_encode($success_response);
}
// else we return a json_response with error message
else {
//customer not found. Return a json response for KopoKopo
// see doc # https://app.kopokopo.com/push_api
$error_response = array("status" => "02", "description" => "Account not found");
echo json_encode($error_response);
return json_encode($error_response);
}
} else {
header('WWW-Authenticate: Basic realm="Copia ERP"');
header('HTTP/1.0 401 Unauthorized');
print 'Access Denied';
exit();
}
?>
Hope this will help you.
Related
On my website we keep transactions as pending and capture them when we ship (often we need to change amounts/cancel and it makes it easier accounting wise to work like that).
When we are ready to ship, we match all specified orders (with specified order status) with the invoice#/order id in authorize.
the issue is that the authorize.net API only allows for 1000 transaction limit so when using their GetUnsettledTransactionListRequest function it is missing transactions that are unsettled passed that amount.
I am able to set the paging limit to 1000 and I can also set the offset to 1000 (or 999 not sure which yet) so I think what I need to do is something like check if the array storing the results size is 1000 and if so get the next 1000 results to store in the array. But about about the next loop do I have to manually say 3000, 4000, 5000 (we don't have that many transactions but still).
here is my current code:
function getUnsettledTransactionList()
{
//get orders that are in the exp status
$orders_pending_query = tep_db_query("select orders_id as invoice_number from " . TABLE_ORDERS . " where orders_status = '15' order by invoice_number");
$orders_pending = array();
while ($row = mysqli_fetch_array($orders_pending_query, MYSQLI_ASSOC)) {
$orders_pending[] = $row;
}
/* Create a merchantAuthenticationType object with authentication details
retrieved from the constants file */
$merchantAuthentication = new AnetAPI\MerchantAuthenticationType();
$merchantAuthentication->setName(\SampleCodeConstants::MERCHANT_LOGIN_ID);
$merchantAuthentication->setTransactionKey(\SampleCodeConstants::MERCHANT_TRANSACTION_KEY);
// Set the transaction's refId
$refId = 'ref' . time();
$request = new AnetAPI\GetUnsettledTransactionListRequest();
$request->setMerchantAuthentication($merchantAuthentication);
$controller = new AnetController\GetUnsettledTransactionListController($request);
$response = $controller->executeWithApiResponse(\net\authorize\api\constants\ANetEnvironment::PRODUCTION);
$transactionArray = array();
$resulttrans = array();
if (($response != null) && ($response->getMessages()->getResultCode() == "Ok")) {
if (null != $response->getTransactions()) {
foreach ($response->getTransactions() as $tx) {
$transactionArray[] = array(
'transaction_id' => $tx->getTransId(),
'invoice_number' => $tx->getInvoiceNumber()
);
// echo "TransactionID: " . $tx->getTransId() . "order ID:" . $tx->getInvoiceNumber() . "Amount:" . $tx->getSettleAmount() . "<br/>";
}
//match the array column by invoice mumber to find all the transaction ids for cards to capture
$invoiceNumbers = array_column($orders_pending, "invoice_number");
$result = array_filter($transactionArray, function ($x) use ($invoiceNumbers) {
return in_array($x["invoice_number"], $invoiceNumbers);
});
$resulttrans = array_column($result, "transaction_id");
print_r($resulttrans);
} else {
echo "No unsettled transactions for the merchant." . "\n";
}
} else {
echo "ERROR : Invalid response\n";
$errorMessages = $response->getMessages()->getMessage();
echo "Response : " . $errorMessages[0]->getCode() . " " . $errorMessages[0]->getText() . "\n";
}
return $resulttrans;
}
GetUnsettledTransactionListRequest offers the ability to page the results. So you after you process the first 1,000 results you can request the next 1,000 results.
I don't use the Authnet SDK but it looks like you can use AnetAPI\PagingType() to handle the paging for you:
$pagenum = 1;
$transactionArray = array();
do {
// ...code truncated...
$request = new AnetAPI\GetUnsettledTransactionListRequest();
$request->setMerchantAuthentication($merchantAuthentication);
// Paging code
$paging = new AnetAPI\PagingType();
$paging->setLimit("1000");
$paging->setOffset($pagenum);
$request->setPaging($paging);
$controller = new AnetController\GetUnsettledTransactionListController($request);
// ...code truncated...
$numResults = (int) $response->getTotalNumInResultSet();
// ...code truncated...
$pagenum++;
} while ($numResults === 1000);
The JSON would resemble this:
{
"getUnsettledTransactionListRequest": {
"merchantAuthentication": {
"name": "",
"transactionKey": ""
},
"paging": {
"limit": "1000",
"offset": "1"
}
}
}
I am wiring up the Authorize.net API for a web site and I have created a cart system where all is well so far. My issue is with the way I am using a parameter in one of the class function calls. It will only work if I use single quotes surrounding my string. I cannot use a variable at all it throws an error which is the reason I am here asking this question. For example:
$lineItem->setDescription('SOME TEXT GOES HERE'); // works perfectly
$foo = 'SOME TEXT GOES HERE';
$lineItem->setDescription($foo); // fails
$lineItem->setDescription("$foo"); // fails
// I tried all kinds of ways like:
$foo = "SOME TEXT GOES HERE"; // double quotes
$lineItem->setDescription($foo); // fails
// I tried this too and this works but In my case I am within a loop
define("FOO", $foo);
$lineItem->setDescription(FOO); // works but I need to loop all the items
// I tried this
$foo = json_encode($foo);
$lineItem->setDescription($foo); // fails?
// It seems like this would work but I know this is not realistic.
$lineItem->setDescription('$foo'); // this is just for illustrative purposes
So what am I doing wrong? If I could print a variable in single quotes it would seem to work but PHP doesn't work like that. Can anyone give me another way to get this to work?
Thanks in advance.
Let me show the full function so everyone can see whats happening...
use net\authorize\api\contract\v1 as AnetAPI;
use net\authorize\api\controller as AnetController;
function AuthorizeNet(){
require 'assets/authorizenet/vendor/autoload.php';
define("AUTHORIZENET_LOG_FILE", "phplog");
// Common setup for API credentials
$merchantAuthentication = new AnetAPI\MerchantAuthenticationType();
$merchantAuthentication->setName($GLOBALS['authorizenet_api']);
$merchantAuthentication->setTransactionKey($GLOBALS['authorizenet_tx']);
// Create the payment data for a credit card
$creditCard = new AnetAPI\CreditCardType();
$creditCard->setCardNumber("4111111111111111");
$creditCard->setExpirationDate("2038-12");
$paymentOne = new AnetAPI\PaymentType();
$paymentOne->setCreditCard($creditCard);
// Create the Bill To info
$billto = new AnetAPI\CustomerAddressType();
$billto->setFirstName("Ellen");
$billto->setLastName("Johnson");
$billto->setCompany("Souveniropolis");
$billto->setAddress("14 Main Street");
$billto->setCity("Pecan Springs");
$billto->setState("TX");
$billto->setZip("44628");
$billto->setCountry("USA");
$billto->setPhoneNumber("310-867-5309");
$total = 0;
$tax=0;
$shipping=0;
$items_subtotal = 0;
$discount_total = 0;
$lineItem_Array = array();
$i=0;
// Create the items
foreach($_SESSION['ms_cart'] as $cart_item){
$desc = array();
if(!empty($cart_item["size"])){
$desc[] = "Size: " . $cart_item["size"];
}
if(!empty($cart_item["color"])){
$desc[] = "Color: " . $cart_item["color"];
}
$description = implode(", ", $desc);
if(!empty($cart_item["discount_total"])){
$discount_total = $discount_total+round($cart_item["discount_total"],2);
}
$name = $cart_item["name"];
$desc = $description;
$quantity = $cart_item["qty"];
$price = $cart_item["price"];
$sku = $cart_item["uiid"];
$items_subtotal = ($price*$quantity)+$items_subtotal;
$lineItem = new AnetAPI\LineItemType();
$lineItem->setItemId($sku);
$lineItem->setName($name); // <-- this is my issue
$lineItem->setDescription($desc); // <-- also here
$lineItem->setQuantity(1);
$lineItem->setUnitPrice(1);
$lineItem->setTaxable(0); // 1 Yes 0 for no
$lineItem_Array[$i] = $lineItem;
$i++;
}
$subtotal = round($items_subtotal, 2);
if(!empty($_SESSION['ms_cart_tax'])){
$tax = number_format(round($_SESSION['ms_cart_tax'], 2), 2, '.', '');
}
if(!empty($_SESSION['ms_ship_rate'])){
$shipping = round($_SESSION['ms_ship_rate'], 2);
}
$total = ($subtotal+$tax+$shipping)-$discount_total;
$total = round($total,2);
// Create a transaction
$transactionRequestType = new AnetAPI\TransactionRequestType();
$transactionRequestType->setTransactionType( "authCaptureTransaction");
$transactionRequestType->setBillTo($billto);
$transactionRequestType->setLineItems($lineItem_Array);
$transactionRequestType->setPayment($paymentOne);
$total=4; // there are 4 items in my cart loop for now I have hard coded the 4
$transactionRequestType->setAmount($total);
$request = new AnetAPI\CreateTransactionRequest();
$request->setMerchantAuthentication($merchantAuthentication);
$request->setTransactionRequest($transactionRequestType);
$controller = new AnetController\CreateTransactionController($request);
$response = $controller->executeWithApiResponse($GLOBALS['authorizenet_env']);
if ($response != null)
{
$tresponse = $response->getTransactionResponse();
if (($tresponse != null) && ($tresponse->getResponseCode()=="1") )
{
echo "Charge Credit Card AUTH CODE : " . $tresponse->getAuthCode() . "\n";
echo "Charge Credit Card TRANS ID : " . $tresponse->getTransId() . "\n";
}
else
{
echo "Charge Credit Card ERROR : Invalid response\n";
}
}
else
{
echo "Charge Credit card Null response returned";
}
}
This was not a good solution for me. I ended up removing the php-sdk and creating my own function to call Authorize.net's API. With some simple PHP JSON and cURL. I was up and running in an hour. Sometimes fussing around with API's can make you spend more time than just writing from scratch. I would like to thank everyone that took the time to take look and provide feedback.
I used paypal php sdk with this :
https://github.com/paypal/merchant-sdk-php/blob/master/samples/RecurringPayments/CreateRecurringPaymentsProfile.php
Express checkout is works well, but use recurring payments have problem : token is invalid.
Line 152 in the sdk, it's said
A timestamped token, the value of which was returned in the response
to the first call to SetExpressCheckout. Call
CreateRecurringPaymentsProfile once for each billing
agreement included in SetExpressCheckout request and use the same
token for each call. Each CreateRecurringPaymentsProfile request
creates a single recurring payments profile.
But i don't understand how to "Call CreateRecurringPaymentsProfile once in SetExpressCheckout", there is my code:
public function createPayToken($returnUrl, $cancelUrl, $payModeData) {
$itemName = $payModeData['name'];
$order = $payModeData['fee'];
// $category = 'Digital';
$category = 'Physical';
$currencyCode = "USD";
$paymentDetails = new PaymentDetailsType();
$itemAmount = new BasicAmountType($currencyCode, $order);
$itemDetails = new PaymentDetailsItemType();
$itemDetails->Name = $itemName;
$itemDetails->Amount = $itemAmount;
$itemDetails->Quantity = 1;
$itemDetails->ItemCategory = $category;
$paymentDetails->OrderTotal = new BasicAmountType($currencyCode, $order);
$paymentDetails->PaymentAction = 'Sale';
$paymentDetails->PaymentDetailsItem[] = $itemDetails;
$setECReqDetails = new SetExpressCheckoutRequestDetailsType();
$setECReqDetails->PaymentDetails[] = $paymentDetails;
$setECReqDetails->ReqConfirmShipping = 0;
$setECReqDetails->NoShipping = 1;
$setECReqDetails->AddressOverride = 0;
$setECReqDetails->CancelURL = $cancelUrl;
$setECReqDetails->ReturnURL = $returnUrl;
$setECReqType = new SetExpressCheckoutRequestType();
$setECReqType->SetExpressCheckoutRequestDetails = $setECReqDetails;
$setECReq = new SetExpressCheckoutReq();
$setECReq->SetExpressCheckoutRequest = $setECReqType;
$paypalService = new PayPalAPIInterfaceServiceService();
try {
$setECResponse = $paypalService->SetExpressCheckout($setECReq);
exit;
} catch (Exception $ex) {
echo $ex;
exit;
}
if(isset($setECResponse)) {
if($setECResponse->Ack =='Success') {
$token = $setECResponse->Token;
return $token;
}
var_dump($setECResponse);
exit;
}
return false;
}
Thank you.
You just need to make sure you're including the billing agreement information in your SetExpressCheckout request. Take a look at this sample of set of API calls to complete a recurring payments profile using Express Checkout.
You'll notice the SEC request includes parameters for L_BILLINGTYPE0 AND L_BILLINGAGREEMENTDESCRIPTION0. You need to make sure you include those, otherwise the token that you get back won't be valid for CreateRecurringPaymentsProfile.
I have been trying to export all of our invoices in a specific format for importing into Sage accounting. I have been unable to export via Dataflow as I need to export the customer ID (which strangely is unavailable) and also a couple of static fields to denote tax codes etc…
This has left me with the option of using the API to export the data and write it to a CSV. I have taken an example script I found (sorry can’t remember where in order to credit it...) and made some amendments and have come up with the following:
<?php
$website = 'www.example.com';
$api_login = 'user';
$api_key ='password';
function magento_soap_array($website,$api_login,$api_key,$list_type,$extra_info){
$proxy = new SoapClient('http://'.$website.'/api/soap/?wsdl');
$sessionId = $proxy->login($api_login, $api_key);
$results = $proxy->call($sessionId,$list_type,1);
if($list_type == 'order_invoice.list'){
/*** INVOICES CSV EXPORT START ***/
$filename = "invoices.csv";
$data = "Type,Account Reference,Nominal A/C Ref,Date,Invoice No,Net Amount,Tax Code,Tax Amount\n";
foreach($results as $invoice){
foreach($invoice as $entry => $value){
if ($entry == "order_id"){
$orders = $proxy->call($sessionId,'sales_order.list',$value);
}
}
$type = "SI";
$nominal = "4600";
$format = 'Y-m-d H:i:s';
$date = DateTime::createFromFormat($format, $invoice['created_at']);
$invoicedOn = $date->format('d/m/Y');
$invoiceNo = $invoice['increment_id'];
$subtotal = $invoice['base_subtotal'];
$shipping = $invoice['base_shipping_amount'];
$net = $subtotal+$shipping;
$taxCode = "T1";
$taxAmount = $invoice['tax_amount'];
$orderNumber = $invoice['order_id'];
foreach($orders as $order){
if ($order['order_id'] == $orderNumber){
$accRef = $order['customer_id'];
}
}
$data .= "$type,$accRef,$nominal,$invoicedOn,$invoiceNo,$net,$taxCode,$taxAmount\n";
}
file_put_contents($_SERVER['DOCUMENT_ROOT']."/var/export/" . $filename, "$header\n$data");
/*** INVOICES CSV EXPORT END ***/
}else{
echo "nothing to see here";
}/*** GENERIC PAGES END ***/
}/*** END function magento_soap_array ***/
if($_GET['p']=="1")
{
magento_soap_array($website,$api_login,$api_key,'customer.list','Customer List');
}
else if($_GET['p']=="2")
{
magento_soap_array($website,$api_login,$api_key,'order_creditmemo.list','Credit Note List');
}
else if($_GET['p']=="3")
{
magento_soap_array($website,$api_login,$api_key,'sales_order.list','Orders List');
}
else if($_GET['p']=="4")
{
magento_soap_array($website,$api_login,$api_key,'order_invoice.list','Invoice List');
}
?>
This seems to be working fine, however it is VERY slow and I can’t help but think there must be a better, more efficient way of doing it…
Has anybody got any ideas?
Thanks
Marc
i think on put break; would be okey. because only one key with order_id, no need to looping after found order_id key.
if ($entry == "order_id"){
$orders = $proxy->call($sessionId,'sales_order.list',$value);
break;
}
and you can gather all call(s) and call it with multicall as example:
$client = new SoapClient('http://magentohost/soap/api/?wsdl');
// If somestuff requires api authentification,
// then get a session token
$session = $client->login('apiUser', 'apiKey');
$result = $client->call($session, 'somestuff.method');
$result = $client->call($session, 'somestuff.method', 'arg1');
$result = $client->call($session, 'somestuff.method', array('arg1', 'arg2', 'arg3'));
$result = $client->multiCall($session, array(
array('somestuff.method'),
array('somestuff.method', 'arg1'),
array('somestuff.method', array('arg1', 'arg2'))
));
// If you don't need the session anymore
$client->endSession($session);
source
With the help of https://github.com/ph/magento-moneris I have managed to create a Moneris payment gateway in Magento and I am testing it now with Moneris Development site.
I have got a couple of questions where I am confused and don't know how to proceed.
Is there a way I can set 'Authorize only' to 'Authorize and Capture' some where in the code so that the capture is performed at the same time when the order is placed?
Also Is there a way that the invoicing can be done at the same time as the order is placed with the invoice mail sent to the customer n store owner.
Ex: when the 'Place Order' is clicked, the customer's card details are checked and validated. If they are ok, then the payment is captured at the same time in the merchant's account and the invoice emails are sent to the customer and store owner.
If the card details are not right, then show an appropriate message on front end to the customer as well keep that order as pending with appropriate reason for the store owner to see.
The code I have for now is for _authorize n _capture functions. Do they need to be modified or new functions needs to be created.
public function authorize(Varien_Object $payment, $amount)
{
$error = false;
// check for payment
if($amount > 0) {
$payment->setAmount($amount);
// Map magento keys to moneris way
$order = $payment->getOrder();
$billing = $order->getBillingAddress();
$avsTemplate = array('avs_zipcode' => $order->getBillingAddress()->getPostcode(), 'avs_street_number' => $order->getBillingAddress()->getStreet(1),'', 'avs_street_name' => $order->getBillingAddress()->getStreet(2),'');
$mpgAvsInfo = new mpgAvsInfo($avsTemplate);
$cvdTemplate = array('cvd_value' => $payment->getCcCid(),'cvd_indicator' => 1);
$mpgCvdInfo = new mpgCvdInfo($cvdTemplate);
$transaction = $this->_build($payment, self::TRANSACTION_PREAUTH);
$transaction->setAvsInfo($mpgAvsInfo);
$transaction->setCvdInfo($mpgCvdInfo);
$response = $this->_send($transaction);
$payment->setCcApproval($response->getReceiptId())
->setLastTransId($response->getReceiptId())
->setCcTransId($response->getTxnNumber())
->setCcAvsStatus($response->getAuthCode())
->setCcCidStatus($response->getResponseCode());
if($response->getResponseCode() > 0 && $response->getResponseCode() <= self::ERROR_CODE_LIMIT)
{
$payment->setStatus(self::STATUS_APPROVED);
$message = 'AVS Response: ' . Mage::helper('paygate')->__($this->_errors[$response->getAvsResultCode()]);
$message .= '<br>CVD Response: ' . Mage::helper('paygate')->__($this->_errors[$response->getCvdResultCode()]);
Mage::getSingleton('core/session')->addSuccess($message);
}
else if($response->getResponseCode() > self::ERROR_CODE_LIMIT && $response->getResponseCode() < self::ERROR_CODE_UPPER_LIMIT)
{
$error = Mage::helper('paygate')->__($this->_errors[$response->getResponseCode()]);
}
else
{
$error = Mage::helper('paygate')->__('Incomplete transaction.');
}
}
else
{
$error = Mage::helper('paygate')->__('Invalid amount for authorization.');
}
if ($error !== false)
Mage::throwException($error);
return $this;
}
/**
* Capture the authorized transaction for a specific order
* #var Variant_Object $payment
* #var Float $amount
*/
public function capture(Varien_Object $payment, $amount) {
$error = false;
// check for payment
if ($amount <= 0)
{
Mage::throwException(Mage::helper('paygate')->__('Invalid amount for capture.'));
}
if($amount > 0)
{
$payment->setAmount($amount);
// Map magento keys to moneris way
$transaction = $this->_build($payment, self::TRANSACTION_COMPLETION);
$response = $this->_send($transaction);
if($response->getResponseCode() > 0 && $response->getResponseCode() <= self::ERROR_CODE_LIMIT)
{
$payment->setStatus(self::STATUS_SUCCESS);
$message = 'AVS Response: ' . Mage::helper('paygate')->__($this->_errors[$response->getAvsResultCode()]);
$message .= '<br>CVD Response: ' . Mage::helper('paygate')->__($this->_errors[$response->getCvdResultCode()]);
Mage::getSingleton('core/session')->addSuccess($message);
}
else if($response->getResponseCode() > self::ERROR_CODE_LIMIT && $response->getResponseCode() < self::ERROR_CODE_UPPER_LIMIT)
{
$error = Mage::helper('paygate')->__($this->_errors[$response->getResponseCode()]);
}
else
{
$error = Mage::helper('paygate')->__('Incomplete transaction.');
}
}
else
{
$error = Mage::helper('paygate')->__('Invalid amount for capture.');
}
// we've got something bad here.
if ($error !== false)
Mage::throwException($error);
return $this;
}
Feel free to correct me anywhere or suggest a better way of doing what I'm trying to do.
In the end I'm looking forward to build a basic Moneris payment gateway in Magento which authorizes n captures the amount if the card details are right and sends invoice mails to customer n store owner all at the same time at the click of 'place order'.
And if the card details are wrong then show appropriate message to customer and keep it as pending with right reason for pending payment for the store owner to see.