/** * Register delivery method with main shop module. */ protected function registerDeliveryMethod() { if (class_exists('shop')) { $shop = shop::getInstance(); $shop->registerDeliveryMethod($this->name, $this); } }
/** * Constructor */ protected function __construct() { global $section; parent::__construct(__FILE__); // register backend if (class_exists('backend')) { $backend = backend::getInstance(); Events::connect('backend', 'user-create', 'handleUserCreate', $this); Events::connect('backend', 'user-delete', 'handleUserDelete', $this); } // connect to shop events if (class_exists('shop')) { $shop = shop::getInstance(); Events::connect('shop', 'transaction-completed', 'handleTransactionCompleted', $this); Events::connect('shop', 'recurring-payment', 'handleRecurringPayment', $this); Events::connect('shop', 'recurring-payment-suspended', 'handleRecurringPaymentSuspended', $this); } }
/** * Make new payment form with specified items and return * boolean stating the success of initial payment process. * * @param array $data * @param array $items * @param string $return_url * @param string $cancel_url * @return string */ public function new_payment($data, $items, $return_url, $cancel_url) { global $language; $description = ''; $tmp_items = array_slice($items, 0, 5); $tmp_names = array(); foreach ($tmp_items as $item) { $tmp_names[] = $item['name'][$language]; } $description = implode(', ', $tmp_names); // add dots if there are more than 5 items if (count($items) > 5) { $description .= ', ...'; } // get proper currency code $shop_module = shop::getInstance(); $currency = $shop_module->getDefaultCurrency(); if (array_key_exists($currency, $this->currency_aliases)) { $currency = $this->currency_aliases[$currency]; } $currency_code = -1; if (array_key_exists($currency, $this->currency)) { $currency_code = $this->currency[$currency]; } // prepare basic parameters $params = array('currency' => $currency_code, 'TranzilaToken' => $data['uid'], 'sum' => $data['total'] + $data['shipping'] + $data['handling'], 'cred_type' => 1, 'pdesc' => $description); // prepare items for checkout foreach ($items as $item) { $item = array_shift($items); } // create HTML form $result = ''; foreach ($params as $key => $value) { $result .= "<input type=\"hidden\" name=\"{$key}\" value=\"{$value}\">"; } return $result; }
/** * Complete checkout and charge money. */ public function completeCheckout() { global $language; $shop = shop::getInstance(); $return_url = fix_chars($_REQUEST['return_url']); $recurring = isset($_REQUEST['type']) && $_REQUEST['type'] == 'recurring'; $transaction_uid = $_SESSION['transaction']['uid']; // get billing information $billing = array(); $fields = array('billing_full_name', 'billing_card_type', 'billing_credit_card', 'billing_expire_month', 'billing_expire_year', 'billing_cvv'); foreach ($fields as $field) { if (isset($_REQUEST[$field])) { $billing[$field] = fix_chars($_REQUEST[$field]); } } // create recurring profile if ($recurring) { $request_id = 0; $plan_name = $_SESSION['recurring_plan']; $manager = PayPal_PlansManager::getInstance(); $plan = $manager->getSingleItem($manager->getFieldNames(), array('text_id' => $plan_name)); $current_plan = $shop->getRecurringPlan(); // cancel existing recurring payment if exists if (!is_null($current_plan)) { $plans = $this->get_recurring_plans(); $current_group = null; // get plan data if (isset($plans[$current_plan->plan_name])) { $current_group = $plans[$current_plan->plan_name]['group']; } // cancel current plan if (!is_null($current_group) && $current_group == $plan->group_name) { $shop->cancelTransaction($current_plan->transaction); } } // generate params for description $plan_params = array('price' => $plan->price, 'period' => $plan->interval_count, 'unit' => $plan->interval, 'setup' => $plan->setup_price, 'trial_period' => $plan->trial_count, 'trial_unit' => $plan->trial); // charge one time setup fee // TODO: Charge one time setup fee. // create recurring payments profile $recurring_fields = $fields; // set buyer information $name = explode(' ', $billing['billing_full_name']); $recurring_fields['CREDITCARDTYPE'] = $this->card_type[$billing['billing_card_type']]; $recurring_fields['ACCT'] = $billing['billing_credit_card']; $recurring_fields['EXPDATE'] = $billing['billing_expire_month'] . $billing['billing_expire_year']; $recurring_fields['FIRSTNAME'] = $name[0]; $recurring_fields['LASTNAME'] = $name[1]; // set starting date of the profile $start_timestamp = strtotime($plan->start_time); if ($start_timestamp < time()) { $start_timestamp = time(); } $recurring_fields['PROFILESTARTDATE'] = strftime('%Y-%m-%dT%T%z', $start_timestamp); // set description $recurring_fields['DESC'] = $shop->formatRecurring($plan_params); // set currency $recurring_fields['AMT'] = $plan->price; $recurring_fields['CURRENCYCODE'] = $shop->getDefaultCurrency(); // billing period $recurring_fields['BILLINGPERIOD'] = $this->units[$plan->interval]; $recurring_fields['BILLINGFREQUENCY'] = $plan->interval_count; // trial period if ($plan->trial_count > 0) { $recurring_fields['TRIALBILLINGPERIOD'] = $this->units[$plan->trial]; $recurring_fields['TRIALBILLINGFREQUENCY'] = $plan->trial_count; $recurring_fields['TRIALTOTALBILLINGCYCLES'] = 1; } // make api call $response = PayPal_Helper::callAPI(PayPal_Helper::METHOD_CreateRecurringPaymentsProfile, $recurring_fields); if ($response['ACK'] == 'Success' || $response['ACK'] == 'SuccessWithWarning') { // update transaction token $shop->setTransactionToken($transaction_uid, fix_chars($response['PROFILEID'])); // update transaction status if ($response['PROFILESTATUS'] == 'ActiveProfile') { $shop->setTransactionStatus($transaction_uid, TransactionStatus::COMPLETED); } } else { // report error $error_code = urldecode($response['L_ERRORCODE0']); $error_long = urldecode($response['L_LONGMESSAGE0']); trigger_error("PayPal_Express: ({$error_code}) - {$error_long}", E_USER_ERROR); } // redirect user header('Location: ' . $return_url, true, 302); } }
/** * Get available delivery types for selected items. Each type needs * to return estimated delivery time, cost and name of service. * * Example of items array: * $items = array( * array( * 'package' => 0, // number identifying package * 'properties' => array(), * 'package_type' => 0, * 'width' => 0.2, * 'height' => 0.5, * 'length' => 1, * 'weight' => 0, * 'units' => 1, * 'count' => 1 * ) * ); * * Example of shipper array: * $shipper = array( * 'street' => array(), * 'city' => '', * 'zip_code' => '', * 'state' => '', * 'country' => '' * ); * * Example of recipient array: * $recipient = array( * 'street' => array(), * 'city' => '', * 'zip_code' => '', * 'state' => '', * 'country' => '' * ); * * Example of result array: * $result = array( * 'normal' => array('Normal', 19.95, 'USD', 1364040000, 1365040000), * 'express' => array('Express', 33.23, 'USD', 1363040000, 1364040000), * 'express_no_estimate' => array('Express', 8.00, 'USD', false, false) * ); * * @param array $items * @param array $shipper * @param array $recipient * @param string $transaction_id * @param string $preferred_currency * @return array */ public function getDeliveryTypes($items, $shipper, $recipient, $transaction_id, $preferred_currency) { $shop = shop::getInstance(); $manager = IntervalManager::getInstance(); $time_manager = IntervalTimeManager::getInstance(); $days = array(); $result = array(); // load all delivery intervals $intervals = $manager->getItems($manager->getFieldNames(), array()); if (count($intervals) == 0) { return $result; } foreach ($intervals as $interval) { // get hours $times = $time_manager->getItems($time_manager->getFieldNames(), array('interval' => $interval->id)); // make sure there are hours defined in this interval if (count($times) == 0) { continue; } // collect delivery hours for ($i = 0; $i < 7; $i++) { if ($interval->days[$i] == '1') { if (!isset($days[$i])) { $days[$i] = array(); } foreach ($times as $time) { $days[$i][] = $time; } } } } // calculate shipping dates for specified number of days $today = mktime(0, 0, 0); $date_format = $this->parent->getLanguageConstant('format_date_short'); $time_format = $this->parent->getLanguageConstant('format_time_short'); $currency = $shop->getDefaultCurrency(); for ($i = 0; $i < $this->days_to_show; $i++) { $current_date = $today + $i * (24 * 60 * 60); $day_of_week = (int) date('N', $current_date) - 1; // skip day if there are no deliveries if (!isset($days[$day_of_week])) { continue; } // add intervals foreach ($days[$day_of_week] as $time) { $start = strtotime($time->start, $current_date); $end = strtotime($time->end, $current_date); // skip past intervals if (time() > $start) { continue; } // add new delivery date $key = date($date_format . ' ' . $time_format, $start); $result[$key] = array($this->parent->getLanguageConstant('label_' . ($day_of_week + 1)), $time->amount, $currency, $start, $end); } } return $result; }
/** * Get available delivery types for selected items. Each type needs * to return estimated delivery time, cost and name of service. * * @param array $items * @param array $shipper * @param array $recipient * @param string $transaction_id * @return array */ public function getDeliveryTypes($items, $shipper, $recipient, $transaction_id, $preferred_currency) { $shop = shop::getInstance(); $debug = $shop->isDebug(); $result = array(); $request = array(); $client = new SoapClient($this->wsdl[FedEx_DeliveryMethod::RATE_SERVICE], array('trace' => $debug)); if (empty($shipper)) { throw new Exception('Missing shipper information!'); } if (empty($recipient)) { throw new Exception('Missing recipient information!'); } // populate request header $this->_populateCredentials($request); $this->_populateClientDetails($request); $this->_populateTransactionDetails($request, $transaction_id); $this->_populateVersionInformation($request, FedEx_DeliveryMethod::RATE_SERVICE); // add remaining request information $request['ReturnTransitAndCommit'] = true; // request tranzit time and commit data $request['RequestedShipment'] = array('RateRequestTypes' => 'PREFERRED'); $request['RequestedShipment']['DropoffType'] = 'REGULAR_PICKUP'; $request['RequestedShipment']['ShipTimestamp'] = date('c'); $request['RequestedShipment']['PackagingType'] = 'YOUR_PACKAGING'; $request['RequestedShipment']['PreferredCurrency'] = $preferred_currency; $request['RequestedShipment']['Shipper'] = array('Contact' => array(), 'Address' => array('StreetLines' => $shipper['street'], 'City' => $shipper['city'], 'PostalCode' => $shipper['zip_code'], 'StateOrProvinceCode' => $shipper['state'], 'CountryCode' => $shipper['country'])); $request['RequestedShipment']['Recipient'] = array('Contact' => array(), 'Address' => array('StreetLines' => $recipient['street'], 'City' => $recipient['city'], 'PostalCode' => $recipient['zip_code'], 'StateOrProvinceCode' => strlen($recipient['state']) >= 2 ? '' : $recipient['state'], 'CountryCode' => $recipient['country'])); $request['RequestedShipment']['ShippingChargesPayment'] = array('PaymentType' => 'SENDER', 'Payor' => array('ResponsibleParty' => array('AccountNumber' => $this->parent->settings['fedex_account'], 'CountryCode' => $shipper['country']))); // get package id's and count items for each package $packages = array(); foreach ($items as $item) { $package_id = $item['package']; if (array_key_exists($package_id, $packages)) { $packages[$package_id]++; } else { $packages[$package_id] = 1; } } // append all the items to list $fedex_items = array(); foreach ($items as $item) { $new_item = array('Weight' => array('Value' => $item['weight'], 'Units' => 'KG'), 'Dimensions' => array('Width' => $item['width'], 'Height' => $item['height'], 'Length' => $item['length'], 'Units' => 'CM')); $new_item['SequenceNumber'] = $item['package']; $new_item['GroupPackageCount'] = $packages[$item['package']]; $fedex_items[] = $new_item; } $request['RequestedShipment']['PackageCount'] = count($packages); $request['RequestedShipment']['RequestedPackageLineItems'] = $fedex_items; // get response from server $response = $client->getRates($request); if (count($response->RateReplyDetails) > 0) { foreach ($response->RateReplyDetails as $type) { // extract data from response $id = $type->ServiceType; $name = $this->parent->getLanguageConstant($id); $timestamp = strtotime($type->DeliveryTimestamp); $amount = $type->RatedShipmentDetails[0]->ShipmentRateDetail->TotalNetCharge->Amount; $currency = $type->RatedShipmentDetails[0]->ShipmentRateDetail->TotalNetCharge->Currency; // add new delivery type to result $result[] = array(!empty($name) ? $name : $id, $amount, $currency, null, $timestamp ? $timestamp : null); } } return $result; }
/** * Show price for this delivery method. * * @param array $tag_params * @param array $children */ private function show_price($tag_params, $children) { $shop = shop::getInstance(); $template = $this->loadTemplate($tag_params, 'price.xml'); // prepare parameters $params = array('price' => 10, 'currency' => $shop->getDefaultCurrency()); // parse template $template->restoreXML(); $template->setLocalParams($params); $template->parse(); }
/** * Charge specified amount with specified token and transaction. */ public function chargeToken() { $transaction_uid = fix_chars($_REQUEST['transaction_uid']); $stripe_token = fix_chars($_REQUEST['stripe_token']); $manager = ShopTransactionsManager::getInstance(); $currency_manager = ShopCurrenciesManager::getInstance(); $transaction = null; // make sure we are working on same transaction for current user if (isset($_SESSION['transaction']) && $_SESSION['transaction']['uid'] == $transaction_uid) { $transaction = $manager->getSingleItem($manager->getFieldNames(), array('uid' => $transaction_uid)); } if (is_object($transaction)) { $currency = $currency_manager->getSingleItem(array('currency'), array('id' => $transaction->currency)); try { // create charge Stripe::setApiKey($this->getPrivateKey()); $charge = Stripe_Charge::create(array('amount' => $transaction->total * 100, 'currency' => $currency->currency, 'card' => $stripe_token, 'description' => null)); } catch (Stripe_CardError $error) { } // update transaction status if (is_object($charge) && $charge->paid) { $shop = shop::getInstance(); $shop->setTransactionToken($transaction_uid, $charge->id); $shop->setTransactionStatus($transaction_uid, TransactionStatus::COMPLETED); } } }
/** * Handle recurring payment IPN. * * @param object $transaction * @param string $type * @param float $amount * @return boolean */ private function handleRecurringIPN($transaction, $type, $amount) { $result = false; $shop = shop::getInstance(); $plan_manager = ShopTransactionPlansManager::getInstance(); // get plan associated with this transaction $plan = $plan_manager->getSingleItem($plan_manager->getFieldNames(), array('transaction' => $transaction->id)); if (!is_object($plan)) { trigger_error('PayPal: Unable to handle IPN, unable to get plan for transaction: ' . $transaction->id, E_USER_WARNING); return $result; } // notification type to status relation $status = array('recurring_payment' => RecurringPayment::ACTIVE, 'recurring_payment_expired' => RecurringPayment::EXPIRED, 'recurring_payment_failed' => RecurringPayment::FAILED, 'recurring_payment_profile_created' => RecurringPayment::PENDING, 'recurring_payment_profile_cancel' => RecurringPayment::CANCELED, 'recurring_payment_skipped' => RecurringPayment::SKIPPED, 'recurring_payment_suspended' => RecurringPayment::SUSPENDED, 'recurring_payment_suspended_due_to_max_failed_payment' => RecurringPayment::SUSPENDED); // add new recurring payment $result = $shop->addRecurringPayment($plan->id, $amount, $status[$type]); return $result; }
/** * Complete checkout and charge money. */ public function completeCheckout() { global $language; // prepare data for new recurring profile $shop = shop::getInstance(); $token = escape_chars($_REQUEST['token']); $payer_id = escape_chars($_REQUEST['payer_id']); $return_url = fix_chars($_REQUEST['return_url']); $recurring = isset($_REQUEST['type']) && $_REQUEST['type'] == 'recurring'; $transaction_uid = $_SESSION['transaction']['uid']; // get buyer information $fields = array('TOKEN' => $token); $response = PayPal_Helper::callAPI(PayPal_Helper::METHOD_GetExpressCheckoutDetails, $fields); // update transaction status and buyer if ($response['ACK'] == 'Success' || $response['ACK'] == 'SuccessWithWarning') { $buyer = array('first_name' => $response['FIRSTNAME'], 'last_name' => $response['LASTNAME'], 'email' => $response['EMAIL'], 'uid' => $response['PAYERID']); $shop->updateBuyerInformation($transaction_uid, $buyer); } else { // report error $error_code = urldecode($response['L_ERRORCODE0']); $error_long = urldecode($response['L_LONGMESSAGE0']); trigger_error("PayPal_Express: ({$error_code}) - {$error_long}", E_USER_ERROR); } // create recurring profile if ($recurring) { $request_id = 0; $plan_name = $_SESSION['recurring_plan']; $manager = PayPal_PlansManager::getInstance(); $plan = $manager->getSingleItem($manager->getFieldNames(), array('text_id' => $plan_name)); $current_plan = $shop->getRecurringPlan(); // cancel existing recurring payment if exists if (!is_null($current_plan)) { $plans = $this->get_recurring_plans(); $current_group = null; // get plan data if (isset($plans[$current_plan->plan_name])) { $current_group = $plans[$current_plan->plan_name]['group']; } // cancel current plan if (!is_null($current_group) && $current_group == $plan->group_name) { $shop->cancelTransaction($current_plan->transaction); } } // generate params for description $plan_params = array('price' => $plan->price, 'period' => $plan->interval_count, 'unit' => $plan->interval, 'setup' => $plan->setup_price, 'trial_period' => $plan->trial_count, 'trial_unit' => $plan->trial); // charge one time setup fee if (is_object($plan) && $plan->setup_price > 0) { $setup_fields = $fields; $setup_fields["PAYMENTREQUEST_{$request_id}_AMT"] = $plan->setup_price; $setup_fields["PAYMENTREQUEST_{$request_id}_CURRENCYCODE"] = $shop->getDefaultCurrency(); $setup_fields["PAYMENTREQUEST_{$request_id}_DESC"] = $this->parent->getLanguageConstant('api_setup_fee'); $setup_fields["PAYMENTREQUEST_{$request_id}_INVNUM"] = $_SESSION['transaction']['uid']; $setup_fields["PAYMENTREQUEST_{$request_id}_PAYMENTACTION"] = 'Sale'; $response = PayPal_Helper::callAPI(PayPal_Helper::METHOD_DoExpressCheckoutPayment, $setup_fields); } // create recurring payments profile $recurring_fields = $fields; // set starting date of the profile $start_timestamp = strtotime($plan->start_time); if ($start_timestamp < time()) { $start_timestamp = time(); } $recurring_fields['PROFILESTARTDATE'] = strftime('%Y-%m-%dT%T%z', $start_timestamp); $recurring_fields['PAYERID'] = $payer_id; // set description $recurring_fields['DESC'] = $shop->formatRecurring($plan_params); // set currency $recurring_fields['AMT'] = $plan->price; $recurring_fields['CURRENCYCODE'] = $shop->getDefaultCurrency(); // billing period $recurring_fields['BILLINGPERIOD'] = $this->units[$plan->interval]; $recurring_fields['BILLINGFREQUENCY'] = $plan->interval_count; // trial period if ($plan->trial_count > 0) { $recurring_fields['TRIALBILLINGPERIOD'] = $this->units[$plan->trial]; $recurring_fields['TRIALBILLINGFREQUENCY'] = $plan->trial_count; $recurring_fields['TRIALTOTALBILLINGCYCLES'] = 1; } // make api call $response = PayPal_Helper::callAPI(PayPal_Helper::METHOD_CreateRecurringPaymentsProfile, $recurring_fields); if ($response['ACK'] == 'Success' || $response['ACK'] == 'SuccessWithWarning') { // update transaction token $shop->setTransactionToken($transaction_uid, fix_chars($response['PROFILEID'])); // update transaction status if ($response['PROFILESTATUS'] == 'ActiveProfile') { $shop->setTransactionStatus($transaction_uid, TransactionStatus::COMPLETED); } } else { // report error $error_code = urldecode($response['L_ERRORCODE0']); $error_long = urldecode($response['L_LONGMESSAGE0']); trigger_error("PayPal_Express: ({$error_code}) - {$error_long}", E_USER_ERROR); } // redirect user header('Location: ' . $return_url, true, 302); } }