public function email($addressee, $address, $subject, array $templates = array()) { global $is_IIS; shopp_debug("ShoppPurchase::email(): {$addressee},{$address},{$subject}," . _object_r($templates)); // Build the e-mail message data $email['from'] = Shopp::email_from(shopp_setting('merchant_email'), shopp_setting('business_name')); if ($is_IIS) { $email['to'] = Shopp::email_to($address); } else { $email['to'] = Shopp::email_to($address, $addressee); } $email['subject'] = $subject; $email['receipt'] = $this->receipt(); $email['url'] = get_bloginfo('url'); $email['sitename'] = get_bloginfo('name'); $email['orderid'] = $this->id; $email = apply_filters('shopp_email_receipt_data', $email); $email = apply_filters('shopp_purchase_email_message', $email); $this->message = array_merge($this->message, $email); // Load and process the template file $defaults = array('email.php', 'order.php', 'order.html'); $emails = array_merge((array) $templates, $defaults); $template = Shopp::locate_template($emails); if (!file_exists($template)) { shopp_add_error(Shopp::__('A purchase notification could not be sent because the template for it does not exist.'), SHOPP_ADMIN_ERR); return false; } // Send the email if (Shopp::email($template, $this->message)) { shopp_debug('A purchase notification was sent to: ' . $this->message['to']); return true; } shopp_debug('A purchase notification FAILED to be sent to: ' . $this->message['to']); return false; }
/** * Verify the authenticity of a PDT message sent by PayPal * * @author Jonathan Davis, John Dillick * @since 1.0 * * @return boolean True if valid, false otherwise **/ protected function pdtvalid() { $ids = array($this->id(), 'PPS'); // 'PPS' is a backwards compatible ID for PDT requests if (!in_array($_REQUEST['rmtpay'], $ids)) { return false; } // not PDT message shopp_debug('Processing PDT request: ' . json_encode($_REQUEST)); if (!Shopp::str_true($this->settings['pdtverify']) || !isset($_REQUEST['tx'])) { ShoppOrder()->success(); return true; // if PDT verify is off, skip this process } $_ = array(); $_['cmd'] = '_notify-synch'; $_['at'] = $this->settings['pdttoken']; $_['tx'] = $_REQUEST['tx']; $message = $this->encode($_); // Build the request $response = $this->send($message); // Send it $response = $this->pdtreply($response); // Parse the response into a ShoppPayPalStandardMessage-compatible structure shopp_debug('PayPal PDT _notify-synch reply: ' . json_encode($response)); // Shift the first element off to get the verification status and have a clean data array for ShoppPayPalStandardMessage if ('SUCCESS' != array_shift($response)) { shopp_debug('The transaction was not verified by PayPal.'); // We run the success() method here to reset the shopping session and // redirect the shopper to the "thanks" page with an "order in progress" message // so the cart will be ready for a new order. Otherwise, the customer could resubmit the // prior order and PayPal will give them "that transaction has already been completed" message. ShoppOrder()->success(); return false; } $this->Message = new ShoppPayPalStandardMessage($response); shopp_debug('PayPal PDT response protocol: ' . _object_r($this->Message)); // Everything looks good, return true and let the order PDT order processing handle it from here return true; }
function updates () { global $Ecart; // Cancel processing if this is not a PayPal Website Payments Standard/Express Checkout IPN if (isset($_POST['txn_type']) && $_POST['txn_type'] != "cart") return false; $target = isset($_POST['parent_txn_id'])?$_POST['parent_txn_id']:$_POST['txn_id']; $Purchase = new Purchase($target,'txnid'); if ($Purchase->txn != $target || empty($Purchase->id)) return; // No Purchase found to update if ($Purchase->gateway != $this->module) return; // Not a PPE order, don't touch it // Validate the order notification if ($this->verifyipn() != "VERIFIED") { new EcartError(sprintf(__('An unverifiable order update notification was received from PayPal for transaction: %s. Possible fraudulent notification! The order will not be updated. IPN message: %s','Ecart'),$target,_object_r($_POST)),'paypal_txn_verification',ECART_TRXN_ERR); return false; } if (!$txnstatus) $txnstatus = $this->status[$_POST['payment_status']]; $Purchase->txnstatus = $txnstatus; $Purchase->save(); $Ecart->Purchase = &$Purchase; $Ecart->Order->purchase = $Purchase->id; do_action('ecart_order_notifications'); if (ECART_DEBUG) new EcartError('PayPal IPN update processed for transaction: '.$target,false,ECART_DEBUG_ERR); die('PayPal IPN update processed.'); }
function updates () { global $Ecart; // Cancel processing if this is not a PayPal Website Payments Standard/Express Checkout IPN if (isset($_POST['txn_type']) && $_POST['txn_type'] != "cart") return false; $target = false; if (isset($_POST['txn_id']) && !isset($_POST['parent_txn_id'])) $target = $_POST['txn_id']; elseif (!empty($_POST['parent_txn_id'])) $target = $_POST['parent_txn_id']; // No transaction target: invalid IPN, silently ignore the message if (!$target) return; // Validate the order notification if ($this->verifyipn() != "VERIFIED") { new EcartError(sprintf(__('An unverifiable order update notification was received from PayPal for transaction: %s. Possible fraudulent notification! The order will not be updated. IPN message: %s','Ecart'),$target,_object_r($_POST)),'paypal_txn_verification',ECART_TRXN_ERR); return false; } $Purchase = new Purchase($target,'txnid'); // Purchase record exists, update it if ($Purchase->txnid == $target && !empty($Purchase->id)) { if ($Purchase->gateway != $this->name) return; // Not a PPS order, don't touch it $txnstatus = isset($this->status[$_POST['payment_status']])? $this->status[$_POST['payment_status']]:$_POST['payment_status']; $Purchase->txnstatus = $txnstatus; $Purchase->save(); $Ecart->Purchase = &$Purchase; $Ecart->Order->purchase = $Purchase->id; do_action('ecart_order_notifications'); die('PayPal IPN update processed.'); } if (!isset($_POST['custom'])) { new EcartError(sprintf(__('No reference to the pending order was available in the PayPal IPN message. Purchase creation failed for transaction %s.'),$target),'paypalstandard_process_neworder',ECART_TRXN_ERR); die('PayPal IPN failed.'); } $Ecart->Order->unhook(); $Ecart->resession($_POST['custom']); $Ecart->Order = Ecart_buyObject::__new('Order',$Ecart->Order); $this->actions(); $Shopping = &$Ecart->Shopping; // Couldn't load the session data if ($Shopping->session != $_POST['custom']) return new EcartError("Session could not be loaded: {$_POST['custom']}",false,ECART_DEBUG_ERR); else new EcartError("PayPal successfully loaded session: {$_POST['custom']}",false,ECART_DEBUG_ERR); $this->ipnupdates(); do_action('ecart_process_order'); // New order die('PayPal IPN processed.'); }
function process() { global $Shopp; if (SHOPP_DEBUG) { new ShoppError('PayPal IPN notification received.', false, SHOPP_DEBUG_ERR); } // If no invoice number is available, we if (empty($_POST['invoice'])) { if (SHOPP_DEBUG) { new ShoppError('No invoice number was provided by PayPal: ' . _object_r($_POST), 'paypalstd_debug', SHOPP_DEBUG_ERR); } return new ShoppError(__('An unverifiable order with no invoice number was received from PayPal. Possible fraudulent order attempt!', 'Shopp'), 'paypal_txn_verification', SHOPP_TRXN_ERR); } session_unset(); session_destroy(); // Load the cart for the correct order $Shopp->Cart->session = $_POST['invoice']; $Shopp->Cart->load($Shopp->Cart->session); if (SHOPP_DEBUG) { new ShoppError('PayPal successfully loaded session: ' . $Shopp->Cart->session, false, SHOPP_DEBUG_ERR); } if (isset($Shopp->Cart->data)) { $Order = $Shopp->Cart->data->Order; $Order->Totals = $Shopp->Cart->data->Totals; $Order->Items = $Shopp->Cart->contents; $Order->Cart = $Shopp->Cart->session; } // Handle IPN updates to existing purchases if ($this->updates()) { exit; } // Validate the order data $validation = true; if (!$Shopp->Cart->validorder()) { new ShoppError(__('There is not enough customer information to process the order.', 'Shopp'), 'invalid_order', SHOPP_TRXN_ERR); $validation = false; } if (number_format($_POST['mc_gross'], 2) != number_format($Order->Totals->total, 2)) { $validation = false; if (SHOPP_DEBUG) { new ShoppError('Order validation failed. Received totals mismatch. Received ' . number_format($_POST['mc_gross'], 2) . ', but originally sent' . number_format($Order->Totals->total, 2), 'paypalstd_debug', SHOPP_DEBUG_ERR); } } if (!empty($Purchase->id)) { $validation = false; if (SHOPP_DEBUG) { new ShoppError('Order validation failed. Received duplicate transaction id: ' . $_POST['txn_id'], 'paypalstd_debug', SHOPP_DEBUG_ERR); } } if ($validation) { $this->order(); } else { new ShoppError(__('An order was received from PayPal that could not be validated against existing pre-order data. Possible order spoof attempt!', 'Shopp'), 'paypal_trxn_validation', SHOPP_TRXN_ERR); } exit; }