Jump to content
  • Checkout
  • Login
  • Get in touch


The e-commerce.

[Contribution]Paypal IPN - Devosc


Recommended Posts

This is what I thought would be correct, but I'm getting and unexpected T String error hmmmm..........


tep_draw_hidden_field('t3', '$order->products[$i]['attributes'][$j]['value']') .


My php sucks :)

Link to comment
Share on other sites

  • Replies 2.1k
  • Created
  • Last Reply

Top Posters In This Topic

} else { //method 1
 for ($i=0; $i<sizeof($order->products); $i++) {
   $item_number .= ' '.$order->products[$i]['name'].' ,';
   if ($order->products[$i]['attributes']) {
     for ($j=0, $j<sizeof($order->products[$i]['attributes']); $j++) {
       if($order->products[$i]['attributes'][$j]['option'] == 'M'){
         $subsciption_type = 'M';
       } elseif($order->products[$i]['attributes'][$j]['option'] == 'Y') {
         $subsciption_type = 'Y';
 $item_number = substr_replace($item_number,'',-1);
 $paypal_fields .= tep_draw_hidden_field('item_number', $item_number);
 $paypal_fields .= tep_draw_hidden_field('t3', $subsciption_type);


Something like the above, but the above presumes that no Monthly and Yearly products are in that same order, since the above will only recall the last product option in the list. Not sure whether 'option' is the right field to be using, see includes/order.php for list of possibilities. Might help if you:


to see which is the right one to use.


Your error before was because of nested 's normally in a string the inner ones would be escaped (\')


In regard to purchasing and distinguishing between normal products and subscription products you'd probably be better off asking in the URL=http://www.paypaldev.org/]PayPal Development Forum[/url] for an absolute answer.


An interesting though then occurs how to do multiple subscriptions.

"Any fool can know. The point is to understand." -- Albert Einstein

Link to comment
Share on other sites

Read too fast,


tep_draw_hidden_field('t3', '$order->products[$i]['attributes'][$j]['value']') .


should be

tep_draw_hidden_field('t3', $order->products[$i]['attributes'][$j]['value']) .


There are other reasonings....

"Any fool can know. The point is to understand." -- Albert Einstein

Link to comment
Share on other sites

Greg, thanks very much for those changes for a resume button on the Order Information screen. Works great.


However, I am still getting 25% of orders in "Pending PayPal Notification" limbo. I phoned 2 customers and both said "I wanted to pay by credit card, not paypal". I'm starting to think it's the PayPal screen that's confusing.


So here's my big question: When a customer confirms their order, it always jumps to PayPal's Payment Details screen. Is there a way to jump directly to the Billing Information screen, where they type their card number? Too many people don't see that little Click Here button.


Then I could:



Link to comment
Share on other sites

Yeah I was thinking the same thing, perhaps a better field would be the


values_id field,


but I would need to convert the value _id field to an M or Y and then equate that to a variable like $subscription for instance.


Then I could simply call


tep_draw_hidden_field('t3', $subscription) .


in the paypal.php file.


Would that work?


I'm just not sure how to write the code for the, sorry :unsure:

Link to comment
Share on other sites

Hi Bob,


Those changes are an outline of what is available, but at present it reuses too much of the existing code, in particular it is the return and cancel urls, since if they cancel they return to the shopping cart itself, and if they return upon completion of payment they would currently return to checkout_sucess.php which would either clear their existing shopping cart or return them to the shopping cart page, I think since they're resuming they should just be either returned to the homepage or directly to their 'my account' page. Easiest method would be to copy and paste the function _getPayPalFields and rename to _getPayPal_ResumePaymentFields, and edit the return urls (not the ipn notify url).


In regard to the other question I haven't heard of a short cut, I think this might be worth asking PayPal directly, I'll try myself and see. The other problem is that if the customer is a PayPal member and has already got cookies set by PayPal, then when they return to the PayPal site they are not given the option to pay via the credit card method, rather they are expected to login.


The PayPal Development Forum is a good palce to raise these questions since it will be more quickly be read by the PayPal team members and raise awareness.

"Any fool can know. The point is to understand." -- Albert Einstein

Link to comment
Share on other sites

I'm pretty that any multi supscription order would have to all be the same subscription length anyway to be included in the same order. I think PayPal would hit the persons account for the entire amount of the order on the same transaction.


So in other words if I was going to charge 20.00 bucks a month for Content Management Services let's say, and the customer wanted a pay his hosting on a yearly basis to save money he'd have to do 2 different orders. I don't think there is any way for the system to differentiate that, so that should not be a problem anyway.


If someone wanted to pay monthly for both they could do that on the same order, it just wondn't seperate the two services, but lump them together in one payment.


Getting close!


Thanks for the help Greg!

Link to comment
Share on other sites

I also tried changing catalog/checkout_process.php to


require(DIR_WS_CLASSES . 'order.php');

$order = new order;


require(DIR_WS_CLASSES . 'order_total.php');

$order_total_modules = new order_total;


$order_totals = $order_total_modules->process();


// load the before_process function from the payment modules



and catalog/includes/modules/payment/paypal/checkout_process.php


  global $payment_modules, $shipping_modules, $order, $currencies, $cart, $customer_id,

        $sendto, $billto, $shipping, $payment, $language, $currency, $languages_id, $order_total_modules, $order_totals;


and :


if(!class_exists('order_total')) {

include(DIR_WS_CLASSES . 'order_total.php');

$order_total_modules = new order_total;

$order_totals = $order_total_modules->process();



eventhough i don't have ccgv.


Thanks again!

If using ccgv is this still needed in version 2.4?


global $payment_modules, $shipping_modules, $order, $currencies, $cart, $customer_id,

$sendto, $billto, $shipping, $payment, $language, $currency, $languages_id, $order_total_modules, $order_totals;

Edited by talon177
Link to comment
Share on other sites

Hi Talon,


Not sure whether the above is totally correct, you need to remeber the via IPN, e.g. paypal/checkout_update.php there is no browser/session interaction.


What you could do is store that session info, e.g. that they are purchasing without an account.


First need to add a field to orders_session_info:

ALTER TABLE orders_session_info ADD customer_pwa tinyint(1) NOT NULL default '0';


Now in paypal/application_top.php

$customer_pwa = $orders_session['customer_pwa'];


Now in paypal/checkout_process.php

if(tep_session_is_registered('noaccount')) {

$sql_data_array['customer_pwa'] = 1;



So now where you had

if (!tep_session_is_registered('noaccount')) {

should now be something like

if ($customer_pwa) {


The above is just a quick out line, see the earlier post also regarding the osC-Affiliate, this shows a bit more info on location, and the preliminary idea about storing session info existing at the time of customer/browser/session interaction.

Thanks greg, I just inputed this and will let u know how it works!

Link to comment
Share on other sites

Hi Bob, no you are freely allowed to use PayPal payment icons.

In regard to the 'Pending PayPal Notification' issue and above, during the checkout should the customer click back from the PayPal site they can still resume that checkout sequence (updating the order if neccessary) so they should not be subject to being charged twice in this regard.

Your above image motivated me to have a look at providing a resume button for transactions that are logged as 'Pending PayPal Notification', there is a slight risk in providing such a functionality since if the customer has paid but the payment is either PayPal.Pending or the IPN has not yet been received (could be up to 4 days), then in these instances it could be possible for the customer to go through and pay a second time, actually if you sychronized your invoice order numbers with PayPal then it would not be allowed.


The following will highlight the changes to be made to trivially provide a resume order checkout feature which will post the customer directly to the PayPal website with the exact same information as they previously had, this is similiar to creating a 'PayPal Money Request', and the changes below are preliminary just for 'Aggregate' Carts, e.g. shipping cost and total cost, how CCGV comes into play has not been identified yet.


[1] catalog/includes/classes/order.php (around line 44)

$order_total_query = tep_db_query("select text , value from " . TABLE_ORDERS_TOTAL . " where orders_id = '" . (int)$order_id . "' and class = 'ot_total'");

$order_total = tep_db_fetch_array($order_total_query);


[2] catalog/includes/classes/order.php (around line 47)

$shipping_method_query = tep_db_query("select title , value from " . TABLE_ORDERS_TOTAL . " where orders_id = '" . (int)$order_id . "' and class = 'ot_shipping'");

$shipping_method = tep_db_fetch_array($shipping_method_query);


[3] catalog/includes/classes/order.php (around line 60)

'date_purchased' => $order['date_purchased'],

'orders_status_id' => $order['orders_status'],

'shipping_cost' => $shipping_method['value'],

'total_value' => $order_total['value'],

'orders_status' => $order_status['orders_status_name'],

'last_modified' => $order['last_modified'],


[4] catalog/includes/modules/payment/paypal.php (around line 159)

function _getPayPalFields($currency = '', $orders_id = '') {


[5] catalog/includes/modules/payment/paypal.php (around line 161)


$my_currency = $this->currency();


$my_currency = (tep_not_null($currency)) ? $currency : $this->currency();


[6] catalog/includes/modules/payment/paypal.php (around line 188)


$paypal_fields .= tep_draw_hidden_field('rm', MODULE_PAYMENT_PAYPAL_RM) .
tep_draw_hidden_field('custom', $paypal_order_id) .


$paypal_fields .= tep_draw_hidden_field('rm', MODULE_PAYMENT_PAYPAL_RM);
$custom = (tep_not_null($orders_id)) ? $orders_id : $paypal_order_id;
$paypal_fields .= tep_draw_hidden_field('custom', $custom) .


[7] catalog/account_history_info.php (around line 238)


<td><?php echo '<a href="' . tep_href_link(FILENAME_ACCOUNT_HISTORY, tep_get_all_get_params(array('order_id')), 'SSL') . '">' . tep_image_button('button_back.gif', IMAGE_BUTTON_BACK) . '</a>'; ?></td>


 ? ? ? ? ? ? ? ?<td><div style="float:left"><?php echo '<a href="' . tep_href_link(FILENAME_ACCOUNT_HISTORY, tep_get_all_get_params(array('order_id')), 'SSL') . '">' . tep_image_button('button_back.gif', IMAGE_BUTTON_BACK) . '</a>'; ?></div>
<?php if(strtolower($order->info['payment_method']) == 'paypal' && $order->info['orders_status_id'] == MODULE_PAYMENT_PAYPAL_PROCESSING_STATUS_ID ) { ?>
include_once(DIR_WS_MODULES . 'payment/paypal/database_tables.php');
include_once(DIR_WS_MODULES . 'payment/paypal.php');
$paypal = new paypal();
$paypal_button = $paypal->_getPayPalFields();
<div style="float:right">
$form_action_url = 'https://www.paypal.com/cgi-bin/webscr';
echo tep_draw_form('checkout', $form_action_url, 'post');
$orders_session_query = tep_db_query("select entry_firstname as firstname, entry_lastname as lastname from " . TABLE_ORDERS_SESSION_INFO . " osi left join " . TABLE_ADDRESS_BOOK . " ab on osi.billto = ab.address_book_id where osi.orders_id ='" . (int)$HTTP_GET_VARS['order_id'] . "'");
$orders_session_info = tep_db_fetch_array($orders_session_query);
$order->customer['firstname'] = $orders_session_info['firstname'];
$order->customer['lastname'] = $orders_session_info['lastname'];
$order->info['total'] = $order->info['total_value'];
echo $paypal->_getPayPalFields($order->info['currency'],$HTTP_GET_VARS['order_id'])."\n";
echo tep_image_submit('button_confirm_order.gif', IMAGE_BUTTON_CONFIRM_ORDER) . '</form>' . "\n";
<?php } ?>
? ? ? ? ? ? ? ?</td>

Remember that in order for PayPal to be able to prevent the customer from checking out with the same order number, then invoice synchronization must be enabled via osC->admin->modules->payment->paypal. And if you ever end up reseting your osC orders table you will have to reset/update the orders table auto-increment value to be higher than any previous PayPal order.


The above has only been quickly implemented, and I haven't tested the whole sites functionality, but pretty confident that it will do the job intended based upon the above changes (hopefully I captured them all), anyway it can be can worked on.

Has anyone tried this with ccgvyet?

Link to comment
Share on other sites

Woah I jsut found something wierd, i hope someone can help. Here's what I did. I bought a gift certificate of 5 dollars. Now next time i did a test shop and clicked on redeem when making a purchase using paypal and then I reach the paypal website and it shows the totals but when i accidently clicked back, it went back to the website and my 5 dollars disappeared allthough i never bought anything. Anyone ever experience this?

Link to comment
Share on other sites

} else { //method 1
?for ($i=0; $i<sizeof($order->products); $i++) {
? ?$item_number .= ' '.$order->products[$i]['name'].' ,';
? ?if ($order->products[$i]['attributes']) {
? ? ?for ($j=0, $j<sizeof($order->products[$i]['attributes']); $j++) {
? ? ? ?if($order->products[$i]['attributes'][$j]['option'] == 'M'){
? ? ? ? ?$subsciption_type = 'M';
? ? ? ?} elseif($order->products[$i]['attributes'][$j]['option'] == 'Y') {
? ? ? ? ?$subsciption_type = 'Y';
? ? ? ?}
? ? ?}
? ?}
?$item_number = substr_replace($item_number,'',-1);
?$paypal_fields .= tep_draw_hidden_field('item_number', $item_number);
?$paypal_fields .= tep_draw_hidden_field('t3', $subsciption_type);

I think this may work Greg but I'm not sure where to put it exactly. I tried putting it in the paypal.php file but it brought back an error.





Link to comment
Share on other sites

Hi All. Greg, I'm lost again. :(


Took your advice and reinstalled everything (and I PRAY I can just move my products from the backup database to the new one or else there goes 3 wks of work).... did a clean install of oscommerce and the paypal module.


Got it working great, no problems (which is amazing for my low tech sql skills) but I can't get the test page to work. No IPN in the order. My order goes through just fine but in my order history all I get is "No IPN history available" and there are 0 orders listen under Admin > Customers > PayPal IPN.


I set up IPN with PayPal. Just 2 little changes right? Check the IPN enable box and type in my domain (do I type in the subdomain since my store is in a folder and not in the main html folder?).


What do I do? Everything is working great. Adding members, checking out, sending e-mails. Just this IPN issue.


Thanks for any advice and BTW you owe me an e-mail, Greg. :)

Link to comment
Share on other sites

Greg, about step [6] of the order resume modification, don't I need to change paypal's "invoice" variable, as well as their "custom" variable to avoid duplicate payments from the resubmission? In other words, around line 200 of catalog/includes/modules/payment/paypal.php, shouldn't I change:


if(MODULE_PAYMENT_PAYPAL_INVOICE_REQUIRED == 'True') $paypal_fields .= tep_draw_hidden_field('invoice', $paypal_order_id );




if(MODULE_PAYMENT_PAYPAL_INVOICE_REQUIRED == 'True') $paypal_fields .= tep_draw_hidden_field('invoice', $custom );


Without this change, I could make a duplicate payment. With this change I get the desirable error from PayPal: "This invoice has already been paid..."

Link to comment
Share on other sites

Quickbooks IIF modification for Paypal IPN v2.4


I just updated my Paypal contrib from v1.7 to v2.4. Thanks Greg for all the hard work! This is a great contrib!!


The only issue I have to resolve now is with the Quickbooks IIF file generation contrib I have installed. I use Quickbooks accounting software, and it works great. For every transaction that is processed through our system, the corresponding information is created in a file that can then be downloaded into Quickbooks for accounting purposes.


When I was running Paypal IPN v1.7, I had the following statement inserted in catalog/ipn.php:

// Quick Books
if (CREATE_SALE_QB_IIF_FILE) {include(DIR_WS_INCLUDES . 'qb_iif_sale.php');}

This statement was located in catalog/ipn.php right after this code:

$customer_notification = (SEND_EMAILS == 'true') ? '1' : '0';
$sql_data_array = array('orders_id' => $insert_id, 
                        'orders_status_id' => '99999', 
                        'date_added' => 'now()', 
                        'customer_notified' => $customer_notification,
                        'comments' => $order->info['comments']);
tep_db_perform(TABLE_ORDERS_STATUS_HISTORY, $sql_data_array);

The Quickbooks statement above invoked the Quickbooks mod to write the transaction information to the Quickbooks IIF file once the transaction was complete.


With Paypal IPN v2.4, the file catalog/ipn.php is completely changed. So, I'm hoping someone can tell me where I should insert this Quickbooks statement within the new Paypal IPN v2.4 contribution. As I'm not exactly sure how the new Paypal IPN works, is there someone out there that can tell me where I could install this line?

Link to comment
Share on other sites

Dawn, what happens when you send a test IPN, do you get a blank page?


Bob, you're correct, I had only realized the association between resuming and specifying the inv. # at the time of writing the above thread.


There is one other niggling aspect and that is the customer's name, by default osC stores their firstname and lastname in one field, this makes it tricky to then want to split their name back into first and last respectively, in the resume code the customers name is retrieved from theit billto address, which could be different from what was on the order. This info is used to pre-populate the PayPal sign up form, so although it is not that significant it would be nice to have things tidy, what may be considered is to add another two fields to the orders_session_info db table and to store their first and last name respectively.


There are opinions about whether the default customers address or their billto to address should be used to pass to pre-populate the PayPal sign up field, however the bill to address doesn't include a telephone number, anyway untill PayPal decides to possibly also allow this info to prepopulate the cc form maybe, then for now the customers default address should suffice.


Craig, look in catalog/includes/modules/payment/paypal/checkout_update.php. You may need to ensure that you have all the variables required for the QB contrib.

"Any fool can know. The point is to understand." -- Albert Einstein

Link to comment
Share on other sites

Greg I took your suggestion and posted my problems with PayPal in the PayPal Developer Network forums, paypaldev.org. After collecting several customer complaints myself, and seeing others in that forum, I started two threads there:

Please pardon my intrusion here, I know this is off-topic. But perhaps if others are having these problems we can get PayPal to be a better Merchant Service Provider.

Link to comment
Share on other sites

Dawn, what happens when you send a test IPN, do you get a blank page?

Hi Greg. :) Ok, just to clear up in case I'm having a blond moment....


I do the test page by creating a customer and then checking out? Or by using John Doe? Can't use John Doe, need to log on or create an acct and don't know Mr. Doe's password.


So I created a new customer and checked out and that's where the no IPN problem comes up. So until I get the IPN # I can't run the test page? Or is that incorrect?


I know this test is supposed to be simple but I'm overlooking something.

Edited by sunsetwebdesign
Link to comment
Share on other sites

Dawn, what happens when you send a test IPN, do you get a blank page?


Forgot to say, yes, I get a blank page if I run the test. I don't have any order or IPN number to test with. No transaction number, no PayPal customer details whatsoever show up.

Edited by sunsetwebdesign
Link to comment
Share on other sites

i have managed to get through the mammoth task of installing this fine, with the exception of one error. this is that there is no link in my admin section in the customer category.


i think i know why this is but i dont know the solution.


in the instructions it says that this must be changed in includes/boxes/customers.php....

'<a href="' . tep_href_link(FILENAME_ORDERS, '', 'NONSSL') . '" class="menuBoxContentLink">' . BOX_CUSTOMERS_ORDERS . '</a>');


however in my customers.php there is nothing like this they all look like this



so i attempted to change the link and instead added this

tep_admin_files_boxes(FILENAME_PAYPAl, BOX_CUSTOMERS_PAYPAL ) .
//end PayPal_Shopping_Cart_IPN


but it isnt working.


any ideas?


(just as an aside - when i try to run a test i get a forbidden page appear. anyideas?)

"because it'll hurt more"- the greatest film of all time?

Link to comment
Share on other sites

Just a quick question.


I just installed the new version IPN.

Everything works fine after testing LIVE with a friends CC Visa.


The small issue I have is once you click "return to Merchant" in PayPal. it takes me to the shopping cart (empty now) and NOT the normal Order Complete page in oSC.


How can I have IPN send the customer back to the normal order complete page in OsC?



Edited by JohnnyVegas
Link to comment
Share on other sites



Looks like you are using teh admin contribution -


Did you add the paypal.php to the files in Admin Files? That link will not show until you do.


Also make sure you have the filename defined and the BOX_CUSTOMERS_PAYPAL defined.


It should like something like this:








if you do not have creat order just remove that....

osC Contributions I have published.


Note: Some I only provided minor changes, updates or additions!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...