/[drupal]/contributions/modules/ec_mvmg/gozabocheckout.module
ViewVC logotype

Contents of /contributions/modules/ec_mvmg/gozabocheckout.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.7 - (show annotations) (download) (as text)
Thu Aug 2 12:39:38 2007 UTC (2 years, 3 months ago) by suydam
Branch: MAIN
CVS Tags: HEAD
Changes since 1.6: +49 -19 lines
File MIME type: text/x-php
Final dev release of this module.  It will not be finalized for public consumtpion as too much site-proprietary code has been inserted.  I make this release just as an offering to anyone who might want to see how we accomplished this.
1 <?php
2
3 // $Id: gozabocheckout.module,v 1.37.2.5.2.1.2.12 2007/03/04 12:05:32 gordon Exp $
4
5 /********************************************************************
6 * Drupal Hooks
7 ********************************************************************/
8
9 /**
10 * Implementation of hook help().
11 */
12 function gozabocheckout_help($section = 'admin/help#gozabocheckout') {
13
14 switch ($section) {
15 case 'admin/ecsettings/gozabocheckout':
16 return t('<p>This module splits txns into multiple txns and allows each to be paid seperately. Messy.</p>');
17 }
18 }
19
20 /**
21 * Implementation of menu_hook()
22 */
23 function gozabocheckout_menu($may_cache) {
24
25 $items = array();
26
27 if ( !$may_cache) {
28 global $user;
29 // only show this for logged in users in their own account pages...they're going to select their payment gateways
30 // also show for admin users
31 // access => $user->uid means "uid>0" which in turn means "registered user"
32 if ( ( ( ( arg(0) == 'user' && arg(1) == $user->uid ) || ( arg(0) == 'user' && arg(1) == $user->name ) ) && user_access('Configure own payment settings') )
33 || ( arg(0) == 'user' && user_access('Admin payment settings') ) ) {
34 $items[] = array(
35 'path' => 'user/' . arg(1) . '/gozaboconfig',
36 'title' => 'Store Settings',
37 'callback' => 'configure_gozabo_settings',
38 'type' => MENU_CALLBACK,
39 'access' => $user->uid,
40 'weight' => 9
41 );
42
43 }
44
45 // vendors and admins can see this tab (on the my_account page)
46 // access => $user->uid means "uid>0" which in turn means "registered user"
47 if ( ( ( ( arg(0) == 'user' && arg(1) == $user->uid ) || ( arg(0) == 'user' && arg(1) == $user->name )) && user_access('manage transactions from own store') )
48 || ( arg(0) == 'user' && user_access('admin transactions from any store') ) ) {
49 $items[] = array(
50 'path' => 'user/' . arg(1). '/vendortxns',
51 'title' => t('Orders'),
52 'callback' => '_gozabo_show_vendor_transaction_list',
53 'type' => MENU_CALLBACK ,
54 'access' => $user->uid,
55 'weight' => 10
56 );
57 }
58
59 // txn editor for vendors
60 // access => $user->uid means "uid>0" which in turn means "registered user"
61 $items[] = array(
62 'path' => 'gozabocheckout/edittxn',
63 'title' => t('Gozabo Checkout - Edit Txn'),
64 'type' => MENU_CALLBACK,
65 'access' => $user->uid,
66 'callback' => '_gozabo_edittxn'
67 );
68
69
70 // this one shows the buyer their order history
71 // access => $user->uid means "uid>0" which in turn means "registered user"
72 $items[] = array(
73 'path' => 'gozabocheckout/showtxns',
74 'title' => t('Gozabo.com Checkout'),
75 'callback' => '_gozabo_show_transaction_list',
76 'type' => MENU_CALLBACK ,
77 'access' => $user->uid
78 );
79
80 // txn cancellation for buyers
81 // access for registered users...will check uid vs. mvmgtxnid when we get to the callback.
82 $items[] = array(
83 'path' => 'gozabocheckout/buyercanceltxn',
84 'title' => t('GoZabo Checkout - Cancel Txn'),
85 'callback' => '_gozabo_buyer_cancel_txn',
86 'type' => MENU_CALLBACK,
87 'access' => $user->uid
88 );
89
90 // handle our custom payments (using ec_mvmg as a transaction and ec_transaction_product as the goods)
91 // supported payment methods come from ec_mvmg_userstore_settings
92
93 // access => $user->uid means "uid>0" which in turn means "registered user"
94 $items[] = array(
95 'path' => 'gozabocheckout/paypal',
96 'title'=> t('Paypal Payment Screen'),
97 'type' => MENU_CALLBACK,
98 'callback' => 'gozabo_payment_processor_paypal',
99 'access' => true
100 );
101
102 $items[] = array(
103 'path' => 'gozabocheckout/cod',
104 'title' => t('Gozabo.com C.O.D. Payment Screen'),
105 'callback' => '_gozabo_show_cod_payment_form',
106 'type' => MENU_CALLBACK ,
107 'access' => true
108 );
109
110 // temp function to handle roles upgrade testing
111 // also added a function to buyer's order histor to click on for this
112 $items[] = array(
113 'path' => 'gozabocheckout/ecroles',
114 'title' => t('Gozabo.com Roles'),
115 'callback' => '_gozabo_roles_processor',
116 'type' => MENU_CALLBACK ,
117 'access' => true
118 );
119
120
121 }
122
123 if ($may_cache) {
124 $items[] = array(
125 'path' => 'gozabocheckout/ipn',
126 'title' => t('GozaboCheckout IPN'),
127 'callback' => 'gozabocheckout_ipn',
128 'access' => true,
129 'type' => MENU_CALLBACK
130 );
131 $items[] = array(
132 'path' => 'admin/ecsettings/gozabocheckout',
133 'title' => 'gozabocheckout',
134 'callback' => 'drupal_get_form',
135 'callback arguments' => 'gozabocheckout_ec_settings',
136 'access' => user_access('administer store'),
137 'type' => MENU_NORMAL_ITEM,
138 'description' => t('Configuration for the gozabocheckout payment gateway'),
139 );
140 }
141 return $items;
142 }
143
144 function _gozabo_show_cod_payment_form() {
145 $output = drupal_get_form('cod_payment_form');
146 return $output;
147 }
148
149 function check_parent_txn_for_completion( $mvmgtxnid ) {
150 $statement = "SELECT txnid FROM ec_mvmg WHERE mvmgtxnid = $mvmgtxnid";
151 $row = db_fetch_array( db_query( $statement ));
152 $txnid = $row['txnid'];
153
154 // get status for all ec_mvmg's with txnid = $row['txnid']
155 $statement = "SELECT COUNT(*) as thecount FROM ec_mvmg WHERE txnid = " . $txnid . " AND payment_status = 1";
156 $row = db_fetch_array( db_query( $statement ));
157 if ( !$row['thecount'] ) {
158 $statement = "UPDATE ec_transaction SET payment_status=" . payment_get_status_id('payment received') . " WHERE txnid=" . $txnid;
159 }
160 }
161
162 function cod_payment_form_submit( $form_id, $form_values ) {
163 global $user;
164 // 1. set payment status to 7 (payed by not confirmed)
165 // 2. deliver info to the seller
166 // 3. check the parent txn in ec_transation...if they're all done Pending then update that one t the lowest status number
167 // 4. route the user back to their transaction list.
168
169 $mvmgtxnid = arg(2);
170
171 // 1. set payment status to 7 (payed but not confirmed)
172 $statement = "UPDATE ec_mvmg SET payment_status=" . payment_get_status_id('payment received') . " WHERE mvmgtxnid=$mvmgtxnid";
173 //print $statement;
174 $sth = db_query( $statement ) or exit("ERROR WITH $statement");
175
176 // 2. deliver info to the seller
177 $statement = "
178 SELECT
179 m.*,
180 u.uid AS u_uid,
181 u.mail AS u_mail,
182 u.name AS u_name
183 FROM ec_mvmg m LEFT JOIN users u ON u.uid = m.vendor WHERE mvmgtxnid = $mvmgtxnid
184 ";
185 //print "<BR>".$statement;
186 $mvmg_row = db_fetch_array( db_query( $statement ) );
187 if ( !isset($mvmg_row['uid']) || $mvmg_row['uid'] != $user->uid ) {
188 drupal_set_message("Transaction $mvmgtxnid doesn't belong to you (" . $user->uid . ").",'error');
189 return '';
190 }
191 //print"<PRE>";print_r($mvmg_row);exit;
192 $mailbody = "User " . $user->uid . " made a purchase from your GoZabo.com store. Please login and process the purchase.\n\n";
193 if ( $form_values['contact_phone'] == 1) {
194 $mailbody .= "If necessary, buyer has requested you contact them by phone at:" . $form_values['phone'] . "\n";
195 }
196 if ( $form_values['contact_email'] == 1) {
197 $mailbody .= "Contact them by email at " . $user->mail . "\n";
198 }
199 if ( $form_values['message'] ) {
200 $mailbody .= 'The buyer has also left you the following note: ' . $form_values['message'] . "\n";
201 }
202 drupal_mail("codpayment_$mvmgtxnid",$mvmg_row['u_mail'],"GoZabo.com: COD Payment for Transaction $mvmgtxnid",$mailbody,$user->mail);
203
204 // 3. check the parent txn in ec_transation...if they're all done Pending then update that one t the lowest status number
205 check_parent_txn_for_completion( $mvmgtxnid );
206
207 // 3 & 1/2. Product api hook to allow for inventory mgmt (and other fun stuff)
208 drupal_set_message("Message delivered. The seller will contact you shortly.");
209 _gozabo_completion_callback( $mvmgtxnid );
210
211 // 4. route the user back to their transaction list.
212 drupal_goto('gozabocheckout/showtxns');
213 }
214
215 function cod_payment_form() {
216 // C.O.D. payment requires that the user confirms their desire to buy with an email to the vendor
217 // after that, it's as simple as updating the status to 7 (payed but not confirmed)
218 global $user;
219
220 $mvmgtxnid = arg(2);
221
222 // print "<PRE>"; print_r( $user ); print "</pre>"; exit;
223
224 // first off make sure that the user calling this page is the user who owns the mvmgtxn
225 // die if not
226 $mvmg_row = db_fetch_array( db_query( "SELECT * FROM ec_mvmg WHERE mvmgtxnid = $mvmgtxnid " ) );
227 if ( !isset($mvmg_row['uid']) || $mvmg_row['uid'] != $user->uid ) {
228 drupal_set_message("Transaction $mvmgtxnid doesn't belong to you (" . $user->uid . ").",'error');
229 return '';
230 }
231
232 $form['#redirect'] = FALSE;
233 $form['pretext'] = array(
234 '#prefix' => '<h1>C.O.D. Payment</h1><P>Transaction ID: mvmg' . $mvmgtxnid . '</p><P>',
235 '#value' => 'The C.O.D. method of payment requires that you contact the seller to arrange payment. Please fill out the form below. <strong>All fields are required.</strong>',
236 '#suffix' => '<P>'
237 );
238
239 // for confirmation
240 /* UPDATE: dont' even need this stuff...
241 $form['buyer_uid'] = array(
242 '#type' => 'value',
243 '#value' => $user->uid
244 );
245
246 $form['buyer_email'] = array(
247 '#type' => 'value',
248 '#value' => $user->mail
249 );
250
251 $form['seller_uid'] = array(
252 '#type' => 'value',
253 '#value' => $mvmg_row['vendor']
254 ); */
255
256 $form['message'] = array(
257 '#type' => 'textarea',
258 '#title' => t('Message to seller'),
259 '#cols' => 45,
260 '#rows' => 5,
261 '#description' => t('Please include instructions to the seller here.'),
262 );
263
264 $form['contact_phone'] = array(
265 '#type' => 'checkbox',
266 '#title' => 'Seller may contact me by phone',
267 );
268
269 $form['phone'] = array(
270 '#type' => 'textfield',
271 '#title' => 'Your phone number',
272 '#size' => 30,
273 '#maxlength' => 64,
274 '#description' => '(optional)'
275 );
276
277 $form['contact_email'] = array(
278 '#type' => 'checkbox',
279 '#title' => 'Seller may contact me by email',
280 );
281
282 $form['submit'] = array(
283 '#type' => 'submit',
284 '#value' => 'Submit'
285 );
286
287 return $form;
288
289 }
290
291 function configure_gozabo_settings() {
292 $output = drupal_get_form('gozabo_store_settings');
293 return $output;
294 }
295
296 function gozabo_store_settings_submit( $form_id, $form_values ) {
297 global $user;
298
299 //print "<PRE><h1>form values:</h1>";print_r($form_values);print "<HR>";print_r($user);print "</pre>";exit;
300
301 // insert or update?
302 $statement = "SELECT COUNT(*) AS thecount FROM {ec_mvmg_userstore_settings} WHERE uid = %d";
303 $sth = db_query( $statement, $user->uid );
304 $result = db_fetch_object( $sth );
305
306 if ( $result->thecount > 0 ) {
307 // update this record
308 $statement = "UPDATE ec_mvmg_userstore_settings
309 SET
310 paypal_enabled = " . $form_values['paypal_enabled'] . ",
311 cod_enabled = " . $form_values['cod_enabled'] . ",
312 receiver_email='" . $form_values['receiver_email'] . "',
313 currency='" . $form_values['currency'] . "',
314 ipn_debug='" . $form_values['ipn_debug'] . "'
315 WHERE uid = " . $user->uid;
316 //print $statement;exit;
317 if ( ! db_query( $statement ) ) {
318 drupal_set_message('Error with db_query:' . db_error() .'<HR>$statement','error');
319 };
320
321 drupal_set_message('The updates to your settings have been saved.');
322 }
323 else {
324 // insert a new record
325 $statement = "INSERT INTO {ec_mvmg_userstore_settings} (uid,paypal_enabled,cod_enabled,receiver_email,currency,ipn_debug) VALUES (".$user->uid.",".$form_values['paypal_enabled'].",".$form_values['cod_enabled'].",'" . $form_values['receiver_email'] . "','" . $form_values['currency'] . "','" . $form_values['ipn_debug'] . "')";
326 //print $statement;exit;
327 if ( ! db_query( $statement) ) {
328 drupal_set_message('Error with db_query:' . db_error() ,'error');
329 };
330 drupal_set_message('Your GoZabo store settings have been stored for the first time');
331 }
332 }
333
334 function gozabo_store_settings() {
335 global $user;
336 $g = array();
337
338 $statement = "SELECT * FROM ec_mvmg_userstore_settings WHERE uid = %d";
339 $sth = db_query( $statement, $user->uid );
340 if ( db_num_rows( $sth ) ) {
341 $g = db_fetch_array( $sth );
342 }
343 /* else {
344 drupal_set_message("This is your first time on this form. Please read the options and instructions carefully.");
345 } */
346
347 // set our default values
348 if ( !isset( $g['uid'] ) ) { $g['uid'] = $user->uid; }
349 if ( !isset( $g['paypal_enabled'] ) ) { $g['paypal_enabled'] = 0; }
350 if ( !isset( $g['cod_enabled'] ) ) { $g['cod_enabled'] = 0; }
351 if ( !isset( $g['receiver_email'] ) ) { $g['receiver_email'] = $user->mail; }
352 if ( !isset( $g['currency'] ) ) { $g['currency']= 'USD'; }
353 if ( !isset( $g['ipn_debug'] ) ) { $g['ipn_debug'] = 'Enabled'; }
354 //drupal_set_message( "<PRE>" . sprint_r($g) . "</pre>" );
355
356 $form['#redirect'] = FALSE;
357
358 $form['pretext'] = array(
359 '#prefix' => '<div id="gzpaypal_form_prefix_text">',
360 '#value' => '<P>Please select payment methods you will accept.</p>
361 <P><strong>IMPORTANT NOTE:</strong> If you are enabling paypal, you must first setup and configure a paypal account
362 with Instant Payment Notification. </p>
363 <P>How do I add the IPN link to my PayPal Account?: Go to your PayPal profile (at <a href="http://www.paypal.com/">paypal.com</a>)
364 under "selling preferences" and then click on the <i>"Instant Payment Notification"</i> link. There you should enter
365 an IPN URL of http://www.gozabo.com/gozabocheckout/ipn/' . $user->uid ,
366 '#suffix' => '</div>'
367 );
368
369 // declare a fieldset for paypal settings..collapse if paypal is disabled
370 $form['paypal'] = array(
371 '#type' => 'fieldset',
372 '#title' => 'Paypal Gateway Settings',
373 '#collapsible' => TRUE,
374 );
375 //if ( $g['paypal_enabled'] ) {
376 $form['paypal']['#collapsed'] = FALSE;
377 //}
378 //else {
379 //$form['paypal']['#collapsed'] = TRUE;
380 //}
381
382 $options = array('1' => t('Yes'), '0' => t('No'));
383 // are we using paypal at all?
384 $form['paypal']['paypal_enabled'] = array(
385 '#type' => 'radios',
386 '#title' => t('Accept Payments through Paypal?'),
387 '#default_value' => $g['paypal_enabled'],
388 '#options' => $options,
389 '#description' => t('If you have a standard paypal account and wish to accept payments using that method, select "Yes." Please <a href="http://www.paypal.com/">open your Paypal account</a> <i>before</i> enabling this payment method.'),
390 );
391
392 // who gets the emails upon receipt? Should be me but might be something/someone else.
393 $form['paypal']['receiver_email'] = array(
394 '#type' => 'textfield',
395 '#title' => t('Receiver Email'),
396 '#default_value' => $g['receiver_email'],
397 '#size' => 30,
398 '#maxlength' => 255,
399 '#description' => t('Primary email address of the payment recipent. This is also your main paypal email address.'),
400 );
401
402 // this url is provided by Paypal
403 /* THESE 4 fields are hard-coded for gozabo.com
404 $form['paypal']['processing_url'] = array(
405 '#type' => 'textfield',
406 '#title' => t('PayPal processing URL'),
407 '#description' => t('URL of the secure payment page customers are sent to for payment processing.'),
408 '#default_value' => $g['processing_url'],
409 '#size' => 30,
410 '#maxlength' => 255,
411 );
412
413 // where do we send them after payment? (back to their order history, thank you very much)
414 // make this hidden after testing...
415 $form['paypal']['post_payment_url'] = array(
416 '#type' => 'textfield',
417 '#title'=> t('Post Payment URL (user should NOT CHANGE THIS)'),
418 '#default_value' => 'gozabocheckout/cleartxn',
419 );
420
421 // what if they cancel mid-stream?
422 // hidden, sends them to their order history.
423 $form['paypal']['post_cancel_url'] = array(
424 '#type' => 'hidden',
425 '#value' => 'gozabocheckout/showtxns'
426 );
427
428 // IPN url for paypal requestback payments
429 // this TOO should be hidden and include the uid
430 $form['paypal']['ipn_url'] = array(
431 '#type' => 'textfield',
432 '#title' => t('IPN URL'),
433 '#default_value' => 'http://www.paypal.com/cgi-bin/webscr'
434 );
435 */
436
437 $currency_codes = array(
438 'USD' => 'USD - U.S. Dollars',
439 'EUR' => 'EUR - Euros',
440 'AUD' => 'AUD - Australian Dollars',
441 'CAD' => 'CAD - Canadian Dollars',
442 'GBP' => 'GBP - Pounds Sterling',
443 'JPY' => 'JPY - Yen',
444 'NZD' => 'NZD - New Zealand Dollar',
445 'CHF' => 'CHF - Swiss Franc',
446 'HKD' => 'HKD - Hong Kong Dollar',
447 'SGD' => 'SGD - Singapore Dollar',
448 'SEK' => 'SEK - Swedish Krona',
449 'DKK' => 'DDK - Danish Krone',
450 'PLN' => 'PLN - Polish Zloty',
451 'NOK' => 'NOK - Norwegian Krone',
452 'HUF' => 'HUF - Hungarian Forint',
453 'CZK' => 'CZK - Czech Koruna'
454 );
455
456 $form['paypal']['currency'] = array(
457 '#type' => 'select',
458 '#title' => t('Currency code'),
459 '#default_value' => $g['currency'],
460 '#options' => $currency_codes,
461 '#description' => t('The currecy code that PayPal should process the payment in.'),
462 );
463 $form['paypal']['ipn_debug'] = array(
464 '#type' => 'radios',
465 '#title' => t('Debug Instant Payment Notification (IPN)'),
466 '#default_value' => $g['ipn_debug'],
467 '#options' => array(t('Disabled'), t('Enabled')),
468 '#description' => t('If enabled, you\'ll receive an email whenever IPN is activated on your site.')
469 );
470 /* $form['paypal']['min_amount'] = array(
471 '#type' => 'textfield',
472 '#title' => t('Minimum purchase amount'),
473 '#default_value' => variable_get('gozabocheckout_min_amount', '5.00'),
474 '#size' => 10,
475 '#maxlength' => 10,
476 '#description' => t('What is the minimum amount an user must purchase for when checking out with Paypal?')
477 ); */
478
479
480 // cod requiers very few settings. :)
481 $form['cod_enabled'] = array(
482 '#type' => 'radios',
483 '#title' => t('Accept C.O.D. / User-Negotiated Payment?'),
484 '#default_value' => $g['cod_enabled'],
485 '#options' => $options,
486 '#description' => t('If you wish to be contacted by the buyer who can setup manual payment, please select "Yes." This is a simple way to get your store up and running as it requires no special settings.'),
487 );
488
489 $form['submit'] = array (
490 '#type' => 'submit',
491 '#value' => 'Save Settings'
492 );
493
494 //drupal_set_message("<PRE>".sprint_r($form)."</pre>");
495
496 return $form;
497 }
498
499 function gozabocheckout_perm() {
500 return array('Configure own payment settings','Admin payment settings','manage transactions from own store','admin transactions from any store');
501 }
502
503
504 function gozabocheckout_paymentapi(&$txn, $op, $arg = '') {
505 switch ($op) {
506 case 'display name':
507 return t('GoZaboCheckout');
508
509 case 'on checkout':
510 //print "<H1>ah ha</h1>";exit;
511 gozabocheckout_verify_checkout($txn);
512 break;
513
514 case 'payment page':
515 // now we have a full txn (cart is empty) and it's time to start hackin'
516 $owner_sorted_txn = _gozabo_txn_to_owners( $txn );
517
518 //STRATEGY:
519 //1) Let it store the txn, use our custom payment method to create new mini-transactions in ec_mvmg_* tables (copy the address from the main one)
520 _gozabo_txn_create( $owner_sorted_txn, $txn );
521 //2) Need the parent txn id as a state variable so that we know which txns to show the user who is purchasing right now
522 //3) Use the parent txn id as a key against our mini txns and show them all (with status and approved payment methods)
523 //4) Process individual mini txns, alter their status, when all are marked "cleared" (or whatever) set the parent to completed as well
524
525 //NOTE:If you want to debug better, comment out the code in cart.module->cart_empty()
526 // ...then your cart's never empty and you can keep on going to the payment page. :)
527
528 //print "<PRE><H1>ORIGINAL TXN:</h1>\n"; print_r($txn);print"\n<H1>OWNER OBJECT:</h1>\n\n\n";print_r($owner_sorted_txn);exit;
529
530 // this is from the original paypal module...basically it says "Hey, if they owe $, send them off to handle it...."
531 // because this sends the full txn over, we have all we need to complete steps 2-4 from the strategy above.
532
533 _gozabo_show_transaction_list();
534 break;
535 }
536 }
537
538 function _gozabo_show_transaction_list() {
539 global $user;
540
541 $output = '';
542 //$output .= "<PRE>" . sprint_r( $GLOBALS ) . "</PRE>";
543 // this function pulls all ec_mvmg transactions that exist, merges them with vendor info (and available payment gateways for those specific vendors)
544 // then it allows you to
545
546 //sometimes this function is called from a url (gozabocheckout/showtxns) and sometimes from a functioncall in the payment api
547 // behave slightly differently based on that.
548 $expand_these = array();
549 // fuggaduboutid...expand unfinished txns all the time lest we confuse the populace
550 //if ( arg(0) == 'cart' ) {
551 // in all other cases, expand none
552 // in this case expand those transactions that are unpaid (payment_status=1)
553 //you get a full list of payment status values from payment_build_status()
554 $expand_these = _get_mvmgtxnids('1',$user->uid);
555 //}
556
557 //inefficient....just did a full select against this table with similar criteria.
558 $statement ="SELECT * FROM ec_mvmg WHERE uid = $user->uid ORDER BY payment_status, vendor, created DESC" ;
559 //drupal_set_message("$statement");
560 $sth = db_query($statement ) or exit("ERROR WITH $statement");
561
562 $title = 'You have ' . db_num_rows( $sth ) . ' transactions in the system. ';
563
564 $output .= "<table class='mvmg_txn_table'>";
565 $output .= "<TR><TH></th><TH>Order #</tH><TH>Date</th><TH>Vendor</th><TH>Status</th></tr>";
566
567 $current_status='';
568
569 drupal_add_css( drupal_get_path('module','gozabocheckout') . '/gozabocheckout.css');
570 drupal_add_js( drupal_get_path('module','gozabocheckout') . '/gozabocheckout.js');
571
572 while ( $row = db_fetch_array( $sth ) ) {
573 $output .= "<TR class='gozabo_showhide_row'>";
574 $output .= "<TD><a href='#' class='showhide'>Show/Hide</a></td>\n";
575 $output .= '<TD>' . $row['mvmgtxnid'] . '</td>';
576 $output .= "<TD style='white-space: nowrap;'>" . format_date( $row['created'],'short' ) . "</td>\n";
577 $output .= "<TD>" . _gozabo_vendor_name( $row['vendor'] ) . "(" . $row['vendor'] . ")</td>\n";
578 $output .= "<TD>" . payment_get_status( $row['payment_status'] ) . "</td>\n";
579 // not showing grss because we haven't calc'ed it yet. :)
580 // $output .= "<TD>$" . $row['gross']. "</td>\n</tr>\n";
581 if ( isset( $expand_these[ $row['mvmgtxnid'] ] ) ) {
582 // expand this now...
583 $output .= "<TR class='details showing'><TD colspan=5>" . _gozabo_mvmg_details( $row['mvmgtxnid'], $row['payment_status'] ) . "</td></tr>\n";
584 }
585 else {
586 $output .= "<TR class='details'><TD colspan=5>" . _gozabo_mvmg_details( $row['mvmgtxnid'], $row['payment_status'] ) . "</td></tr>\n";
587 }
588 }
589
590 $output .= '</table>';
591
592
593 $the_box = theme_box($title,$output,'main');
594 print theme('page', $the_box );
595
596 exit;
597 }
598
599 function _gozabo_vendor_name( $uid ) {
600 $statement = "SELECT name FROM users WHERE uid=$uid";
601 $sth = db_query( $statement );
602 $row = db_fetch_array( $sth );
603 return $row['name'];
604 }
605
606 function _gozabo_sku_getter($nid) {
607 $statement = "SELECT sku FROM ec_product WHERE nid = $nid " ;
608 $prod = db_fetch_array( db_query($statement) );
609 //drupal_set_message("<PRE>$statement</pre>");
610 //drupal_set_message("<PRE>" . sprint_r($prod) . "</pre>");
611 return $prod['sku'];
612 }
613
614 function _gozabo_mvmg_detail_query( $mvmgtxnid ) {
615 $statement = "
616 SELECT
617 m.mvmgtxnid,
618 m.txnid AS m_txnid,
619 m.txnid AS txnid,
620 m.uid AS purchaser_uid,
621 m.vendor AS vendor_uid,
622 m.prod,
623 m.payment_status,
624 m.payment_date,
625 tp.nid,
626 tp.title,
627 tp.price,
628 tp.qty,
629 tp.data,
630 tp.txnid AS tp_txnid
631 ,node.uid
632 ,users.name
633 FROM ec_mvmg m,
634 ec_transaction_product tp,
635 node,
636 users
637 WHERE
638 m.mvmgtxnid = $mvmgtxnid
639 AND tp.txnid = m.txnid
640 AND node.nid = tp.nid
641 AND users.uid = node.uid
642 AND users.uid = m.vendor "; // //$returner .= '<PRE>' . $statement . '</PRE>';
643
644 $sth = db_query( $statement );
645
646 //watchdog('gozabocheckoug',"DETAILs: $mvmgtxnid<BR><PRE>$statement</pre>");
647 if ( ! db_num_rows( $sth ) ) {
648 watchdog('gozabocheckout',"ZERO ROW DETAIL REQUEST $mvmgtxnid<P>Statement returned zero rows. That means a vendor and a purchaser have an error showing up because of the following: \n<PRE>$statement</pre>");
649 }
650
651 return $sth;
652 }
653
654 function _gozabo_mvmg_details( $mvmgtxnid,$status=0,$showops=1 ) {
655 // so the mvmgtxnid we were passed is either our purchase or our sale.
656 // determine which
657 global $user;
658 $returner = '<BR>';
659 $sth = _gozabo_mvmg_detail_query( $mvmgtxnid );
660 if ( ! db_num_rows( $sth ) ) {
661 // this happens when the product is deleted ... transactions aren't
662 // removed upon product deletion, because transactions aren't removed,
663 // ec_mvmg doesn't get updated either.
664
665 // what were the products supposed to be?
666 $temp = db_fetch_array( db_query( "SELECT prod FROM ec_mvmg WHERE mvmgtxnid = $mvmgtxnid "));
667 if ( isset( $temp['prod'] ) ) {
668 drupal_set_message("Transaction ec_mvmg.$mvmgtxnid is corrupt (no products sold, looking for products: " . $temp['prod'] . ").",'error');
669 }
670 else {
671 drupal_set_message("Transaction ec_mvmg.$mvmgtxnid is corrupt (no transaction record found).",'error');
672 }
673
674 return '<strong>Broken Transaction.</strong> <P>Please contact customer service. this error usually appears because the product(s) making up this transaction have been deleted from the system</p><P>It is probably ok to remove this transaction from the system.</p>';
675
676 // debugging here...txn exists but no products?!
677 // MENTAL NOTE: CHANGING OWNER (NODE.UID) OF A PRODUCT BREAKS EC_MVMG
678 /*
679 $statement = "SELECT txnid FROM ec_mvmg WHERE mvmgtxnid = $mvmgtxnid";
680 $temp_sth = db_query( $statement );
681 $temp_row = db_fetch_array( $temp_sth );
682 drupal_set_message("Perhaps it's a role-based purchase?
683 Try again without ec_transaction_product<PRE>" .
684 sprint_r( store_transaction_load( $temp_row['txnid'] ) ) . "</pre>");
685 */
686 }
687 $counter=0;
688 $subtotal = 'err';
689 $first_row = array();
690 while ($row = db_fetch_array( $sth ) ) {
691 if ( $counter == 0 ) {
692 // first pass....
693 $subtotal = _gozabo_store_transaction_calc_gross( $row );
694 $first_row = $row;
695 }
696 $this_gross = $row['price'] * $row['qty'];
697 $returner .= "<div class='gozabo_txn_product_row'>" . $row['title'] . ' ($' . $row['price'] . ' x ' . $row['qty'] . ' = $' . number_format($this_gross,2) . ') - SKU: ' . _gozabo_sku_getter($row['nid']) . '</div>';
698 $counter++;
699 }
700 $returner .= "<div class='gozabo_txn_total_text'>TOTAL: $" . number_format($subtotal,2) . "</div>";
701
702 // need this stuff later....
703 $row = $first_row;
704
705
706 // so who are we? purchaser or vendor?
707 if ( $user->uid == $row['vendor_uid'] ) {
708 //drupal_set_message('You are the vendor!');
709 // vendors want to see the status (which shows in the parent table) and have options to change the status, message their buyers
710 $returner .= "<BR>Operations: [ <a href='" .url("gozabocheckout/edittxn/$mvmgtxnid") . "'>View/Ship/Edit</a> | <a href='" .url('user/' . $row['purchaser_uid'] .'/contact') . "'>Contact Purchaser</a> ]\n";
711
712 }
713 elseif ($user->uid == $row['purchaser_uid'] ) {
714 //drupal_set_message('You are the purchaser!');
715 // they need to pay...show choices, act accordingly
716 if ( $status == 1 ) {
717 // get the seller's settings
718 $store_settings = _gozabo_userstore_settings_retrieve( $mvmgtxnid );
719 $returner .= '<div class="gozabo_payment_buttons"><h4>Pay Now (select method): </h4>';
720
721 // figure out available payment methods
722 $payment_methods = array();
723 if ( isset( $store_settings['paypal_enabled'] ) && $store_settings['paypal_enabled'] == 1 ) {
724 $payment_methods[] = "<a onclick='return confirm(\"You will now leave GoZabo.com to process your payment at Paypal.com\")' href='" . url("gozabocheckout/paypal/$mvmgtxnid") . "'><img src='/sites/all/modules/custom/ec_mvmg/img/paypalbutton.gif' alt='Paypal Payment'></a>";
725 }
726 if ( isset( $store_settings['cod_enabled'] ) && $store_settings['cod_enabled'] == 1 ) {
727 //$payment_methods[] = "<a id='$mvmgtxnid' class='cod_form_show' href='#'>C.O.D.</a>";
728 $payment_methods[] = "<a href='" . url("gozabocheckout/cod/$mvmgtxnid") . "'><img src='/sites/all/modules/custom/ec_mvmg/img/CODbutton.gif' alt='COD Payment'></a>";
729 }
730
731 $returner .= join('&nbsp;', $payment_methods);
732 $returner .= "</div>";
733
734 }
735 // they've already paid, show status
736 else {
737 $returner .= "<div class='gozabo_status_text'>Status = " . payment_get_status( $row['payment_status'] ) . "</div>";
738 }
739 if ( $showops ) {
740 //$returner .= "<BR>Operations: [ ";
741 $returner .= "<div class='gozabo_buyer_ops_list'>";
742 //if ( $user->name == 'testbuyer' ) {
743 //$returner .= "<a href='" . url('gozabocheckout/ecroles/' . $row['mvmgtxnid'] ) . "'>Secret Button</a> | ";
744 //}
745 $returner .= "<a href='" . url('user/' . $row['vendor_uid'] . '/contact') . "'>Contact Seller</a>";
746
747 // only allow cancelation of pending txns
748 if ( payment_get_status_id('pending') == $row['payment_status'] ) {
749 $returner .= " | <a href='" . url('gozabocheckout/buyercanceltxn/' . $mvmgtxnid ) . "'>Cancel Transaction</a>";
750 }
751
752 $returner .= "</div>";
753 }
754 }
755 else {
756 drupal_set_message('There is a problem. You are user ' . $user->uid . ' but that is not the vendor (' . $row['vendor_uid'] . ') or purchaser (' . $row['purchaser_uid'] . ') of this transaction! Please contact customer support.<PRE>' . sprint_r($row) . "</pre>",'error');
757 return '';
758 }
759
760 $returner .= "<BR><BR>";
761 return $returner;
762
763 }
764
765 function _gozabo_userstore_settings_retrieve( $mvmgtxnid ) {
766 $statement = "SELECT * FROM ec_mvmg_userstore_settings LEFT JOIN ec_mvmg ON ec_mvmg.vendor = ec_mvmg_userstore_settings.uid WHERE ec_mvmg.mvmgtxnid = $mvmgtxnid";
767 $sth = db_query( $statement );
768 $result = db_fetch_array( $sth );
769 //drupal_set_message( "$statement<BR><PRE>" . sprint_r( $result ) . "</pre>");
770 return $result;
771 }
772
773 function _get_mvmgtxnids($status,$uid) {
774 $sth = db_query( "SELECT mvmgtxnid FROM ec_mvmg WHERE uid = $uid AND payment_status = $status ORDER BY payment_status, created DESC" );
775 $return_list = array();
776 while ( $row = db_fetch_array( $sth ) ) {
777 $return_list[ $row['mvmgtxnid'] ] = 1;
778 }
779 return $return_list;
780 }
781
782 /**
783 * Implementation of hook_ec_transactionapi().
784 */
785 function gozabocheckout_ec_transactionapi(&$txn, $op, $a3 = NULL, $a4 = NULL) {
786 if ($txn->payment_method != 'gozabocheckout') return NULL;
787 switch ($op) {
788 case 'load':
789 $txn->payment = db_fetch_object(db_query("SELECT * FROM {ec_mvmg} WHERE txnid = %d", $txn->txnid));
790 break;
791 case 'insert':
792 case 'update':
793 gozabocheckout_save($txn);
794 break;
795 case 'delete':
796 gozabocheckout_delete($txn);
797 break;
798 }
799 }
800
801 function gozabocheckout_verify_checkout($txn) {
802 $estimate = store_transaction_calc_gross($txn);
803 if (variable_get('gozabocheckout_min_amount', '5.00') > $estimate) {
804 form_set_error('gross', t('Your purchase total must be at least %min-purchase-amount for Paypal purchases.', array('%min-purchase-amount' => payment_format(variable_get('gozabocheckout_min_amount', '5.00')))));
805 }
806 }
807
808 function gozabocheckout_delete($txn) {
809 db_query('DELETE FROM {ec_gozabocheckout} WHERE txnid = %d', $txn->txnid);
810 }
811
812 function gozabocheckout_save($txn) {
813 //print"<h1>in checkoutapi</h1>TXNID: ".$txn->txnid."<BR>PPID: ".$txn->ppid."<PRE>";print_r($op);print "<HR>";
814 /* print_r($txn); */
815
816 if ($txn->txnid && $txn->ppid) {
817
818 if (db_result(db_query("SELECT COUNT(txnid) FROM {ec_gozabocheckout} WHERE txnid = '%s'", $txn->txnid))) {
819 db_query("UPDATE {ec_gozabocheckout} SET ppid = '%s', fee = '%s' WHERE txnid = '%d'", $txn->ppid, $txn->fee, $txn->txnid);
820 }
821 else {
822 db_query("INSERT INTO {ec_gozabocheckout} (txnid, ppid, fee) VALUES (%d, '%s', '%s')", $txn->txnid, $txn->ppid, $txn->fee);
823 }
824 }
825
826 //print "<PRE><H1>HERE WE ARE...having saved not a damn thing....</h1>";
827
828 // let's see if we can create the multiple invoices here....kkkkkkkkkkkkkkk
829 #print"<HR>";print_r( $txn->items );print "<HR>";
830
831 // loop the list of products and re-organize them by vendor.
832 // $owners = array();
833 // foreach ( array_keys( $txn->items ) as $nid ) {
834 // $items[$nid] = node_load( $nid );
835 // $owners[ $items[$nid]->name ][] = $items[$nid];
836 // }
837 //
838 // print"<HR><h1>OWNER DATA</h1>\n";
839 // print_r( $owners );
840 //exit;
841
842 //$owners = _gozabo_txn_to_owners($txn);
843
844 // HERE
845
846 }
847
848 function gozabocheckout_ipn() {
849 watchdog('IPN', "POST VAR:<PRE> " . sprint_r($_POST) . "</pre>" );
850 $debug = "PayPal IPN Results\n";
851 $debug .= "==================\n";
852 $debug .= "Paypal says....\n<PRE>" . sprint_r($_POST) . "</pre>";
853
854 // what this basically does:
855 /*
856 * 1) Receive a post from PAYPAL
857 * 2) immediately post it back to PAYPAL(?)
858 * 3) Paypal returns a status
859 * 4) we act accordingly
860 */
861
862 /* step 1...paypal sends us a txnid (ec_mvmg.mvmgtxnid)
863 * get the settings for that userstore so that we know who's who here.
864 */
865
866 $has_txn_key = false;
867 $mvmgtxnid = 0;
868 $i = array();
869 /* Read the post from PayPal system and add 'cmd' */
870 $req = 'cmd=_notify-validate';
871
872 $debug=preg_replace("/\n/",'<BR>',$debug);
873 //watchdog('IPN', $debug);;
874
875 ksort($_POST); //easier for debugging
876 // getting ahold of different items
877 // $i = item array
878 foreach ($_POST as $key => $value) {
879
880 $debug .= "$key = $value\n";
881 $debug = preg_replace("/\n/",'<BR>',$debug);
882 //watchdog('IPN keyval', $debug);;
883
884 if (strstr($key, 'item_number')) {
885
886 if (strstr($value, 'txnid_')) {
887 $mvmgtxnid = substr($value, strlen('txnid_'));
888 $has_txn_key = true;
889 $debug .= t("A MVMG Transaction ID exists and is #%key\n", array('%key' => $mvmgtxnid));
890 }
891
892 $i[substr($key, strlen('item_number'))] = $mvmgtxnid;
893 }
894 elseif (strstr($key, 'quantity')) {
895 $quantity[substr($key, strlen('quantity'))] = $value;
896 }
897 elseif (strstr($key, 'item_name')) {
898 $name[substr($key, strlen('item_name'))] = $value;
899 }
900
901 $value = urlencode(stripslashes($value));
902 $req .= "&$key=$value";
903 }
904 $debug=preg_replace("/\n/",'<BR>',$debug);
905 //watchdog('IPN Post Parse', $debug);;
906 watchdog('IPN', "SORTED KEYS:<BR>".join("<BR>",$i) );;
907
908 if ($mvmgtxnid) {
909 $message = "IPN hit for $mvmgtxnid";
910 watchdog('IPN', $message);
911 }
912 else {
913 watchdog('IPN', t('ERROR. EXIT!<BR>IPN hit, no transaction ID given! All sorts of problems will ensue.'));
914 exit;
915 }
916
917 // ok, right here we have at mvmgtxnid, get the info for this particular transaction from the database (need receiver email, specifically)
918 $statement = "SELECT g.receiver_email FROM ec_mvmg LEFT JOIN ec_mvmg_userstore_settings AS g ON g.uid = ec_mvmg.vendor WHERE ec_mvmg.mvmgtxnid = $mvmgtxnid";
919 watchdog("IPN","RECEIVER EMAIL SELECTION SQL<BR>$statement");
920 $row = db_fetch_array( db_query( $statement ));
921 $real_receiver_email = $row['receiver_email'];
922
923 $has_shippable_item = false;
924 foreach($i as $key => $value) {
925 $pp_item = new StdClass();
926 $pp_item->nid = $value;
927 $pp_item->qty = $quantity[$key];
928 $pp_item->title = $name[$key];
929 $pp_item->price = null;
930
931 if (product_is_shippable($pp_item->nid)) {
932 $has_shippable_item = true;
933 }
934
935 $item[] = $pp_item;
936 }
937
938 /* Post back to PayPal system to validate */
939 $ipnrb = parse_url('https://www.paypal.com/cgi-bin/webscr');
940 if ($ipnrb['scheme']=='http') {
941 $port= 80;
942 $host=$ipnrb['host'];
943 }
944 else {
945 $port= 443;
946 $host="ssl://{$ipnrb['host']}";
947 }
948 //$port = 443;
949 //$host = "ssl://www.paypal.com/cgi-bin/webscr";
950
951 $header = "POST {$ipnrb['path']} HTTP/1.0\r\n";
952 $header .= "Host: {$ipnrb['host']}:$port\r\n";
953 $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
954 $header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
955 $fp = fsockopen($host, $port, $errno, $errstr, 30);
956
957 /* Assign posted variables to local variables */
958 $payment_status = $_POST['payment_status'];
959 $fee = $_POST['payment_fee'];
960 $payment_amount = $_POST['mc_gross'];
961 $ppid = $_POST['txn_id'];
962 $paypal_receiver_email = $_POST['receiver_email'];
963 watchdog('IPN',"Paypal Acct Email = $paypal_receiver_email");
964 watchdog('IPN',"Receiver email = $real_receiver_email");
965 if ( $paypal_receiver_email == $real_receiver_email ) {
966 watchdog ('IPN','EMAILS are EQUAL.');
967 }
968 else {
969 watchdog ('IPN','EMAILS NOT EQUAL. IPN WILL FAIL.');
970 }
971
972 if (!$fp) {
973 // HTTP ERROR
974 $debug .= t("An HTTP error occurred\n");
975 watchdog('IPN','An HTTP error roccured trying to post to Paypal');
976 }
977 elseif ($ppid && $has_txn_key) { // We can't do much without a txn_id so the else below dies
978 watchdog('IPN','doing fputs');
979 fputs ($fp, $header . $req);
980 while (!feof($fp)) {
981 $res = fgets ($fp, 1024);
982 watchdog('IPN',"res = $res<BR>paypal email = $paypal_receiver_email<BR>real receiver email = $real_receiver_email");
983 watchdog('IPN',"0 = good...strcmp=" . strcmp( $res,'VERIFIED'));
984 if (strcmp ($res, 'VERIFIED') == 0 && $paypal_receiver_email == $real_receiver_email ) {
985
986 $debug .= t("PayPal has verified the transaction\n");
987 watchdog('IPN', t("PayPal has verified the transaction"));
988
989 $data['gross'] = $payment_amount;
990 $data['fee'] = $fee;
991 $data['payment_method'] = 'gozabocheckout';
992 $data['payment_status'] = payment_get_status_id($payment_status);
993 $data['ppid'] = $ppid;
994
995 if ($has_txn_key) {
996 $data['txnid'] = $mvmgtxnid;
997 }
998 else {
999 $data['billing_firstname'] = $_POST['address_first_name'];
1000 $data['billing_lastname'] = $_POST['address_last_name'];
1001 $data['billing_street1'] = $_POST['address_street'];
1002 $data['billing_city'] = $_POST['address_city'];
1003 $data['billing_state'] = $_POST['address_state'];
1004 $data['billing_zip'] = $_POST['address_zip'];
1005 //$data['billing_country'] = store_get_country_id($_POST['address_country']);
1006 $data['billing_country'] = 'us';
1007 $data['items'] = $item;
1008 $data['uid'] = db_result(db_query("SELECT uid FROM {users} WHERE mail = '%s'", $_POST['payer_email']));
1009 }
1010 ksort($data);
1011 $debug .= "\nData being sent to store_transaction_save:\n===================================\n";
1012 foreach ($data as $key => $value) {
1013 $debug .= "$key = $value\n";
1014 }
1015 $debug .= "\n";
1016
1017 // nothing is ever new...we're shoving ppid (paypal's txnid) into the ec_mvmg table
1018 // however we're also (below) going to always send an invoice email to the customer
1019 //$is_new = (db_result(db_query('SELECT COUNT(txnid) FROM {ec_gozabocheckout} WHERE ppid = %d', $ppid))) ? false : true;
1020 $is_new = 0;
1021
1022 switch (strtoupper($payment_status)) {
1023 /* if referring to an initial purchase, this means the payment has
1024 been completed and the funds are successfully in your account
1025 balance. If referring to a reversal (i.e. txn_type= reversal ),
1026 then it means the reversal has been completed and funds have been
1027 removed from your account and returned to the customer */
1028 case 'COMPLETED':
1029 watchdog('IPN', t("PayPal status completed"));
1030 $data['payment_status'] = payment_get_status_id('completed');
1031 watchdog('IPN','Now, update status in ec_mvmg...');
1032 // If there are no shippable items, assume the transaction workflow is complete.
1033 // gozabo don't do shippin
1034 //if (!$has_shippable_item) {
1035 //$data['workflow'] = 6;
1036 //}
1037
1038 // they were saving to the main ec_transaction table....
1039 // that serves no purpose here as we're avoiding the use of that table.
1040 // for that reason, we're doing to update our own table with those items from $data that matter
1041 //$txnid = store_transaction_save($data);
1042
1043 // update and email
1044 _gozabo_transaction_status_update( $mvmgtxnid, $data['payment_status'] );
1045 watchdog('IPN','Now, email a notification.');
1046 _gozabo_transaction_emailer( 'confirmed', $mvmgtxnid, $data['payment_status'] );
1047 watchdog('IPN','Emailed.');
1048
1049 // internal function to manage things like inventory through hook_productapi()
1050 // we call this same thing when a cod completes too
1051 _gozabo_completion_callback( $mvmgtxnid );
1052 watchdog("IPN","PRODUCT API FINISHED");
1053
1054 // hook back to ec_roles
1055 _gozabo_roles_processor( $mvmgtxnid );
1056 watchdog("IPN","ROLES PROCESSOR FINISHED");
1057
1058
1059 break;
1060
1061 /* The payment is pending; the pending_reason variable will give you
1062 more information. Note: You will receive another Instant Payment
1063 Notification when the payment becomes "Completed", "Failed", or "Denied" */
1064 case 'PENDING':
1065 watchdog('IPN', t("PayPal status pending"));
1066 // we already set stuff to pending.... email the user that it's not completed yet so that they know.
1067 $data['payment_status'] = payment_get_status_id('pending');
1068 _gozabo_transaction_status_update( $mvmgtxnid, $data['payment_status'] );
1069 //$txnid = store_transaction_save($data);
1070 _gozabo_transaction_emailer( 'pending', $mvmgtxnid, $data['payment_status'] );
1071 break;
1072
1073 /* The payment has failed. This will only happen if the payment was
1074 made from your customer's bank account */
1075 case 'FAILED':
1076 watchdog('IPN', t("PayPal status failed"));
1077 $data['payment_status'] = payment_get_status_id('failed');
1078 _gozabo_transaction_status_update( $mvmgtxnid, $data['payment_status'] );
1079 _gozabo_transaction_emailer( 'failed', $mvmgtxnid, $data['payment_status'] );
1080 break;
1081
1082 /* You, the merchant, denied the payment. This will only happen if the
1083 payment was previously pending due to one of the pending reasons below */
1084 case 'DENIED':
1085 watchdog('IPN', t("PayPal status denied"));
1086 $data['payment_status'] = payment_get_status_id('denied');
1087 //$txnid = store_transaction_save($data);
1088 _gozabo_transaction_status_update( $mvmgtxnid, $data['payment_status'] );
1089 _gozabo_transaction_emailer( 'denied', $mvmgtxnid, $data['payment_status'] );
1090 break;
1091
1092 /* You, the merchant, refunded the payment. */
1093 case 'REFUNDED':
1094 watchdog('IPN', t("PayPal status refunded"));
1095 $data['payment_status'] = payment_get_status_id('refunded');
1096 _gozabo_transaction_status_update( $mvmgtxnid, $data['payment_status'] );
1097 _gozabo_transaction_emailer( 'refunded', $mvmgtxnid, $data['payment_status'] );
1098 //$txnid = store_transaction_save($data);
1099 break;
1100
1101 /* This means a reversal has been canceled (e.g. you, the merchant,
1102 won a dispute with the customer and the funds for the transaction
1103 that was reversed have been returned to you) */
1104 case 'CANCELED':
1105 watchdog('IPN', t("PayPal status canceled"));
1106 $data['payment_status'] = payment_get_status_id('canceled');
1107 _gozabo_transaction_status_update( $mvmgtxnid, $data['payment_status'] );
1108 _gozabo_transaction_emailer( 'cancelled', $mvmgtxnid, $data['payment_status'] );
1109 //$txnid = store_transaction_save($data);
1110 break;
1111
1112 default:
1113 /* Unkmown payment status */
1114 _gozabo_transaction_emailer( 'unknown', $mvmgtxnid, $data['payment_status'] );
1115 watchdog('IPN', t("PayPal status UNKNOWN"));
1116 }
1117 $debug .= t("Transaction has been processed.\n");
1118 watchdog('IPN', t("PayPal processing complete"));
1119
1120 }
1121 else if (strcmp ($res, 'INVALID') == 0) {
1122 /* log for manual investigation */
1123 $debug .= t("The transaction has returned an invalid result from PayPal.\n");
1124 watchdog('IPN', t("PayPal reports INVALID"));
1125 }
1126 else {
1127 watchdog('IPN',"PAYPAL reports neither VERIFIED or INVALID...");
1128 }
1129 }
1130 }
1131 else {
1132 $debug .= t("Because there's no txnid, we didn't know what to do!\n");
1133 watchdog('IPN', t("Missing txnid caused exit"));
1134 }
1135 fclose ($fp);
1136
1137 watchdog('IPN', t("Debugging output (also emailed to suydam@gmail.com):<BR>".$debug));
1138 // debug by default for now
1139 //if (variable_get('gozabocheckout_debug', 0)) {
1140 /*
1141 $filename = 'pp.txt';
1142 $handle = fopen($filename, 'a');
1143 fwrite($handle, $debug);
1144 close($handle);
1145 */
1146
1147 $from = 'suydam@gmail.com';
1148 $to = $from;
1149 $subject = t('GOZABO IPN debug debug results for'). ' '. variable_get('site_name', 'drupal');
1150 $body = preg_replace("/<BR>/","\n",$debug);
1151 //$headers = "Reply-to: $from\nX-Mailer: PHP\nReturn-path: $from\nErrors-to: $from";
1152 drupal_mail('ec_gozabocheckout_debug', $to, $subject, $body, $from);
1153 //}
1154 }
1155
1156 function _gozabo_txn_to_owners( $txn ) {
1157 $owners = array();
1158 foreach ( array_keys( $txn->items ) as $nid ) {
1159 $items[$nid] = </