From 486fbb3e2009d20949619bfbdbcdec6ac6f3355b Mon Sep 17 00:00:00 2001 From: Matthias Reuter Date: Thu, 26 Jun 2014 17:42:11 +0200 Subject: [PATCH] 1.6.9 * MarketPress: Beta released * Common: Allows overriding language files by placing them into /wp-content/languages/paymill/ * PayButton: Order Form optimized * PayButton: Feature for price/currency format * Shopp: Paymill as Payment Gateway wasn't recognized due to last changes in shopplugin - fixed * Shopp: Errors wasn't shown on checkout process - fixed * Shopp: Compatibility with new checkout button achieved --- CHANGES.md | 10 + README.md | 8 +- .../shopp/wp-content/shopp-addons/paymill.php | 5 + lib/config.inc.php | 7 +- lib/css/paymill.css | 6 + lib/integration/marketpress.inc.php | 612 +++++------------- lib/integration/shopplugin.inc.php | 20 +- lib/integration/woocommerce.inc.php | 2 +- lib/js/paymill.js | 27 +- lib/scripts.inc.php | 1 + lib/setup.inc.php | 1 + lib/tpl/checkout_form.php | 4 +- lib/tpl/pay_button.php | 58 +- lib/translate/paymill-de_DE.po | 469 +++++++++----- lib/translate/paymill-en_US.po | 469 +++++++++----- paymill.php | 14 +- readme.txt | 28 +- 17 files changed, 914 insertions(+), 827 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index c5edb9d..c015f3f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,16 @@ Changelog ========= +1.6.9 +----- +* MarketPress: Beta released +* Common: Allows overriding language files by placing them into /wp-content/languages/paymill/ +* PayButton: Order Form optimized +* PayButton: Feature for price/currency format +* Shopp: Paymill as Payment Gateway wasn't recognized due to last changes in shopplugin - fixed +* Shopp: Errors wasn't shown on checkout process - fixed +* Shopp: Compatibility with new checkout button achieved + 1.6.8 ----- * WooCommerce: Issue with order completion fixed diff --git a/README.md b/README.md index 4d842de..fdf1ece 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ PAYMILL for WordPress * Tags: paymill, creditcard, elv, payment, woocommerce, paybutton, ecommerce, debitcard, subscriptions * Requires at least: 3.9 * Tested up to: 3.9 -* Stable tag: 1.6.8 +* Stable tag: 1.6.9 * License: [GPLv3 or later](http://www.gnu.org/licenses/gpl-3.0.html) With PAYMILL you are able to provide credit card based payments for your customers. @@ -21,15 +21,15 @@ Requires: * WordPress 3.9.x or higher Supported Shops including subscriptions support: -* WooCommerce (2.1.x) +* WooCommerce (2.1.x) + WooCommerce Subscriptions (1.5.x) * Magic Members (1.8.x) * Pay Button (independent, light-weight payment form) Supported Shops without subscriptions support (yet): -* ShopPlugin (1.3.x) +* ShopPlugin (1.3.4) work in progress: -* MarketPress (2.9.x) +* MarketPress (2.9.x) - 95% completed Service Description diff --git a/copy_this/shopp/wp-content/shopp-addons/paymill.php b/copy_this/shopp/wp-content/shopp-addons/paymill.php index 8c06fbf..3a9cc37 100644 --- a/copy_this/shopp/wp-content/shopp-addons/paymill.php +++ b/copy_this/shopp/wp-content/shopp-addons/paymill.php @@ -10,6 +10,11 @@ * @since 1.2 * @subpackage PaymillShopp **/ + +/* +class PaymillShopp extends GatewayFramework implements GatewayModule { + +*/ if(defined('PAYMILL_DIR') && file_exists(PAYMILL_DIR.'lib/integration/shopplugin.inc.php')){ require_once(PAYMILL_DIR.'lib/integration/shopplugin.inc.php'); diff --git a/lib/config.inc.php b/lib/config.inc.php index 8362389..a4c9cc0 100644 --- a/lib/config.inc.php +++ b/lib/config.inc.php @@ -24,7 +24,8 @@ public function __construct() { $this->paymill_pay_button_settings = array_merge( array( 'number_decimal' => '.', 'number_thousands' => ',', - 'currency' => 'EUR' + 'currency' => 'EUR', + 'currency_format' => '%n%s' ), $this->paymill_pay_button_settings ); if(isset($this->paymill_general_settings['api_key_private']) && isset($this->paymill_general_settings['api_key_public']) && $this->paymill_general_settings['api_key_private'] != '' && $this->paymill_general_settings['api_key_public'] != ''){ @@ -132,6 +133,7 @@ public function paymill_register_pay_button_settings(){ 'number_decimal' => __('Number Format: Decimal Point', 'paymill'), 'number_thousands' => __('Number Format: Thousands Seperator', 'paymill'), 'currency' => __('Currency', 'paymill'), + 'currency_format' => __('Currency Format', 'paymill'), 'email_outgoing' => __('Outgoing Email', 'paymill'), 'email_incoming' => __('Incoming Email', 'paymill'), 'thankyou_url' => __('Thank You URL', 'paymill'), @@ -173,7 +175,6 @@ public function paymill_register_pay_button_settings(){ // shipping add_settings_section( 'section_pay_button_shipping', false, array( &$this, 'section_pay_button_shipping_desc' ), $this->setting_keys['paymill_pay_button_settings'] ); - //var_dump($this->paymill_pay_button_settings['flat_shipping']); if(isset($this->paymill_pay_button_settings['flat_shipping'])){ if(isset($this->paymill_pay_button_settings['flat_shipping'][count($this->paymill_pay_button_settings['flat_shipping'])]['flat_shipping_country']) && strlen($this->paymill_pay_button_settings['flat_shipping'][count($this->paymill_pay_button_settings['flat_shipping'])]['flat_shipping_country']) > 0){ $shipping = count($this->paymill_pay_button_settings['flat_shipping'])+5; @@ -359,6 +360,7 @@ class="regular-text code" '.($value ? 'checked="checked"' : '').' /> 'surname', 'street', 'number', + 'state', 'zip', 'city', /*'email',*/ @@ -431,6 +433,7 @@ private function paymill_do_settings_fields($page, $section){ $descriptions['no_default_css'] = __('Advanced users want to fully customize the payment button. Disabling default CSS from Pay Button will make that much easier.', 'paymill'); $descriptions['currency'] = __('Currency, ISO 4217 e.g. "EUR" or "GBP"', 'paymill'); + $descriptions['currency_format'] = __('Currency Format - use the following variables: %n = number, %s = symbol.', 'paymill'); $descriptions['api_key_private'] = __('Insert your Paymill PRIVATE API key.', 'paymill'); $descriptions['api_key_public'] = __('Insert your Paymill PUBLIC API key.', 'paymill'); diff --git a/lib/css/paymill.css b/lib/css/paymill.css index 1cf7e22..c3f97ed 100644 --- a/lib/css/paymill.css +++ b/lib/css/paymill.css @@ -73,6 +73,12 @@ display:block; clear:both; } +#paymill_payment_form .paymill_card_cvc .cvc_desc{ + line-height:30px; + display:inline-block; + height:30px; + margin-left:5px; +} #paymill_payment_form #paymill_card_number{ background-image:url('../img/payment_logos.png'); background-repeat:no-repeat; diff --git a/lib/integration/marketpress.inc.php b/lib/integration/marketpress.inc.php index b6aadb7..7fd2553 100644 --- a/lib/integration/marketpress.inc.php +++ b/lib/integration/marketpress.inc.php @@ -4,6 +4,15 @@ Author: Matthias Reuter */ +if(!function_exists('paymill_marketpress_errorHandling')){ + function paymill_marketpress_errorHandling($errors){ + global $mp; + foreach($errors as $error){ + $mp->cart_checkout_error('
'.$error.'. '.sprintf(__('Please go back and try again.', 'paymill'), mp_checkout_step_url('checkout')).'
'); + } + } +} + class MP_Gateway_Paymill_for_WordPress extends MP_Gateway_API { //private gateway slug. Lowercase alpha (a-z) and dashes (-) only please! @@ -70,6 +79,80 @@ private function paymill_getCurrency(){ return $mp->get_setting('currency'); } + private function getCurrentClient(){ + require_once(PAYMILL_DIR.'lib/integration/client.inc.php'); + + if(isset($_SESSION['name'])){ + $desc = $_SESSION['name']; + }else{ + $desc = ''; + } + + // create or get client + $this->clientClass = new paymill_client($_SESSION['email'],$desc); + return $this->clientClass->getCurrentClient(); + } + + private function processSubscriptions(){ + return true; + } + private function processProducts(){ + global $wpdb; + if($this->total > 0){ + // make transaction + $GLOBALS['paymill_loader']->request_transaction->setAmount(round($this->total,2)); // e.g. "4200" for 42.00 EUR + $GLOBALS['paymill_loader']->request_transaction->setCurrency($this->currency); + if($this->paymentClass->getPreauthID() != false){ + $GLOBALS['paymill_loader']->request_transaction->setPreauthorization($this->paymentClass->getPreauthID()); + }else{ + $GLOBALS['paymill_loader']->request_transaction->setPayment($this->paymentClass->getPaymentID()); + } + $GLOBALS['paymill_loader']->request_transaction->setClient($this->client->getId()); + $GLOBALS['paymill_loader']->request_transaction->setDescription($this->order_desc); + $GLOBALS['paymill_loader']->request->setSource(serialize($GLOBALS['paymill_source'])); + + $GLOBALS['paymill_loader']->request->create($GLOBALS['paymill_loader']->request_transaction); + + $response = $GLOBALS['paymill_loader']->request->getLastResponse(); + + if(isset($response['body']['data']['response_code']) && $response['body']['data']['response_code'] != '20000'){ + $GLOBALS['paymill_loader']->paymill_errors->setError(__($response['body']['data']['response_code'], 'paymill')); + if($GLOBALS['paymill_loader']->paymill_errors->status()){ + $GLOBALS['paymill_loader']->paymill_errors->getErrors(); + } + return false; + } + + // save data to transaction table + $wpdb->query($wpdb->prepare(' + INSERT INTO '.$wpdb->prefix.'paymill_transactions (paymill_transaction_id, paymill_payment_id, paymill_client_id, marketpress_order_id, paymill_transaction_time, paymill_transaction_data) + VALUES (%s,%s,%s,%d,%d,%s)', + array( + $response['body']['data']['id'], + $response['body']['data']['payment']['id'], + $response['body']['data']['client']['id'], + $this->order_id, + time(), + serialize($_POST) + ))); + + do_action('paymill_marketpress_products_paid', array( + 'total' => $this->total, + 'currency' => $this->currency, + 'client' => $response['body']['data']['client']['id'] + )); + + return true; + }else{ // total is zero, so just return true + + // remove preauth when not used + // @todo: Once preauths are usable for delayed payment in this plugin, we need to make a condition for this + $this->paymentClass->removePreauth(); + + return true; + } + } + /****** Below are the public methods you may overwrite via a plugin ******/ /** @@ -77,15 +160,19 @@ private function paymill_getCurrency(){ */ function on_creation() { global $mp; - $settings = get_option('mp_settings'); + $settings = get_option('mp_settings'); //set names here to be able to translate - $this->admin_name = __('Paymill for WordPress', 'paymill'); - $this->public_name = __('Paymill', 'paymill'); + $this->admin_name = __('Paymill for WordPress', 'paymill'); + $this->public_name = __('Paymill', 'paymill'); //button img - $this->method_img_url = plugins_url('',__FILE__ ).'/../img/logo_small.png'; - $this->method_button_img_url = plugins_url('',__FILE__ ).'/../img/logo_small.png'; + $this->method_img_url = plugins_url('',__FILE__ ).'/../img/logo_small.png'; + $this->method_button_img_url = plugins_url('',__FILE__ ).'/../img/logo_small.png'; + + load_paymill(); // this function-call can and should be used whenever working with Paymill API + $GLOBALS['paymill_loader']->paymill_errors->setFunction('paymill_marketpress_errorHandling'); + $GLOBALS['paymill_source']['marketpress_version'] = $mp->version; } /** @@ -129,98 +216,7 @@ function payment_form($global_cart, $shipping_info) { * @param array $order Contains the list of order ids */ function process_payment_authorize($orders) { - if (is_array($orders)) { - foreach ($orders as $order) { - $transaction_id = $order['transaction_id']; - $amount = $order['amount']; - - $authorization = $this->DoAuthorization($transaction_id, $amount); - - switch ($result["PAYMENTSTATUS"]) { - case 'Canceled-Reversal': - $status = __('A reversal has been canceled; for example, when you win a dispute and the funds for the reversal have been returned to you.', 'mp'); - $authorized = true; - break; - case 'Expired': - $status = __('The authorization period for this payment has been reached.', 'mp'); - $authorized = false; - break; - case 'Voided': - $status = __('An authorization for this transaction has been voided.', 'mp'); - $authorized = false; - break; - case 'Failed': - $status = __('The payment has failed. This happens only if the payment was made from your customer\'s bank account.', 'mp'); - $authorized = false; - break; - case 'Partially-Refunded': - $status = __('The payment has been partially refunded.', 'mp'); - $authorized = true; - break; - case 'In-Progress': - $status = __('The transaction has not terminated, e.g. an authorization may be awaiting completion.', 'mp'); - $authorized = false; - break; - case 'Completed': - $status = __('The payment has been completed, and the funds have been added successfully to your account balance.', 'mp'); - $authorized = true; - break; - case 'Processed': - $status = __('A payment has been accepted.', 'mp'); - $authorized = true; - break; - case 'Reversed': - $status = __('A payment was reversed due to a chargeback or other type of reversal. The funds have been removed from your account balance and returned to the buyer', 'mp'); - $reverse_reasons = array( - 'none' => '', - 'chargeback' => __('A reversal has occurred on this transaction due to a chargeback by your customer.', 'mp'), - 'guarantee' => __('A reversal has occurred on this transaction due to your customer triggering a money-back guarantee.', 'mp'), - 'buyer-complaint' => __('A reversal has occurred on this transaction due to a complaint about the transaction from your customer.', 'mp'), - 'refund' => __('A reversal has occurred on this transaction because you have given the customer a refund.', 'mp'), - 'other' => __('A reversal has occurred on this transaction due to an unknown reason.', 'mp') - ); - $status .= ': ' . $reverse_reasons[$result["REASONCODE"]]; - $authorized = false; - break; - case 'Refunded': - $status = __('You refunded the payment.', 'mp'); - $authorized = false; - break; - case 'Denied': - $status = __('You denied the payment when it was marked as pending.', 'mp'); - $authorized = false; - break; - case 'Pending': - $pending_str = array( - 'address' => __('The payment is pending because your customer did not include a confirmed shipping address and your Payment Receiving Preferences is set such that you want to manually accept or deny each of these payments. To change your preference, go to the Preferences section of your Profile.', 'mp'), - 'authorization' => __('The payment is pending because it has been authorized but not settled. You must capture the funds first.', 'mp'), - 'echeck' => __('The payment is pending because it was made by an eCheck that has not yet cleared.', 'mp'), - 'intl' => __('The payment is pending because you hold a non-U.S. account and do not have a withdrawal mechanism. You must manually accept or deny this payment from your Account Overview.', 'mp'), - 'multi-currency' => __('You do not have a balance in the currency sent, and you do not have your Payment Receiving Preferences set to automatically convert and accept this payment. You must manually accept or deny this payment.', 'mp'), - 'order' => __('The payment is pending because it is part of an order that has been authorized but not settled.', 'mp'), - 'paymentreview' => __('The payment is pending while it is being reviewed by PayPal for risk.', 'mp'), - 'unilateral' => __('The payment is pending because it was made to an email address that is not yet registered or confirmed.', 'mp'), - 'upgrade' => __('The payment is pending because it was made via credit card and you must upgrade your account to Business or Premier status in order to receive the funds. It can also mean that you have reached the monthly limit for transactions on your account.', 'mp'), - 'verify' => __('The payment is pending because you are not yet verified. You must verify your account before you can accept this payment.', 'mp'), - 'other' => __('The payment is pending for an unknown reason. For more information, contact PayPal customer service.', 'mp'), - '*' => '' - ); - $status = __('The payment is pending', 'mp'); - if (isset($pending_str[$result["PENDINGREASON"]])) - $status .= ': ' . $pending_str[$result["PENDINGREASON"]]; - $authorized = false; - break; - default: - // case: various error cases - $authorized = false; - } - if ($authorized) { - update_post_meta($order['order_id'], 'mp_deal', 'authorized'); - update_post_meta($order['order_id'], 'mp_deal_authorization_id', $authorization['TRANSACTIONID']); - } - } - } } /** @@ -230,16 +226,7 @@ function process_payment_authorize($orders) { * @param array $authorizations Contains the list of authorization ids */ function process_payment_capture($authorizations) { - if (is_array($authorizations)) { - foreach ($authorizations as $authorization) { - $transaction_id = $authorization['transaction_id']; - $amount = $authorization['amount']; - - $capture = $this->DoCapture($transaction_id, $amount); - - update_post_meta($authorization['deal_id'], 'mp_deal', 'captured'); - } - } + } /** @@ -253,34 +240,8 @@ function process_payment_capture($authorizations) { * @param array $shipping_info. Contains shipping info and email in case you need it */ function process_payment_form($global_cart, $shipping_info) { - global $mp; - - //create order id for paypal invoice - $order_id = $mp->generate_order_id(); - /* - foreach ($global_cart as $bid => $cart) { - foreach ($cart as $product_id => $data) { - if ('deal' == get_post_type($product_id)) { - $this->payment_action = 'Order'; - } - } - } - */ - //set it up with PayPal - $result = $this->SetExpressCheckout($global_cart, $shipping_info, $order_id); - - //check response - if($result["ACK"] == "Success" || $result["ACK"] == "SuccessWithWarning") { - $token = urldecode($result["TOKEN"]); - $this->RedirectToPayPal($token); - } else { //whoops, error - for ($i = 0; $i <= 5; $i++) { //print the first 5 errors - if (isset($result["L_ERRORCODE$i"])) { - $error .= "
  • {$result["L_ERRORCODE$i"]} - {$result["L_SHORTMESSAGE$i"]} - {$result["L_LONGMESSAGE$i"]}
  • "; - } - } - $error = '
    '; - $mp->cart_checkout_error( __('There was a problem connecting to PayPal to setup your purchase. Please try again.', 'mp') . $error ); + if (isset($_POST['paymillToken'])){ + $_SESSION['paymillToken'] = $_POST['paymillToken']; } } @@ -292,51 +253,6 @@ function process_payment_form($global_cart, $shipping_info) { * @param array $shipping_info. Contains shipping info and email in case you need it */ function confirm_payment_form($global_cart, $shipping_info) { - global $mp; - - $content = ''; - - if (isset($_GET['token']) && isset($_GET['PayerID'])) { - $_SESSION['token'] = $_GET['token']; - $_SESSION['PayerID'] = $_GET['PayerID']; - - //get details from PayPal - $result = $this->GetExpressCheckoutDetails($_SESSION['token']); - - //check response - if($result["ACK"] == "Success" || $result["ACK"] == "SuccessWithWarning") { - - $account_name = ($result["BUSINESS"]) ? $result["BUSINESS"] : $result["EMAIL"]; - - //set final amount - $_SESSION['final_amt'] = 0; - $_SESSION['store_count'] = 0; - - for ($i=0; $i<10; $i++) { - if (!isset($result['PAYMENTREQUEST_'.$i.'_AMT'])) { - continue; - } - $_SESSION['final_amt'] += $result['PAYMENTREQUEST_'.$i.'_AMT']; - $_SESSION['store_count']++; - } - - //print payment details - $content .= '

    ' . sprintf(__('Please confirm your final payment for this order totaling %s. It will be made via your "%s" PayPal account.', 'mp'), $mp->format_currency('', $_SESSION['final_amt']), $account_name) . '

    '; - - } else { //whoops, error - for ($i = 0; $i <= 5; $i++) { //print the first 5 errors - if (isset($result["L_ERRORCODE$i"])) - $error .= "
  • {$result["L_ERRORCODE$i"]} - {$result["L_SHORTMESSAGE$i"]} - {$result["L_LONGMESSAGE$i"]}
  • "; - } - $error = '
    '; - $content .= '
    ' . sprintf(__('There was a problem with your PayPal transaction. Please go back and try again.', 'mp'), mp_checkout_step_url('checkout')) . $error . '
    '; - } - - } else { - $content .= '
    ' . sprintf(__('Whoops, looks like you skipped a step! Please go back and try again.', 'mp'), mp_checkout_step_url('checkout')) . '
    '; - } - - return $content; } /** @@ -350,148 +266,86 @@ function confirm_payment_form($global_cart, $shipping_info) { * @param array $shipping_info. Contains shipping info and email in case you need it */ function process_payment($global_cart, $shipping_info) { - global $mp, $blog_id, $site_id, $switched_stack, $switched; + global $mp, $blog_id, $site_id, $switched_stack, $switched, $wpdb; $blog_id = (is_multisite()) ? $blog_id : 1; $current_blog_id = $blog_id; - if (!$mp->global_cart) + if (!$mp->global_cart){ $selected_cart[$blog_id] = $global_cart; - else + }else{ $selected_cart = $global_cart; + } - if (isset($_SESSION['token']) && isset($_SESSION['PayerID']) && isset($_SESSION['final_amt'])) { - //attempt the final payment - $result = $this->DoExpressCheckoutPayment($_SESSION['token'], $_SESSION['PayerID']); + if (isset($_SESSION['paymillToken'])){ + $_POST['paymillToken'] = $_SESSION['paymillToken']; + + $this->client = $this->getCurrentClient(); + // client retrieved, now we are ready to process the payment + if($this->client->getId() !== false && strlen($this->client->getId()) > 0){ + $this->order_id = $mp->generate_order_id(); + $this->order_desc = __('Order #','paymill').$this->order_id; + $this->cart = $selected_cart; + $this->total_complete = + $this->total = $this->paymill_getCartTotal($global_cart); + $this->currency = $this->paymill_getCurrency(); - //check response - if($result["ACK"] == "Success" || $result["ACK"] == "SuccessWithWarning") { + + // load subscription class + //$this->subscriptions = new paymill_subscriptions('marketpress'); + //$this->offers = $this->subscriptions->offerGetList(); + + // get the totals for pre authorization + //$this->getTotals(); + + // create payment object and preauthorization + require_once(PAYMILL_DIR.'lib/integration/payment.inc.php'); + $this->paymentClass = new paymill_payment($this->client->getId(),$this->total_complete,$this->currency); // create payment object, as it should be used for next processing instead of the token. + if($GLOBALS['paymill_loader']->paymill_errors->status()){ + $GLOBALS['paymill_loader']->paymill_errors->getErrors(); + return false; + } - //setup our payment details - $payment_info['gateway_public_name'] = $this->public_name; - $payment_info['gateway_private_name'] = $this->admin_name; - for ($i=0; $i<10; $i++) { - if (!isset($result['PAYMENTINFO_'.$i.'_PAYMENTTYPE'])) { - continue; - } - $payment_info['method'] = ($result["PAYMENTINFO_{$i}_PAYMENTTYPE"] == 'echeck') ? __('eCheck', 'mp') : __('PayPal balance, Credit Card, or Instant Transfer', 'mp'); - $payment_info['transaction_id'] = $result["PAYMENTINFO_{$i}_TRANSACTIONID"]; - - $timestamp = time();//strtotime($result["PAYMENTINFO_{$i}_ORDERTIME"]); - //setup status - switch ($result["PAYMENTINFO_{$i}_PAYMENTSTATUS"]) { - case 'Canceled-Reversal': - $status = __('A reversal has been canceled; for example, when you win a dispute and the funds for the reversal have been returned to you.', 'mp'); - $paid = true; - break; - case 'Expired': - $status = __('The authorization period for this payment has been reached.', 'mp'); - $paid = false; - break; - case 'Voided': - $status = __('An authorization for this transaction has been voided.', 'mp'); - $paid = false; - break; - case 'Failed': - $status = __('The payment has failed. This happens only if the payment was made from your customer\'s bank account.', 'mp'); - $paid = false; - break; - case 'Partially-Refunded': - $status = __('The payment has been partially refunded.', 'mp'); - $paid = true; - break; - case 'In-Progress': - $status = __('The transaction has not terminated, e.g. an authorization may be awaiting completion.', 'mp'); - $paid = false; - break; - case 'Completed': - $status = __('The payment has been completed, and the funds have been added successfully to your account balance.', 'mp'); - $paid = true; - break; - case 'Processed': - $status = __('A payment has been accepted.', 'mp'); - $paid = true; - break; - case 'Reversed': - $status = __('A payment was reversed due to a chargeback or other type of reversal. The funds have been removed from your account balance and returned to the buyer:', 'mp'); - $reverse_reasons = array( - 'none' => '', - 'chargeback' => __('A reversal has occurred on this transaction due to a chargeback by your customer.', 'mp'), - 'guarantee' => __('A reversal has occurred on this transaction due to your customer triggering a money-back guarantee.', 'mp'), - 'buyer-complaint' => __('A reversal has occurred on this transaction due to a complaint about the transaction from your customer.', 'mp'), - 'refund' => __('A reversal has occurred on this transaction because you have given the customer a refund.', 'mp'), - 'other' => __('A reversal has occurred on this transaction due to an unknown reason.', 'mp') - ); - $status .= '
    ' . $reverse_reasons[$result["PAYMENTINFO_{$i}_REASONCODE"]]; - $paid = false; - break; - case 'Refunded': - $status = __('You refunded the payment.', 'mp'); - $paid = false; - break; - case 'Denied': - $status = __('You denied the payment when it was marked as pending.', 'mp'); - $paid = false; - break; - case 'Pending': - $pending_str = array( - 'address' => __('The payment is pending because your customer did not include a confirmed shipping address and your Payment Receiving Preferences is set such that you want to manually accept or deny each of these payments. To change your preference, go to the Preferences section of your Profile.', 'mp'), - 'authorization' => __('The payment is pending because it has been authorized but not settled. You must capture the funds first.', 'mp'), - 'echeck' => __('The payment is pending because it was made by an eCheck that has not yet cleared.', 'mp'), - 'intl' => __('The payment is pending because you hold a non-U.S. account and do not have a withdrawal mechanism. You must manually accept or deny this payment from your Account Overview.', 'mp'), - 'multi-currency' => __('You do not have a balance in the currency sent, and you do not have your Payment Receiving Preferences set to automatically convert and accept this payment. You must manually accept or deny this payment.', 'mp'), - 'order' => __('The payment is pending because it is part of an order that has been authorized but not settled.', 'mp'), - 'paymentreview' => __('The payment is pending while it is being reviewed by PayPal for risk.', 'mp'), - 'unilateral' => __('The payment is pending because it was made to an email address that is not yet registered or confirmed.', 'mp'), - 'upgrade' => __('The payment is pending because it was made via credit card and you must upgrade your account to Business or Premier status in order to receive the funds. It can also mean that you have reached the monthly limit for transactions on your account.', 'mp'), - 'verify' => __('The payment is pending because you are not yet verified. You must verify your account before you can accept this payment.', 'mp'), - 'other' => __('The payment is pending for an unknown reason. For more information, contact PayPal customer service.', 'mp'), - '*' => '' - ); - $status = __('The payment is pending.', 'mp'); - $status .= '
    ' . $pending_str[$result["PAYMENTINFO_{$i}_PENDINGREASON"]]; - $paid = false; - break; - default: - // case: various error cases - $paid = false; - } - $status = $result["PAYMENTINFO_{$i}_PAYMENTSTATUS"] . ': '. $status; + // process subscriptions & products + if($this->processSubscriptions() && $this->processProducts()){ + // success + $timestamp = time(); + + //setup our payment details + $payment_info['gateway_public_name'] = $this->public_name; + $payment_info['gateway_private_name'] = $this->admin_name; + $payment_info['method'] = 'Paymill'; + $payment_info['transaction_id'] = $this->order_id; // todo: insert real paymill transaction id //status's are stored as an array with unix timestamp as key - $payment_info['status'] = array(); - $payment_info['status'][$timestamp] = $status; - $payment_info['currency'] = $result["PAYMENTINFO_{$i}_CURRENCYCODE"]; - $payment_info['total'] = $result["PAYMENTINFO_{$i}_AMT"]; - - $payment_info['note'] = $result["NOTE"]; //optional, only shown if gateway supports it - - //figure out blog_id of this payment to put the order into it - $unique_id = ($result["PAYMENTINFO_{$i}_PAYMENTREQUESTID"]) ? $result["PAYMENTINFO_{$i}_PAYMENTREQUESTID"] : $result["PAYMENTREQUEST_{$i}_PAYMENTREQUESTID"]; //paypal docs messed up, not sure which is valid return - @list($bid, $order_id) = explode(':', $unique_id); - - if (is_multisite()) - switch_to_blog($bid, true); + $payment_info['status'] = array(); + $payment_info['status'][$timestamp] = 'success'; + $payment_info['currency'] = $this->currency; + $payment_info['total'] = ($this->total_complete/100); + //$payment_info['note'] = $result["NOTE"]; //optional, only shown if gateway supports it //succesful payment, create our order now - $mp->create_order($_SESSION['mp_order'], $selected_cart[$bid], $shipping_info, $payment_info, $paid); - } - - if (is_multisite()) - switch_to_blog($current_blog_id, true); - - //success. Do nothing, it will take us to the confirmation page - } else { //whoops, error - - for ($i = 0; $i <= 5; $i++) { //print the first 5 errors - if (isset($result["L_ERRORCODE$i"])) - $error .= "
  • {$result["L_ERRORCODE$i"]} - {$result["L_SHORTMESSAGE$i"]} - ".stripslashes($result["L_LONGMESSAGE$i"])."
  • "; + // last parameter: paid = true / false + $mp->create_order($_SESSION['mp_order'], $global_cart, $shipping_info, $payment_info, true); + + if (is_multisite()){ + switch_to_blog($current_blog_id, true); + } + //success. Do nothing, it will take us to the confirmation page + + }else{ + if($GLOBALS['paymill_loader']->paymill_errors->status()){ + $GLOBALS['paymill_loader']->paymill_errors->getErrors(); + } + return false; } - $error = '
    '; - $mp->cart_checkout_error( sprintf(__('There was a problem finalizing your purchase with PayPal. Please go back and try again.', 'mp'), mp_checkout_step_url('checkout')) . $error ); + }else{ + $GLOBALS['paymill_loader']->paymill_errors->setError(__('There was an issue with adding you as client for the payment process.', 'paymill')); + return false; } } else { - $mp->cart_checkout_error( sprintf(__('There was a problem finalizing your purchase with PayPal. Please go back and try again.', 'mp'), mp_checkout_step_url('checkout')) ); + $GLOBALS['paymill_loader']->paymill_errors->setError(__('There was a problem finalizing your purchase with Paymill.', 'paymill')); + return false; } } @@ -521,20 +375,9 @@ function order_confirmation_email($msg, $order) { function order_confirmation_msg($content, $order) { global $mp; - if ($mp->global_cart) { + if ($mp->global_cart){ $content .= '

    ' . sprintf(__('Your order(s) for %s store(s) totaling %s were successful.', 'mp'), $_SESSION['store_count'], $mp->format_currency($this->currencyCode, $_SESSION['final_amt'])) . '

    '; /* TODO - create a list of sep store orders*/ - } else { - if ($order->post_status == 'order_received') { - $content .= '

    ' . sprintf(__('Your PayPal payment for this order totaling %s is not yet complete. Here is the latest status:', 'mp'), $mp->format_currency($order->mp_payment_info['currency'], $order->mp_payment_info['total'])) . '

    '; - $statuses = $order->mp_payment_info['status']; - krsort($statuses); //sort with latest status at the top - $status = reset($statuses); - $timestamp = key($statuses); - $content .= '

    ' . $mp->format_date($timestamp) . ': ' . esc_html($status) . '

    '; - } else { - $content .= '

    ' . sprintf(__('Your PayPal payment for this order totaling %s is complete. The PayPal transaction number is %s.', 'mp'), $mp->format_currency($order->mp_payment_info['currency'], $order->mp_payment_info['total']), $order->mp_payment_info['transaction_id']) . '

    '; - } } return $content; } @@ -562,140 +405,7 @@ function process_gateway_settings($settings) { * return the proper headers to your ipn sender. Exits after. */ function process_ipn_return() { - global $mp; - - // PayPal IPN handling code - if (isset($_POST['payment_status']) || isset($_POST['txn_type'])) { - - if ($mp->get_setting('gateways->paypal-express->mode') == 'sandbox') { - $domain = 'https://www.sandbox.paypal.com/cgi-bin/webscr'; - } else { - $domain = 'https://www.paypal.com/cgi-bin/webscr'; - } - - $req = 'cmd=_notify-validate'; - if (!isset($_POST)) $_POST = $HTTP_POST_VARS; - foreach ($_POST as $k => $v) { - if (get_magic_quotes_gpc()) $v = stripslashes($v); - $req .= '&' . $k . '=' . urlencode($v); - } - - $args['user-agent'] = "MarketPress/{$mp->version}: http://premium.wpmudev.org/project/e-commerce | PayPal Express Plugin/{$mp->version}"; - $args['body'] = $req; - $args['sslverify'] = false; - $args['timeout'] = 30; - - //use built in WP http class to work with most server setups - $response = wp_remote_post($domain, $args); - - //check results - if (is_wp_error($response) || wp_remote_retrieve_response_code($response) != 200 || $response['body'] != 'VERIFIED') { - header("HTTP/1.1 503 Service Unavailable"); - _e( 'There was a problem verifying the IPN string with PayPal. Please try again.', 'mp' ); - exit; - } - - // process PayPal response - switch ($_POST['payment_status']) { - - case 'Canceled-Reversal': - $status = __('A reversal has been canceled; for example, when you win a dispute and the funds for the reversal have been returned to you.', 'mp'); - $paid = true; - break; - - case 'Expired': - $status = __('The authorization period for this payment has been reached.', 'mp'); - $paid = false; - break; - - case 'Voided': - $status = __('An authorization for this transaction has been voided.', 'mp'); - $paid = false; - break; - - case 'Failed': - $status = __("The payment has failed. This happens only if the payment was made from your customer's bank account.", 'mp'); - $paid = false; - break; - - case 'Partially-Refunded': - $status = __('The payment has been partially refunded.', 'mp'); - $paid = true; - break; - - case 'In-Progress': - $status = __('The transaction has not terminated, e.g. an authorization may be awaiting completion.', 'mp'); - $paid = false; - break; - - case 'Completed': - $status = __('The payment has been completed, and the funds have been added successfully to your account balance.', 'mp'); - $paid = true; - break; - - case 'Processed': - $status = __('A payment has been accepted.', 'mp'); - $paid = true; - break; - - case 'Reversed': - $status = __('A payment was reversed due to a chargeback or other type of reversal. The funds have been removed from your account balance and returned to the buyer:', 'mp'); - $reverse_reasons = array( - 'none' => '', - 'chargeback' => __('A reversal has occurred on this transaction due to a chargeback by your customer.', 'mp'), - 'guarantee' => __('A reversal has occurred on this transaction due to your customer triggering a money-back guarantee.', 'mp'), - 'buyer-complaint' => __('A reversal has occurred on this transaction due to a complaint about the transaction from your customer.', 'mp'), - 'refund' => __('A reversal has occurred on this transaction because you have given the customer a refund.', 'mp'), - 'other' => __('A reversal has occurred on this transaction due to an unknown reason.', 'mp') - ); - $status .= '
    ' . $reverse_reasons[$result["PAYMENTINFO_0_REASONCODE"]]; - $paid = false; - break; - - case 'Refunded': - $status = __('You refunded the payment.', 'mp'); - $paid = false; - break; - - case 'Denied': - $status = __('You denied the payment when it was marked as pending.', 'mp'); - $paid = false; - break; - - case 'Pending': - $pending_str = array( - 'address' => __('The payment is pending because your customer did not include a confirmed shipping address and your Payment Receiving Preferences is set such that you want to manually accept or deny each of these payments. To change your preference, go to the Preferences section of your Profile.', 'mp'), - 'authorization' => __('The payment is pending because it has been authorized but not settled. You must capture the funds first.', 'mp'), - 'echeck' => __('The payment is pending because it was made by an eCheck that has not yet cleared.', 'mp'), - 'intl' => __('The payment is pending because you hold a non-U.S. account and do not have a withdrawal mechanism. You must manually accept or deny this payment from your Account Overview.', 'mp'), - 'multi-currency' => __('You do not have a balance in the currency sent, and you do not have your Payment Receiving Preferences set to automatically convert and accept this payment. You must manually accept or deny this payment.', 'mp'), - 'order' => __('The payment is pending because it is part of an order that has been authorized but not settled.', 'mp'), - 'paymentreview' => __('The payment is pending while it is being reviewed by PayPal for risk.', 'mp'), - 'unilateral' => __('The payment is pending because it was made to an email address that is not yet registered or confirmed.', 'mp'), - 'upgrade' => __('The payment is pending because it was made via credit card and you must upgrade your account to Business or Premier status in order to receive the funds. It can also mean that you have reached the monthly limit for transactions on your account.', 'mp'), - 'verify' => __('The payment is pending because you are not yet verified. You must verify your account before you can accept this payment.', 'mp'), - 'other' => __('The payment is pending for an unknown reason. For more information, contact PayPal customer service.', 'mp'), - '*' => '' - ); - $status = __('The payment is pending.', 'mp'); - $status .= '
    ' . $pending_str[$_POST["pending_reason"]]; - $paid = false; - break; - - default: - // case: various error cases - } - $status = $_POST['payment_status'] . ': '. $status; - - //record transaction - $mp->update_order_payment_status($_POST['invoice'], $status, $paid); - - } else { - // Did not find expected POST variables. Possible access attempt from a non PayPal site. - header('Status: 404 Not Found'); - echo 'Error: Missing POST variables. Identification is not possible.'; - exit; - } + } } diff --git a/lib/integration/shopplugin.inc.php b/lib/integration/shopplugin.inc.php index fdb7734..f73ebfd 100644 --- a/lib/integration/shopplugin.inc.php +++ b/lib/integration/shopplugin.inc.php @@ -24,6 +24,7 @@ class PaymillShopp extends GatewayFramework implements GatewayModule { function __construct(){ parent::__construct(); + load_paymill(); // this function-call can and should be used whenever working with Paymill API $GLOBALS['paymill_loader']->paymill_errors->setFunction('paymill_shopp_errorHandling'); if (!isset($this->settings['label'])){ @@ -167,7 +168,7 @@ private function processProducts(){ } function sale ($Event) { global $wpdb; - + $this->order_id = $Event->order; $this->order_desc = __('Order #','paymill').$this->order_id; $this->order = $this->Order; @@ -190,16 +191,21 @@ function sale ($Event) { // create payment object and preauthorization require_once(PAYMILL_DIR.'lib/integration/payment.inc.php'); + $this->paymentClass = new paymill_payment($this->client->getId(),$this->total_complete,$this->currency()); // create payment object, as it should be used for next processing instead of the token. if($GLOBALS['paymill_loader']->paymill_errors->status()){ - shopp_add_order_event($Purchase->id, 'auth-fail', array( - 'amount' => $orderTotals->total, // Amount to be authorized - 'gateway' => $Event->gateway, // Gateway handler name (module name from @subpackage) - 'message' => $GLOBALS['paymill_loader']->paymill_errors->getErrors(), 'paymill') - ); + $error = Shopp::__($GLOBALS['paymill_loader']->paymill_errors->getErrors()); + new ShoppError($error, 'paymill_error', SHOPP_TRXN_ERR); + return shopp_add_order_event($Event->order, $Event->type . '-fail', array( + 'amount' => $Event->amount, + 'error' => 0, + 'message' => $error, + 'gateway' => $this->module + )); + return false; } - + // process subscriptions & products if($this->processSubscriptions() && $this->processProducts()){ // success diff --git a/lib/integration/woocommerce.inc.php b/lib/integration/woocommerce.inc.php index 92299c1..0bdbc68 100644 --- a/lib/integration/woocommerce.inc.php +++ b/lib/integration/woocommerce.inc.php @@ -555,7 +555,7 @@ private function processProducts(){ global $wpdb; if($this->total > 0){ // make transaction - $GLOBALS['paymill_loader']->request_transaction->setAmount(round($this->total)); // e.g. "4200" for 42.00 EUR + $GLOBALS['paymill_loader']->request_transaction->setAmount(round($this->total,2)); // e.g. "4200" for 42.00 EUR $GLOBALS['paymill_loader']->request_transaction->setCurrency(get_woocommerce_currency()); if($this->paymentClass->getPreauthID() != false){ $GLOBALS['paymill_loader']->request_transaction->setPreauthorization($this->paymentClass->getPreauthID()); diff --git a/lib/js/paymill.js b/lib/js/paymill.js index 931cc01..87bf30d 100644 --- a/lib/js/paymill.js +++ b/lib/js/paymill.js @@ -1,4 +1,6 @@ jQuery(document).ready(function () { + var paymill_youshallpass = false; + if(typeof paymill_shop_name != 'undefined'){ if(paymill_shop_name == 'woocommerce' || jQuery('body').hasClass('woocommerce-checkout')){ jQuery('body').on('click', paymill_form_checkout_submit_id, function(event) { @@ -13,6 +15,15 @@ jQuery(document).ready(function () { } }); } + else if(paymill_shop_name == 'shopplugin'){ + jQuery('body').on('submit', paymill_form_checkout_id, function(event) { + if(paymill_youshallpass == false){ + event.preventDefault(); + jQuery(paymill_form_checkout_submit_id).hide(); + bridgePreparePayment(); + } + }); + } else if(paymill_shop_name != 'woocommerce'){ jQuery('body').on('click', paymill_form_checkout_submit_id, function(event) { event.preventDefault(); @@ -62,6 +73,7 @@ jQuery(document).ready(function () { // insert token into form var token = result.token; form.append(""); + paymill_youshallpass = true; form.submit(); } if(paymill_shop_name == 'shopplugin'){ @@ -90,7 +102,6 @@ jQuery(document).ready(function () { }, function (error, result) { if (error) { // shows error - alert(paymill_lang[error.apierror]); jQuery(".paymill_payment_errors").text(paymill_lang[error.apierror]); jQuery(paymill_form_checkout_submit_id).show(); } else { @@ -100,6 +111,7 @@ jQuery(document).ready(function () { // insert token into form var token = result.token; form.append(""); + paymill_youshallpass = true; form.submit(); } }); @@ -134,6 +146,7 @@ jQuery(document).ready(function () { // insert token into form var token = result.token; form.append(""); + paymill_youshallpass = true; form.submit(); } }); @@ -207,15 +220,15 @@ jQuery(document).ready(function () { decimalSymbol: paymill_lang.decimalSymbol, digitGroupSymbol: paymill_lang.digitGroupSymbol, symbol: ' '+paymill_lang.symbol, - negativeFormat: '%n%s', - positiveFormat: '%n%s' + negativeFormat: paymill_lang.currency_format, + positiveFormat: paymill_lang.currency_format }); jQuery('.paymill_price').formatCurrency({ decimalSymbol: paymill_lang.decimalSymbol, digitGroupSymbol: paymill_lang.digitGroupSymbol, symbol: ' '+paymill_lang.symbol, - negativeFormat: '%n%s', - positiveFormat: '%n%s' + negativeFormat: paymill_lang.currency_format, + positiveFormat: paymill_lang.currency_format }); function PaymillPayButtonCalcTotal(){ @@ -239,8 +252,8 @@ jQuery(document).ready(function () { decimalSymbol: paymill_lang.decimalSymbol, digitGroupSymbol: paymill_lang.digitGroupSymbol, symbol: ' '+paymill_lang.symbol, - negativeFormat: '%n%s', - positiveFormat: '%n%s' + negativeFormat: paymill_lang.currency_format, + positiveFormat: paymill_lang.currency_format }); } diff --git a/lib/scripts.inc.php b/lib/scripts.inc.php index 118bf53..1d70f63 100644 --- a/lib/scripts.inc.php +++ b/lib/scripts.inc.php @@ -50,6 +50,7 @@ function paymill_load_frontend_scripts(){ 'decimalSymbol' => esc_attr__($GLOBALS['paymill_settings']->paymill_pay_button_settings['number_decimal'], 'paymill'), 'digitGroupSymbol' => esc_attr__($GLOBALS['paymill_settings']->paymill_pay_button_settings['number_thousands'], 'paymill'), 'symbol' => esc_attr__($GLOBALS['paymill_settings']->paymill_pay_button_settings['currency'], 'paymill'), + 'currency_format' => esc_attr__($GLOBALS['paymill_settings']->paymill_pay_button_settings['currency_format'], 'paymill'), 'internal_server_error' => esc_attr__('Communication with PSP failed', 'paymill'), 'invalid_public_key' => esc_attr__('Invalid Public Key', 'paymill'), 'invalid_payment_data' => esc_attr__('not permitted for this method of payment, credit card type, currency or country', 'paymill'), diff --git a/lib/setup.inc.php b/lib/setup.inc.php index f2ea093..b96e1b4 100644 --- a/lib/setup.inc.php +++ b/lib/setup.inc.php @@ -161,6 +161,7 @@ function paymill_install(){ woocommerce_order_id int(11) NOT NULL, pay_button_order_id int(11) NOT NULL, shopplugin_order_id int(11) NOT NULL, + marketpress_order_id int(11) NOT NULL, UNIQUE KEY paymill_transaction_id (paymill_transaction_id));'; $sql .= 'CREATE TABLE '.$wpdb->prefix.'paymill_cache_offers ( diff --git a/lib/tpl/checkout_form.php b/lib/tpl/checkout_form.php index d297a37..b7eb08f 100644 --- a/lib/tpl/checkout_form.php +++ b/lib/tpl/checkout_form.php @@ -64,10 +64,10 @@
    -
    +
    -
    +