From eb0d04f3047277c17c48edefa24f48b837f5ade1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 7 Jun 2019 11:24:35 +0200 Subject: [PATCH 1/5] Code comment --- htdocs/stripe/class/stripe.class.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index 1d81e12da8c..de43c063922 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -242,7 +242,7 @@ class Stripe extends CommonObject * Warning. If a payment was tried and failed, a payment intent was created. * But if we change someting on object to pay (amount or other), reusing same payment intent is not allowed. * Recommanded solution is to recreate a new payment intent each time we need one (old one will be automatically closed after a delay), - * that's why i comment the part of code to retreive a payment intent with object id (never mind if we cumulate payment intent with old that will not be used) + * that's why i comment the part of code to retreive a payment intent with object id (never mind if we cumulate payment intent with old ones that will not be used) * * @param double $amount Amount * @param string $currency_code Currency code @@ -366,6 +366,7 @@ class Stripe extends CommonObject global $stripearrayofkeysbyenv; \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']); + // Note: If all data for payment intent are same than a previous on, even if we use 'create', Stripe will return ID of the old existing payment intent. if (empty($key)) { // If the Stripe connect account not set, we use common API usage $paymentintent = \Stripe\PaymentIntent::create($dataforintent, array("idempotency_key" => "$description")); //$paymentintent = \Stripe\PaymentIntent::create($dataforintent, array()); @@ -373,7 +374,7 @@ class Stripe extends CommonObject $paymentintent = \Stripe\PaymentIntent::create($dataforintent, array("idempotency_key" => "$description", "stripe_account" => $key)); //$paymentintent = \Stripe\PaymentIntent::create($dataforintent, array("stripe_account" => $key)); } - //var_dump($paymentintent); + //var_dump($paymentintent->id); // Store the payment intent if (is_object($object)) From dc479a5377eee3267a15ad2b11d2b6d7f2434467 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 7 Jun 2019 11:29:59 +0200 Subject: [PATCH 2/5] FIX Create stripe intent only if Stripe was selected. This reduce also duplicate code. FIX Free payment when using paymentintent architecture. --- htdocs/public/payment/newpayment.php | 214 +++++++++++---------------- 1 file changed, 90 insertions(+), 124 deletions(-) diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index 145df4f9e94..8c6753db54b 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -662,7 +662,7 @@ if ($action == 'charge' && ! empty($conf->stripe->enabled)) else { // TODO We can alse record the payment mode into llx_societe_rib with stripe $paymentintent->payment_method - // Note that with other Stripe architecture (using Charge API), the payment mode was not recorded, so it is not mandatory to do it here. + // Note that with other old Stripe architecture (using Charge API), the payment mode was not recorded, so it is not mandatory to do it here. //dol_syslog("Create payment_method for ".$paymentintent->payment_method, LOG_DEBUG, 0, '_stripe'); } } @@ -864,25 +864,6 @@ if (! $source) print ''; print ''."\n"; - if (! empty($conf->stripe->enabled) && $paymentmethod == 'stripe' && ! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) - { - require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; - - $service = 'StripeLive'; - $servicestatus = 1; - - if (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha')) - { - $service = 'StripeTest'; - $servicestatus = 0; - } - $stripe = new Stripe($db); - $stripeacc = $stripe->getStripeAccount($service); - $stripecu = null; - - $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, 'Stripe payment: '.$fulltag, $object, $stripecu, $stripeacc, $servicestatus); - if ($stripe->error) setEventMessages($stripe->error, null, 'errors'); - } // We do not add fields shipToName, shipToStreet, shipToCity, shipToState, shipToCountryCode, shipToZip, shipToStreet2, phoneNum // as they don't exists (buyer is unknown, tag is free). } @@ -974,26 +955,6 @@ if ($source == 'order') print ''; print ''."\n"; - if (! empty($conf->stripe->enabled) && $paymentmethod == 'stripe' && empty($order->billed) && ! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) - { - require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; - - $service = 'StripeLive'; - $servicestatus = 1; - - if (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha')) - { - $service = 'StripeTest'; - $servicestatus = 0; - } - $stripe = new Stripe($db); - $stripeacc = $stripe->getStripeAccount($service); - $stripecu = $stripe->customerStripe($order->thirdparty, $stripeacc, $servicestatus, 1); - - $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, 'Stripe payment: '.$fulltag.' ref='.$object->ref, $object, $stripecu, $stripeacc, $servicestatus); - if ($stripe->error) setEventMessages($stripe->error, null, 'errors'); - } - // Shipping address $shipToName=$order->thirdparty->name; $shipToStreet=$order->thirdparty->address; @@ -1121,25 +1082,6 @@ if ($source == 'invoice') print ''; print ''."\n"; - if (! empty($conf->stripe->enabled) && ($paymentmethod == 'stripe') && empty($object->paye) && ! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) - { - require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; - - $service = 'StripeLive'; - $servicestatus = 1; - if (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha')) - { - $service = 'StripeTest'; - $servicestatus = 0; - } - $stripe = new Stripe($db); - $stripeacc = $stripe->getStripeAccount($service); - $stripecu = $stripe->customerStripe($invoice->thirdparty, $stripeacc, $servicestatus, 1); - - $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, 'Stripe payment: '.$fulltag.' ref='.$object->ref, $object, $stripecu, $stripeacc, $servicestatus); - if ($stripe->error) setEventMessages($stripe->error, null, 'errors'); - } - // Shipping address $shipToName=$invoice->thirdparty->name; $shipToStreet=$invoice->thirdparty->address; @@ -1350,26 +1292,6 @@ if ($source == 'contractline') print ''; print ''."\n"; - if (! empty($conf->stripe->enabled) && $paymentmethod == 'stripe' && ! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) - { - require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; - - $service = 'StripeLive'; - $servicestatus = 1; - - if (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha')) - { - $service = 'StripeTest'; - $servicestatus = 0; - } - $stripe = new Stripe($db); - $stripeacc = $stripe->getStripeAccount($service); - $stripecu = null; - - $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, 'Stripe payment: '.$fulltag." ref=".$object->ref, $object, $stripecu, $stripeacc, $servicestatus); - if ($stripe->error) setEventMessages($stripe->error, null, 'errors'); - } - // Shipping address $shipToName=$contract->thirdparty->name; $shipToStreet=$contract->thirdparty->address; @@ -1536,26 +1458,6 @@ if ($source == 'membersubscription') print ''; print ''."\n"; - if (! empty($conf->stripe->enabled) && $paymentmethod == 'stripe' && ! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) - { - require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; - - $service = 'StripeLive'; - $servicestatus = 1; - - if (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha')) - { - $service = 'StripeTest'; - $servicestatus = 0; - } - $stripe = new Stripe($db); - $stripeacc = $stripe->getStripeAccount($service); - $stripecu = null; - - $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, 'Stripe payment: '.$fulltag." ref=".$object->ref, $object, $stripecu, $stripeacc, $servicestatus); - if ($stripe->error) setEventMessages($stripe->error, null, 'errors'); - } - // Shipping address $shipToName=$member->getFullName($langs); $shipToStreet=$member->address; @@ -1697,26 +1599,6 @@ if ($source == 'donation') print ''; print ''."\n"; - if (! empty($conf->stripe->enabled) && ($paymentmethod == 'stripe') && empty($object->paid) && ! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) - { - require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; - - $service = 'StripeLive'; - $servicestatus = 1; - - if (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha')) - { - $service = 'StripeTest'; - $servicestatus = 0; - } - $stripe = new Stripe($db); - $stripeacc = $stripe->getStripeAccount($service); - $stripecu = $stripe->customerStripe($don->thirdparty, $stripeacc, $servicestatus, 1); - - $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, 'Stripe payment: '.$fulltag." ref=".$object->ref, $object, $stripecu, $stripeacc, $servicestatus); - if ($stripe->error) setEventMessages($stripe->error, null, 'errors'); - } - // Shipping address $shipToName=$don->getFullName($langs); $shipToStreet=$don->address; @@ -1758,6 +1640,7 @@ print ''."\n"; print "\n"; +// Show all payment mode buttons (Stripe, Paypal, ...) if ($action != 'dopayment') { if ($found && ! $error) // We are in a management option and no error @@ -1833,7 +1716,7 @@ print '
'; // Add more content on page for some services -if (preg_match('/^dopayment/', $action)) +if (preg_match('/^dopayment/', $action)) // If we choosed/click on the payment mode { // Stripe @@ -1888,6 +1771,27 @@ if (preg_match('/^dopayment/', $action)) print ''; print ''; + if (! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) + { + require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; + + $service = 'StripeLive'; + $servicestatus = 1; + + if (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha')) + { + $service = 'StripeTest'; + $servicestatus = 0; + } + $stripe = new Stripe($db); + $stripeacc = $stripe->getStripeAccount($service); + $stripecu = null; + if (is_object($object) && is_object($object->thirdparty)) $stripecu = $stripe->customerStripe($object->thirdparty, $stripeacc, $servicestatus, 1); + + $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, 'Stripe payment: '.$fulltag.(is_object($object)?' ref='.$object->ref:''), $object, $stripecu, $stripeacc, $servicestatus); + if ($stripe->error) setEventMessages($stripe->error, null, 'errors'); + } + if (empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION) || ! empty($paymentintent)) { print ' @@ -1949,12 +1853,75 @@ if (preg_match('/^dopayment/', $action)) } else { + // JS Code for Stripe + print ''; print ''."\n"; // Code to ask the credit card. This use the default "API version". No way to force API version when using JS code. print ''."\n"; @@ -1862,21 +1865,46 @@ if (preg_match('/^dopayment/', $action)) // If we choosed/click on the payment if (! empty($conf->global->STRIPE_USE_NEW_CHECKOUT)) { - $sessionstripe = \Stripe\Checkout\Session::create([ - 'customer_email' => (GETPOST('email', 'alpha')?GETPOST('email', 'alpha'):''), - 'payment_method_types' => ['card'], - 'line_items' => [[ - 'name' => 'T-shirt', - 'description' => 'Stripe payment: '.$FULLTAG.' ref='.$ref, - //'images' => ['https://example.com/t-shirt.png'], - 'amount' => $amount, - 'currency' => $currency, - 'quantity' => 1, - ]], - 'success_url' => $urlok, - 'cancel_url' => $urlko, - ]); + $amountstripe = $amount; + // Correct the amount according to unit of currency + // See https://support.stripe.com/questions/which-zero-decimal-currencies-does-stripe-support + $arrayzerounitcurrency=array('BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'); + if (! in_array($currency, $arrayzerounitcurrency)) $amountstripe=$amountstripe * 100; + + try { + $arrayforcheckout = array( + 'payment_method_types' => array('card'), + 'line_items' => array(array( + 'name' => $langs->transnoentitiesnoconv("Payment").' '.$FULLTAG.' ref='.$ref, + 'description' => 'Stripe payment: '.$FULLTAG.' ref='.$ref, + 'amount' => $amountstripe, + 'currency' => $currency, + 'images' => array($urllogofull), + 'quantity' => 1, + )), + 'client_reference_id' => $FULLTAG, + 'success_url' => $urlok, + 'cancel_url' => $urlko, + ); + if ($stripecu) $arrayforcheckout['customer'] = $stripecu; + elseif (GETPOST('email', 'alpha') && isValidEmail(GETPOST('email', 'alpha'))) $arrayforcheckout['customer_email'] = GETPOST('email', 'alpha'); + $sessionstripe = \Stripe\Checkout\Session::create($arrayforcheckout); + + $remoteip = getUserRemoteIP(); + + // Save some data for the paymentok + $_SESSION["currencyCodeType"] = $currency; + $_SESSION["paymentType"] = ''; + $_SESSION["FinalPaymentAmt"] = $amount; + $_SESSION['ipaddress'] = ($remoteip?$remoteip:'unknown'); // Payer ip + $_SESSION['payerID'] = is_object($stripecu)?$stripecu->id:''; + $_SESSION['TRANSACTIONID'] = $sessionstripe->id; + } + catch(Exception $e) + { + print $e->getMessage(); + } ?> // Code for payment with option STRIPE_USE_NEW_CHECKOUT set diff --git a/htdocs/public/stripe/ipn.php b/htdocs/public/stripe/ipn.php index ca7db10f9d1..201d434e758 100644 --- a/htdocs/public/stripe/ipn.php +++ b/htdocs/public/stripe/ipn.php @@ -297,12 +297,18 @@ elseif ($event->type == 'customer.deleted') { $db->query($sql); $db->commit(); } -elseif ($event->type == 'payment_intent.succeeded') { - // TODO: Redirect to paymentok.php +elseif ($event->type == 'payment_intent.succeeded') { // Called when making payment with PaymentIntent method ($conf->global->STRIPE_USE_NEW_CHECKOUT is on). + // TODO: create fees + // TODO: Redirect to paymentok.php } elseif ($event->type == 'payment_intent.payment_failed') { // TODO: Redirect to paymentko.php } +elseif ($event->type == 'checkout.session.completed') // Called when making payment with new Checkout method ($conf->global->STRIPE_USE_NEW_CHECKOUT is on). +{ + // TODO: create fees + // TODO: Redirect to paymentok.php +} elseif ($event->type == 'charge.succeeded') { // TODO: create fees // TODO: Redirect to paymentok.php From 9314bb4667f3d198257ecb974e29c1d6a5bfda20 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 7 Jun 2019 13:07:19 +0200 Subject: [PATCH 4/5] Fix missing statement descriptor --- htdocs/public/payment/newpayment.php | 15 +++++++++++++++ htdocs/public/stripe/ipn.php | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index 93620e70c0e..32db0d99a08 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -1872,7 +1872,21 @@ if (preg_match('/^dopayment/', $action)) // If we choosed/click on the payment $arrayzerounitcurrency=array('BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'); if (! in_array($currency, $arrayzerounitcurrency)) $amountstripe=$amountstripe * 100; + $ipaddress=getUserRemoteIP(); + $metadata = array('dol_version'=>DOL_VERSION, 'dol_entity'=>$conf->entity, 'ipaddress'=>$ipaddress); + if (is_object($object)) + { + $metadata['dol_type'] = $object->element; + $metadata['dol_id'] = $object->id; + } + try { + $arrayforpaymentintent = array( + 'description'=>'Stripe payment: '.$FULLTAG.(is_object($object)?' ref='.$object->ref:''), + "metadata" => $metadata + ); + if ($TAG) $arrayforpaymentintent["statement_descriptor"] = dol_trunc($TAG, 10, 'right', 'UTF-8', 1); // 22 chars that appears on bank receipt (company + description) + $arrayforcheckout = array( 'payment_method_types' => array('card'), 'line_items' => array(array( @@ -1886,6 +1900,7 @@ if (preg_match('/^dopayment/', $action)) // If we choosed/click on the payment 'client_reference_id' => $FULLTAG, 'success_url' => $urlok, 'cancel_url' => $urlko, + 'payment_intent_data' => $arrayforpaymentintent ); if ($stripecu) $arrayforcheckout['customer'] = $stripecu; elseif (GETPOST('email', 'alpha') && isValidEmail(GETPOST('email', 'alpha'))) $arrayforcheckout['customer_email'] = GETPOST('email', 'alpha'); diff --git a/htdocs/public/stripe/ipn.php b/htdocs/public/stripe/ipn.php index 201d434e758..8795031592a 100644 --- a/htdocs/public/stripe/ipn.php +++ b/htdocs/public/stripe/ipn.php @@ -106,7 +106,7 @@ catch(\UnexpectedValueException $e) { $langs->load("main"); -// TODO Do we really need a user in setup just to have an name to fill an email topic when it is a technical system notification email +// TODO Do we really need a user in setup just to have a name to fill an email topic when it is a technical system notification email $user = new User($db); $user->fetch($conf->global->STRIPE_USER_ACCOUNT_FOR_ACTIONS); $user->getrights(); From 1520ca964606a58ce4e961fa52c29853c042af70 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 7 Jun 2019 13:51:53 +0200 Subject: [PATCH 5/5] Fix buttons for payments --- htdocs/langs/en_US/paybox.lang | 2 +- htdocs/langs/en_US/paypal.lang | 1 + htdocs/langs/en_US/stripe.lang | 2 +- htdocs/public/payment/newpayment.php | 18 ++++++++++++++---- htdocs/theme/eldy/global.inc.php | 7 ++++++- htdocs/theme/md/style.css.php | 5 ++++- 6 files changed, 27 insertions(+), 8 deletions(-) diff --git a/htdocs/langs/en_US/paybox.lang b/htdocs/langs/en_US/paybox.lang index d3c26c8e65a..a4eee3680af 100644 --- a/htdocs/langs/en_US/paybox.lang +++ b/htdocs/langs/en_US/paybox.lang @@ -10,7 +10,7 @@ ToComplete=To complete YourEMail=Email to receive payment confirmation Creditor=Creditor PaymentCode=Payment code -PayBoxDoPayment=Pay with Credit or Debit Card (Paybox) +PayBoxDoPayment=Pay with Paybox ToPay=Do payment YouWillBeRedirectedOnPayBox=You will be redirected on secured Paybox page to input you credit card information Continue=Next diff --git a/htdocs/langs/en_US/paypal.lang b/htdocs/langs/en_US/paypal.lang index 1db01a59012..5eb5f389445 100644 --- a/htdocs/langs/en_US/paypal.lang +++ b/htdocs/langs/en_US/paypal.lang @@ -33,3 +33,4 @@ PostActionAfterPayment=Post actions after payments ARollbackWasPerformedOnPostActions=A rollback was performed on all Post actions. You must complete post actions manually if they are necessary. ValidationOfPaymentFailed=Validation of payment has failed CardOwner=Card holder +PayPalBalance=Paypal credit diff --git a/htdocs/langs/en_US/stripe.lang b/htdocs/langs/en_US/stripe.lang index 1eb0a649a74..91d1f5a54c5 100644 --- a/htdocs/langs/en_US/stripe.lang +++ b/htdocs/langs/en_US/stripe.lang @@ -12,7 +12,7 @@ YourEMail=Email to receive payment confirmation STRIPE_PAYONLINE_SENDEMAIL=Email notification after a payment attempt (success or fail) Creditor=Creditor PaymentCode=Payment code -StripeDoPayment=Pay with Credit or Debit Card (Stripe) +StripeDoPayment=Pay with Stripe YouWillBeRedirectedOnStripe=You will be redirected on secured Stripe page to input you credit card information Continue=Next ToOfferALinkForOnlinePayment=URL for %s payment diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index 32db0d99a08..90646ef9b41 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -1670,27 +1670,37 @@ if ($action != 'dopayment') if ((empty($paymentmethod) || $paymentmethod == 'paybox') && ! empty($conf->paybox->enabled)) { // If STRIPE_PICTO_FOR_PAYMENT is 'cb' we show a picto of a crdit card instead of paybox - print '
'; + print '
'; + print '
'; + print ''.$langs->trans("CreditOrDebitCard").''; + print '
'; } if ((empty($paymentmethod) || $paymentmethod == 'stripe') && ! empty($conf->stripe->enabled)) { // If STRIPE_PICTO_FOR_PAYMENT is 'cb' we show a picto of a crdit card instead of stripe - print '
'; + print '
'; + print '
'; + print ''.$langs->trans("CreditOrDebitCard").''; + print '
'; } if ((empty($paymentmethod) || $paymentmethod == 'paypal') && ! empty($conf->paypal->enabled)) { if (empty($conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY)) $conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY='integral'; + print '
'; if ($conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY == 'integral') { - print '
'; + print '
'; + print ''.$langs->trans("CreditOrDebitCard").' - '; + print ''.$langs->trans("PayPalBalance").''; } if ($conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY == 'paypalonly') { - print '
'; + //print '
'.$langs->trans("PaypalAccount").'">'; } + print '
'; } } } diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 70496d8689a..e5e68e59c48 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -133,7 +133,7 @@ input.buttongen { vertical-align: middle; } input.buttonpayment, button.buttonpayment, div.buttonpayment { - min-width: 320px; + min-width: 290px; margin-bottom: 15px; background-image: none; line-height: 24px; @@ -147,6 +147,11 @@ input.buttonpayment, button.buttonpayment, div.buttonpayment { color: #fff; border-radius: 4px; } +.buttonpaymentsmall { + font-size: 0.65em; + padding-left: 5px; + padding-right: 5px; +} div.buttonpayment input { background-color: unset; color: #fff; diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 98618800e39..752f60541d1 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -353,8 +353,11 @@ input.buttongen { vertical-align: middle; } input.buttonpayment, button.buttonpayment, div.buttonpayment { - min-width: 320px; + min-width: 290px; margin-bottom: 15px; + margin-top: 0; + margin-left: 5px; + margin-right: 5px; background-image: none; line-height: 24px; padding: 8px;